blob: 9c5d37d9c79a3173e228d83a8a9a7a607e942192 [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
Matthew Wilcox349d2c42007-09-09 08:56:34 -060066 * 6. Use scsi_transport_spi
67 * 7. advansys_info is not safe against multiple simultaneous callers
68 * 8. Kill boardp->id
69 * 9. Add module_param to override ISA/VLB ioport array
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 */
71#warning this driver is still not properly converted to the DMA API
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073/* Enable driver /proc statistics. */
74#define ADVANSYS_STATS
75
76/* Enable driver tracing. */
77/* #define ADVANSYS_DEBUG */
78
Linus Torvalds1da177e2005-04-16 15:20:36 -070079/*
80 * --- Asc Library Constants and Macros
81 */
82
83#define ASC_LIB_VERSION_MAJOR 1
84#define ASC_LIB_VERSION_MINOR 24
85#define ASC_LIB_SERIAL_NUMBER 123
86
87/*
88 * Portable Data Types
89 *
90 * Any instance where a 32-bit long or pointer type is assumed
91 * for precision or HW defined structures, the following define
92 * types must be used. In Linux the char, short, and int types
93 * are all consistent at 8, 16, and 32 bits respectively. Pointers
94 * and long types are 64 bits on Alpha and UltraSPARC.
95 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040096#define ASC_PADDR __u32 /* Physical/Bus address data type. */
97#define ASC_VADDR __u32 /* Virtual address data type. */
98#define ASC_DCNT __u32 /* Unsigned Data count type. */
99#define ASC_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
101/*
102 * These macros are used to convert a virtual address to a
103 * 32-bit value. This currently can be used on Linux Alpha
104 * which uses 64-bit virtual address but a 32-bit bus address.
105 * This is likely to break in the future, but doing this now
106 * will give us time to change the HW and FW to handle 64-bit
107 * addresses.
108 */
109#define ASC_VADDR_TO_U32 virt_to_bus
110#define ASC_U32_TO_VADDR bus_to_virt
111
112typedef unsigned char uchar;
113
114#ifndef TRUE
115#define TRUE (1)
116#endif
117#ifndef FALSE
118#define FALSE (0)
119#endif
120
121#define EOF (-1)
122#define ERR (-1)
123#define UW_ERR (uint)(0xFFFF)
124#define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126#define ASC_DVCLIB_CALL_DONE (1)
127#define ASC_DVCLIB_CALL_FAILED (0)
128#define ASC_DVCLIB_CALL_ERROR (-1)
129
Dave Jones2672ea82006-08-02 17:11:49 -0400130#define PCI_VENDOR_ID_ASP 0x10cd
131#define PCI_DEVICE_ID_ASP_1200A 0x1100
132#define PCI_DEVICE_ID_ASP_ABP940 0x1200
133#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
134#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
135#define PCI_DEVICE_ID_38C0800_REV1 0x2500
136#define PCI_DEVICE_ID_38C1600_REV1 0x2700
137
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138/*
139 * Enable CC_VERY_LONG_SG_LIST to support up to 64K element SG lists.
140 * The SRB structure will have to be changed and the ASC_SRB2SCSIQ()
141 * macro re-defined to be able to obtain a ASC_SCSI_Q pointer from the
142 * SRB structure.
143 */
144#define CC_VERY_LONG_SG_LIST 0
145#define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr)
146
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400147#define PortAddr unsigned short /* port address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148#define inp(port) inb(port)
149#define outp(port, byte) outb((byte), (port))
150
151#define inpw(port) inw(port)
152#define outpw(port, word) outw((word), (port))
153
154#define ASC_MAX_SG_QUEUE 7
155#define ASC_MAX_SG_LIST 255
156
157#define ASC_CS_TYPE unsigned short
158
159#define ASC_IS_ISA (0x0001)
160#define ASC_IS_ISAPNP (0x0081)
161#define ASC_IS_EISA (0x0002)
162#define ASC_IS_PCI (0x0004)
163#define ASC_IS_PCI_ULTRA (0x0104)
164#define ASC_IS_PCMCIA (0x0008)
165#define ASC_IS_MCA (0x0020)
166#define ASC_IS_VL (0x0040)
167#define ASC_ISA_PNP_PORT_ADDR (0x279)
168#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800)
169#define ASC_IS_WIDESCSI_16 (0x0100)
170#define ASC_IS_WIDESCSI_32 (0x0200)
171#define ASC_IS_BIG_ENDIAN (0x8000)
172#define ASC_CHIP_MIN_VER_VL (0x01)
173#define ASC_CHIP_MAX_VER_VL (0x07)
174#define ASC_CHIP_MIN_VER_PCI (0x09)
175#define ASC_CHIP_MAX_VER_PCI (0x0F)
176#define ASC_CHIP_VER_PCI_BIT (0x08)
177#define ASC_CHIP_MIN_VER_ISA (0x11)
178#define ASC_CHIP_MIN_VER_ISA_PNP (0x21)
179#define ASC_CHIP_MAX_VER_ISA (0x27)
180#define ASC_CHIP_VER_ISA_BIT (0x30)
181#define ASC_CHIP_VER_ISAPNP_BIT (0x20)
182#define ASC_CHIP_VER_ASYN_BUG (0x21)
183#define ASC_CHIP_VER_PCI 0x08
184#define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02)
185#define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03)
186#define ASC_CHIP_MIN_VER_EISA (0x41)
187#define ASC_CHIP_MAX_VER_EISA (0x47)
188#define ASC_CHIP_VER_EISA_BIT (0x40)
189#define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3)
190#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21
191#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A
192#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL)
193#define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL)
194#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL)
195#define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL)
196#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL)
197#define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL)
198#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL)
199#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL)
200
201#define ASC_SCSI_ID_BITS 3
202#define ASC_SCSI_TIX_TYPE uchar
203#define ASC_ALL_DEVICE_BIT_SET 0xFF
204#define ASC_SCSI_BIT_ID_TYPE uchar
205#define ASC_MAX_TID 7
206#define ASC_MAX_LUN 7
207#define ASC_SCSI_WIDTH_BIT_SET 0xFF
208#define ASC_MAX_SENSE_LEN 32
209#define ASC_MIN_SENSE_LEN 14
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210#define ASC_SCSI_RESET_HOLD_TIME_US 60
211
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212/*
Matthew Wilcoxf05ec592007-09-09 08:56:36 -0600213 * Narrow boards only support 12-byte commands, while wide boards
214 * extend to 16-byte commands.
215 */
216#define ASC_MAX_CDB_LEN 12
217#define ADV_MAX_CDB_LEN 16
218
219/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data)
221 * and CmdDt (Command Support Data) field bit definitions.
222 */
223#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3
224#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2
225#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1
226#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0
227
228#define ASC_SCSIDIR_NOCHK 0x00
229#define ASC_SCSIDIR_T2H 0x08
230#define ASC_SCSIDIR_H2T 0x10
231#define ASC_SCSIDIR_NODATA 0x18
232#define SCSI_ASC_NOMEDIA 0x3A
233#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4))
234#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F))
235#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13))
236#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237#define MS_SDTR_LEN 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238#define MS_WDTR_LEN 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
240#define ASC_SG_LIST_PER_Q 7
241#define QS_FREE 0x00
242#define QS_READY 0x01
243#define QS_DISC1 0x02
244#define QS_DISC2 0x04
245#define QS_BUSY 0x08
246#define QS_ABORTED 0x40
247#define QS_DONE 0x80
248#define QC_NO_CALLBACK 0x01
249#define QC_SG_SWAP_QUEUE 0x02
250#define QC_SG_HEAD 0x04
251#define QC_DATA_IN 0x08
252#define QC_DATA_OUT 0x10
253#define QC_URGENT 0x20
254#define QC_MSG_OUT 0x40
255#define QC_REQ_SENSE 0x80
256#define QCSG_SG_XFER_LIST 0x02
257#define QCSG_SG_XFER_MORE 0x04
258#define QCSG_SG_XFER_END 0x08
259#define QD_IN_PROGRESS 0x00
260#define QD_NO_ERROR 0x01
261#define QD_ABORTED_BY_HOST 0x02
262#define QD_WITH_ERROR 0x04
263#define QD_INVALID_REQUEST 0x80
264#define QD_INVALID_HOST_NUM 0x81
265#define QD_INVALID_DEVICE 0x82
266#define QD_ERR_INTERNAL 0xFF
267#define QHSTA_NO_ERROR 0x00
268#define QHSTA_M_SEL_TIMEOUT 0x11
269#define QHSTA_M_DATA_OVER_RUN 0x12
270#define QHSTA_M_DATA_UNDER_RUN 0x12
271#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
272#define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14
273#define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21
274#define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22
275#define QHSTA_D_HOST_ABORT_FAILED 0x23
276#define QHSTA_D_EXE_SCSI_Q_FAILED 0x24
277#define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25
278#define QHSTA_D_ASPI_NO_BUF_POOL 0x26
279#define QHSTA_M_WTM_TIMEOUT 0x41
280#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
281#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
282#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
283#define QHSTA_M_TARGET_STATUS_BUSY 0x45
284#define QHSTA_M_BAD_TAG_CODE 0x46
285#define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47
286#define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48
287#define QHSTA_D_LRAM_CMP_ERROR 0x81
288#define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1
289#define ASC_FLAG_SCSIQ_REQ 0x01
290#define ASC_FLAG_BIOS_SCSIQ_REQ 0x02
291#define ASC_FLAG_BIOS_ASYNC_IO 0x04
292#define ASC_FLAG_SRB_LINEAR_ADDR 0x08
293#define ASC_FLAG_WIN16 0x10
294#define ASC_FLAG_WIN32 0x20
295#define ASC_FLAG_ISA_OVER_16MB 0x40
296#define ASC_FLAG_DOS_VM_CALLBACK 0x80
297#define ASC_TAG_FLAG_EXTRA_BYTES 0x10
298#define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04
299#define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08
300#define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40
301#define ASC_SCSIQ_CPY_BEG 4
302#define ASC_SCSIQ_SGHD_CPY_BEG 2
303#define ASC_SCSIQ_B_FWD 0
304#define ASC_SCSIQ_B_BWD 1
305#define ASC_SCSIQ_B_STATUS 2
306#define ASC_SCSIQ_B_QNO 3
307#define ASC_SCSIQ_B_CNTL 4
308#define ASC_SCSIQ_B_SG_QUEUE_CNT 5
309#define ASC_SCSIQ_D_DATA_ADDR 8
310#define ASC_SCSIQ_D_DATA_CNT 12
311#define ASC_SCSIQ_B_SENSE_LEN 20
312#define ASC_SCSIQ_DONE_INFO_BEG 22
313#define ASC_SCSIQ_D_SRBPTR 22
314#define ASC_SCSIQ_B_TARGET_IX 26
315#define ASC_SCSIQ_B_CDB_LEN 28
316#define ASC_SCSIQ_B_TAG_CODE 29
317#define ASC_SCSIQ_W_VM_ID 30
318#define ASC_SCSIQ_DONE_STATUS 32
319#define ASC_SCSIQ_HOST_STATUS 33
320#define ASC_SCSIQ_SCSI_STATUS 34
321#define ASC_SCSIQ_CDB_BEG 36
322#define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56
323#define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60
324#define ASC_SCSIQ_B_FIRST_SG_WK_QP 48
325#define ASC_SCSIQ_B_SG_WK_QP 49
326#define ASC_SCSIQ_B_SG_WK_IX 50
327#define ASC_SCSIQ_W_ALT_DC1 52
328#define ASC_SCSIQ_B_LIST_CNT 6
329#define ASC_SCSIQ_B_CUR_LIST_CNT 7
330#define ASC_SGQ_B_SG_CNTL 4
331#define ASC_SGQ_B_SG_HEAD_QP 5
332#define ASC_SGQ_B_SG_LIST_CNT 6
333#define ASC_SGQ_B_SG_CUR_LIST_CNT 7
334#define ASC_SGQ_LIST_BEG 8
335#define ASC_DEF_SCSI1_QNG 4
336#define ASC_MAX_SCSI1_QNG 4
337#define ASC_DEF_SCSI2_QNG 16
338#define ASC_MAX_SCSI2_QNG 32
339#define ASC_TAG_CODE_MASK 0x23
340#define ASC_STOP_REQ_RISC_STOP 0x01
341#define ASC_STOP_ACK_RISC_STOP 0x03
342#define ASC_STOP_CLEAN_UP_BUSY_Q 0x10
343#define ASC_STOP_CLEAN_UP_DISC_Q 0x20
344#define ASC_STOP_HOST_REQ_RISC_HALT 0x40
345#define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS))
346#define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid))
347#define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID))
348#define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID)
349#define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID)
350#define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN)
351#define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6))
352
353typedef struct asc_scsiq_1 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400354 uchar status;
355 uchar q_no;
356 uchar cntl;
357 uchar sg_queue_cnt;
358 uchar target_id;
359 uchar target_lun;
360 ASC_PADDR data_addr;
361 ASC_DCNT data_cnt;
362 ASC_PADDR sense_addr;
363 uchar sense_len;
364 uchar extra_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365} ASC_SCSIQ_1;
366
367typedef struct asc_scsiq_2 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400368 ASC_VADDR srb_ptr;
369 uchar target_ix;
370 uchar flag;
371 uchar cdb_len;
372 uchar tag_code;
373 ushort vm_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374} ASC_SCSIQ_2;
375
376typedef struct asc_scsiq_3 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400377 uchar done_stat;
378 uchar host_stat;
379 uchar scsi_stat;
380 uchar scsi_msg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381} ASC_SCSIQ_3;
382
383typedef struct asc_scsiq_4 {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400384 uchar cdb[ASC_MAX_CDB_LEN];
385 uchar y_first_sg_list_qp;
386 uchar y_working_sg_qp;
387 uchar y_working_sg_ix;
388 uchar y_res;
389 ushort x_req_count;
390 ushort x_reconnect_rtn;
391 ASC_PADDR x_saved_data_addr;
392 ASC_DCNT x_saved_data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393} ASC_SCSIQ_4;
394
395typedef struct asc_q_done_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400396 ASC_SCSIQ_2 d2;
397 ASC_SCSIQ_3 d3;
398 uchar q_status;
399 uchar q_no;
400 uchar cntl;
401 uchar sense_len;
402 uchar extra_bytes;
403 uchar res;
404 ASC_DCNT remain_bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405} ASC_QDONE_INFO;
406
407typedef struct asc_sg_list {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400408 ASC_PADDR addr;
409 ASC_DCNT bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410} ASC_SG_LIST;
411
412typedef struct asc_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400413 ushort entry_cnt;
414 ushort queue_cnt;
415 ushort entry_to_copy;
416 ushort res;
417 ASC_SG_LIST sg_list[ASC_MAX_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418} ASC_SG_HEAD;
419
420#define ASC_MIN_SG_LIST 2
421
422typedef struct asc_min_sg_head {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400423 ushort entry_cnt;
424 ushort queue_cnt;
425 ushort entry_to_copy;
426 ushort res;
427 ASC_SG_LIST sg_list[ASC_MIN_SG_LIST];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428} ASC_MIN_SG_HEAD;
429
430#define QCX_SORT (0x0001)
431#define QCX_COALEASE (0x0002)
432
433typedef struct asc_scsi_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400434 ASC_SCSIQ_1 q1;
435 ASC_SCSIQ_2 q2;
436 uchar *cdbptr;
437 ASC_SG_HEAD *sg_head;
438 ushort remain_sg_entry_cnt;
439 ushort next_sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440} ASC_SCSI_Q;
441
442typedef struct asc_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400443 ASC_SCSIQ_1 r1;
444 ASC_SCSIQ_2 r2;
445 uchar *cdbptr;
446 ASC_SG_HEAD *sg_head;
447 uchar *sense_ptr;
448 ASC_SCSIQ_3 r3;
449 uchar cdb[ASC_MAX_CDB_LEN];
450 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451} ASC_SCSI_REQ_Q;
452
453typedef struct asc_scsi_bios_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400454 ASC_SCSIQ_1 r1;
455 ASC_SCSIQ_2 r2;
456 uchar *cdbptr;
457 ASC_SG_HEAD *sg_head;
458 uchar *sense_ptr;
459 ASC_SCSIQ_3 r3;
460 uchar cdb[ASC_MAX_CDB_LEN];
461 uchar sense[ASC_MIN_SENSE_LEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462} ASC_SCSI_BIOS_REQ_Q;
463
464typedef struct asc_risc_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400465 uchar fwd;
466 uchar bwd;
467 ASC_SCSIQ_1 i1;
468 ASC_SCSIQ_2 i2;
469 ASC_SCSIQ_3 i3;
470 ASC_SCSIQ_4 i4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471} ASC_RISC_Q;
472
473typedef struct asc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400474 uchar seq_no;
475 uchar q_no;
476 uchar cntl;
477 uchar sg_head_qp;
478 uchar sg_list_cnt;
479 uchar sg_cur_list_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480} ASC_SG_LIST_Q;
481
482typedef struct asc_risc_sg_list_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400483 uchar fwd;
484 uchar bwd;
485 ASC_SG_LIST_Q sg;
486 ASC_SG_LIST sg_list[7];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487} ASC_RISC_SG_LIST_Q;
488
489#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL
490#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024
491#define ASCQ_ERR_NO_ERROR 0
492#define ASCQ_ERR_IO_NOT_FOUND 1
493#define ASCQ_ERR_LOCAL_MEM 2
494#define ASCQ_ERR_CHKSUM 3
495#define ASCQ_ERR_START_CHIP 4
496#define ASCQ_ERR_INT_TARGET_ID 5
497#define ASCQ_ERR_INT_LOCAL_MEM 6
498#define ASCQ_ERR_HALT_RISC 7
499#define ASCQ_ERR_GET_ASPI_ENTRY 8
500#define ASCQ_ERR_CLOSE_ASPI 9
501#define ASCQ_ERR_HOST_INQUIRY 0x0A
502#define ASCQ_ERR_SAVED_SRB_BAD 0x0B
503#define ASCQ_ERR_QCNTL_SG_LIST 0x0C
504#define ASCQ_ERR_Q_STATUS 0x0D
505#define ASCQ_ERR_WR_SCSIQ 0x0E
506#define ASCQ_ERR_PC_ADDR 0x0F
507#define ASCQ_ERR_SYN_OFFSET 0x10
508#define ASCQ_ERR_SYN_XFER_TIME 0x11
509#define ASCQ_ERR_LOCK_DMA 0x12
510#define ASCQ_ERR_UNLOCK_DMA 0x13
511#define ASCQ_ERR_VDS_CHK_INSTALL 0x14
512#define ASCQ_ERR_MICRO_CODE_HALT 0x15
513#define ASCQ_ERR_SET_LRAM_ADDR 0x16
514#define ASCQ_ERR_CUR_QNG 0x17
515#define ASCQ_ERR_SG_Q_LINKS 0x18
516#define ASCQ_ERR_SCSIQ_PTR 0x19
517#define ASCQ_ERR_ISR_RE_ENTRY 0x1A
518#define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B
519#define ASCQ_ERR_ISR_ON_CRITICAL 0x1C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520
521/*
522 * Warning code values are set in ASC_DVC_VAR 'warn_code'.
523 */
524#define ASC_WARN_NO_ERROR 0x0000
525#define ASC_WARN_IO_PORT_ROTATE 0x0001
526#define ASC_WARN_EEPROM_CHKSUM 0x0002
527#define ASC_WARN_IRQ_MODIFIED 0x0004
528#define ASC_WARN_AUTO_CONFIG 0x0008
529#define ASC_WARN_CMD_QNG_CONFLICT 0x0010
530#define ASC_WARN_EEPROM_RECOVER 0x0020
531#define ASC_WARN_CFG_MSW_RECOVER 0x0040
532#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080
533
534/*
535 * Error code values are set in ASC_DVC_VAR 'err_code'.
536 */
537#define ASC_IERR_WRITE_EEPROM 0x0001
538#define ASC_IERR_MCODE_CHKSUM 0x0002
539#define ASC_IERR_SET_PC_ADDR 0x0004
540#define ASC_IERR_START_STOP_CHIP 0x0008
541#define ASC_IERR_IRQ_NO 0x0010
542#define ASC_IERR_SET_IRQ_NO 0x0020
543#define ASC_IERR_CHIP_VERSION 0x0040
544#define ASC_IERR_SET_SCSI_ID 0x0080
545#define ASC_IERR_GET_PHY_ADDR 0x0100
546#define ASC_IERR_BAD_SIGNATURE 0x0200
547#define ASC_IERR_NO_BUS_TYPE 0x0400
548#define ASC_IERR_SCAM 0x0800
549#define ASC_IERR_SET_SDTR 0x1000
550#define ASC_IERR_RW_LRAM 0x8000
551
552#define ASC_DEF_IRQ_NO 10
553#define ASC_MAX_IRQ_NO 15
554#define ASC_MIN_IRQ_NO 10
555#define ASC_MIN_REMAIN_Q (0x02)
556#define ASC_DEF_MAX_TOTAL_QNG (0xF0)
557#define ASC_MIN_TAG_Q_PER_DVC (0x04)
558#define ASC_DEF_TAG_Q_PER_DVC (0x04)
559#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q
560#define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q))
561#define ASC_MAX_TOTAL_QNG 240
562#define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16
563#define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8
564#define ASC_MAX_PCI_INRAM_TOTAL_QNG 20
565#define ASC_MAX_INRAM_TAG_QNG 16
566#define ASC_IOADR_TABLE_MAX_IX 11
567#define ASC_IOADR_GAP 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568#define ASC_LIB_SCSIQ_WK_SP 256
569#define ASC_MAX_SYN_XFER_NO 16
570#define ASC_SYN_MAX_OFFSET 0x0F
571#define ASC_DEF_SDTR_OFFSET 0x0F
572#define ASC_DEF_SDTR_INDEX 0x00
573#define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02
574#define SYN_XFER_NS_0 25
575#define SYN_XFER_NS_1 30
576#define SYN_XFER_NS_2 35
577#define SYN_XFER_NS_3 40
578#define SYN_XFER_NS_4 50
579#define SYN_XFER_NS_5 60
580#define SYN_XFER_NS_6 70
581#define SYN_XFER_NS_7 85
582#define SYN_ULTRA_XFER_NS_0 12
583#define SYN_ULTRA_XFER_NS_1 19
584#define SYN_ULTRA_XFER_NS_2 25
585#define SYN_ULTRA_XFER_NS_3 32
586#define SYN_ULTRA_XFER_NS_4 38
587#define SYN_ULTRA_XFER_NS_5 44
588#define SYN_ULTRA_XFER_NS_6 50
589#define SYN_ULTRA_XFER_NS_7 57
590#define SYN_ULTRA_XFER_NS_8 63
591#define SYN_ULTRA_XFER_NS_9 69
592#define SYN_ULTRA_XFER_NS_10 75
593#define SYN_ULTRA_XFER_NS_11 82
594#define SYN_ULTRA_XFER_NS_12 88
595#define SYN_ULTRA_XFER_NS_13 94
596#define SYN_ULTRA_XFER_NS_14 100
597#define SYN_ULTRA_XFER_NS_15 107
598
599typedef struct ext_msg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400600 uchar msg_type;
601 uchar msg_len;
602 uchar msg_req;
603 union {
604 struct {
605 uchar sdtr_xfer_period;
606 uchar sdtr_req_ack_offset;
607 } sdtr;
608 struct {
609 uchar wdtr_width;
610 } wdtr;
611 struct {
612 uchar mdp_b3;
613 uchar mdp_b2;
614 uchar mdp_b1;
615 uchar mdp_b0;
616 } mdp;
617 } u_ext_msg;
618 uchar res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619} EXT_MSG;
620
621#define xfer_period u_ext_msg.sdtr.sdtr_xfer_period
622#define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset
623#define wdtr_width u_ext_msg.wdtr.wdtr_width
624#define mdp_b3 u_ext_msg.mdp_b3
625#define mdp_b2 u_ext_msg.mdp_b2
626#define mdp_b1 u_ext_msg.mdp_b1
627#define mdp_b0 u_ext_msg.mdp_b0
628
629typedef struct asc_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400630 ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
631 ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
632 ASC_SCSI_BIT_ID_TYPE disc_enable;
633 ASC_SCSI_BIT_ID_TYPE sdtr_enable;
634 uchar chip_scsi_id;
635 uchar isa_dma_speed;
636 uchar isa_dma_channel;
637 uchar chip_version;
638 ushort lib_serial_no;
639 ushort lib_version;
640 ushort mcode_date;
641 ushort mcode_version;
642 uchar max_tag_qng[ASC_MAX_TID + 1];
643 uchar *overrun_buf;
644 uchar sdtr_period_offset[ASC_MAX_TID + 1];
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400645 uchar adapter_info[6];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646} ASC_DVC_CFG;
647
648#define ASC_DEF_DVC_CNTL 0xFFFF
649#define ASC_DEF_CHIP_SCSI_ID 7
650#define ASC_DEF_ISA_DMA_SPEED 4
651#define ASC_INIT_STATE_NULL 0x0000
652#define ASC_INIT_STATE_BEG_GET_CFG 0x0001
653#define ASC_INIT_STATE_END_GET_CFG 0x0002
654#define ASC_INIT_STATE_BEG_SET_CFG 0x0004
655#define ASC_INIT_STATE_END_SET_CFG 0x0008
656#define ASC_INIT_STATE_BEG_LOAD_MC 0x0010
657#define ASC_INIT_STATE_END_LOAD_MC 0x0020
658#define ASC_INIT_STATE_BEG_INQUIRY 0x0040
659#define ASC_INIT_STATE_END_INQUIRY 0x0080
660#define ASC_INIT_RESET_SCSI_DONE 0x0100
661#define ASC_INIT_STATE_WITHOUT_EEP 0x8000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662#define ASC_BUG_FIX_IF_NOT_DWB 0x0001
663#define ASC_BUG_FIX_ASYN_USE_SYN 0x0002
664#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41
665#define ASC_MIN_TAGGED_CMD 7
666#define ASC_MAX_SCSI_RESET_WAIT 30
667
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400668struct asc_dvc_var; /* Forward Declaration. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670typedef struct asc_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400671 PortAddr iop_base;
672 ushort err_code;
673 ushort dvc_cntl;
674 ushort bug_fix_cntl;
675 ushort bus_type;
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400676 ASC_SCSI_BIT_ID_TYPE init_sdtr;
677 ASC_SCSI_BIT_ID_TYPE sdtr_done;
678 ASC_SCSI_BIT_ID_TYPE use_tagged_qng;
679 ASC_SCSI_BIT_ID_TYPE unit_not_ready;
680 ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
681 ASC_SCSI_BIT_ID_TYPE start_motor;
682 uchar scsi_reset_wait;
683 uchar chip_no;
684 char is_in_int;
685 uchar max_total_qng;
686 uchar cur_total_qng;
687 uchar in_critical_cnt;
688 uchar irq_no;
689 uchar last_q_shortage;
690 ushort init_state;
691 uchar cur_dvc_qng[ASC_MAX_TID + 1];
692 uchar max_dvc_qng[ASC_MAX_TID + 1];
693 ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1];
694 ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1];
695 uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO];
696 ASC_DVC_CFG *cfg;
697 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always;
698 char redo_scam;
699 ushort res2;
700 uchar dos_int13_table[ASC_MAX_TID + 1];
701 ASC_DCNT max_dma_count;
702 ASC_SCSI_BIT_ID_TYPE no_scam;
703 ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer;
704 uchar max_sdtr_index;
705 uchar host_init_sdtr_index;
706 struct asc_board *drv_ptr;
707 ASC_DCNT uc_break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708} ASC_DVC_VAR;
709
710typedef struct asc_dvc_inq_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400711 uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712} ASC_DVC_INQ_INFO;
713
714typedef struct asc_cap_info {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400715 ASC_DCNT lba;
716 ASC_DCNT blk_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717} ASC_CAP_INFO;
718
719typedef struct asc_cap_info_array {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400720 ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721} ASC_CAP_INFO_ARRAY;
722
723#define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001
724#define ASC_MCNTL_NULL_TARGET (ushort)0x0002
725#define ASC_CNTL_INITIATOR (ushort)0x0001
726#define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002
727#define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004
728#define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008
729#define ASC_CNTL_NO_SCAM (ushort)0x0010
730#define ASC_CNTL_INT_MULTI_Q (ushort)0x0080
731#define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040
732#define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100
733#define ASC_CNTL_RESET_SCSI (ushort)0x0200
734#define ASC_CNTL_INIT_INQUIRY (ushort)0x0400
735#define ASC_CNTL_INIT_VERBOSE (ushort)0x0800
736#define ASC_CNTL_SCSI_PARITY (ushort)0x1000
737#define ASC_CNTL_BURST_MODE (ushort)0x2000
738#define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000
739#define ASC_EEP_DVC_CFG_BEG_VL 2
740#define ASC_EEP_MAX_DVC_ADDR_VL 15
741#define ASC_EEP_DVC_CFG_BEG 32
742#define ASC_EEP_MAX_DVC_ADDR 45
743#define ASC_EEP_DEFINED_WORDS 10
744#define ASC_EEP_MAX_ADDR 63
745#define ASC_EEP_RES_WORDS 0
746#define ASC_EEP_MAX_RETRY 20
747#define ASC_MAX_INIT_BUSY_RETRY 8
748#define ASC_EEP_ISA_PNP_WSIZE 16
749
750/*
751 * These macros keep the chip SCSI id and ISA DMA speed
752 * bitfields in board order. C bitfields aren't portable
753 * between big and little-endian platforms so they are
754 * not used.
755 */
756
757#define ASC_EEP_GET_CHIP_ID(cfg) ((cfg)->id_speed & 0x0f)
758#define ASC_EEP_GET_DMA_SPD(cfg) (((cfg)->id_speed & 0xf0) >> 4)
759#define ASC_EEP_SET_CHIP_ID(cfg, sid) \
760 ((cfg)->id_speed = ((cfg)->id_speed & 0xf0) | ((sid) & ASC_MAX_TID))
761#define ASC_EEP_SET_DMA_SPD(cfg, spd) \
762 ((cfg)->id_speed = ((cfg)->id_speed & 0x0f) | ((spd) & 0x0f) << 4)
763
764typedef struct asceep_config {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400765 ushort cfg_lsw;
766 ushort cfg_msw;
767 uchar init_sdtr;
768 uchar disc_enable;
769 uchar use_cmd_qng;
770 uchar start_motor;
771 uchar max_total_qng;
772 uchar max_tag_qng;
773 uchar bios_scan;
774 uchar power_up_wait;
775 uchar no_scam;
776 uchar id_speed; /* low order 4 bits is chip scsi id */
777 /* high order 4 bits is isa dma speed */
778 uchar dos_int13_table[ASC_MAX_TID + 1];
779 uchar adapter_info[6];
780 ushort cntl;
781 ushort chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782} ASCEEP_CONFIG;
783
784#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800
785#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080
786#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020
787
788#define ASC_EEP_CMD_READ 0x80
789#define ASC_EEP_CMD_WRITE 0x40
790#define ASC_EEP_CMD_WRITE_ABLE 0x30
791#define ASC_EEP_CMD_WRITE_DISABLE 0x00
792#define ASC_OVERRUN_BSIZE 0x00000048UL
793#define ASC_CTRL_BREAK_ONCE 0x0001
794#define ASC_CTRL_BREAK_STAY_IDLE 0x0002
795#define ASCV_MSGOUT_BEG 0x0000
796#define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3)
797#define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4)
798#define ASCV_BREAK_SAVED_CODE (ushort)0x0006
799#define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8)
800#define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3)
801#define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4)
802#define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8)
803#define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8)
804#define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020
805#define ASCV_BREAK_ADDR (ushort)0x0028
806#define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A
807#define ASCV_BREAK_CONTROL (ushort)0x002C
808#define ASCV_BREAK_HIT_COUNT (ushort)0x002E
809
810#define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030
811#define ASCV_MCODE_CHKSUM_W (ushort)0x0032
812#define ASCV_MCODE_SIZE_W (ushort)0x0034
813#define ASCV_STOP_CODE_B (ushort)0x0036
814#define ASCV_DVC_ERR_CODE_B (ushort)0x0037
815#define ASCV_OVERRUN_PADDR_D (ushort)0x0038
816#define ASCV_OVERRUN_BSIZE_D (ushort)0x003C
817#define ASCV_HALTCODE_W (ushort)0x0040
818#define ASCV_CHKSUM_W (ushort)0x0042
819#define ASCV_MC_DATE_W (ushort)0x0044
820#define ASCV_MC_VER_W (ushort)0x0046
821#define ASCV_NEXTRDY_B (ushort)0x0048
822#define ASCV_DONENEXT_B (ushort)0x0049
823#define ASCV_USE_TAGGED_QNG_B (ushort)0x004A
824#define ASCV_SCSIBUSY_B (ushort)0x004B
825#define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C
826#define ASCV_CURCDB_B (ushort)0x004D
827#define ASCV_RCLUN_B (ushort)0x004E
828#define ASCV_BUSY_QHEAD_B (ushort)0x004F
829#define ASCV_DISC1_QHEAD_B (ushort)0x0050
830#define ASCV_DISC_ENABLE_B (ushort)0x0052
831#define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053
832#define ASCV_HOSTSCSI_ID_B (ushort)0x0055
833#define ASCV_MCODE_CNTL_B (ushort)0x0056
834#define ASCV_NULL_TARGET_B (ushort)0x0057
835#define ASCV_FREE_Q_HEAD_W (ushort)0x0058
836#define ASCV_DONE_Q_TAIL_W (ushort)0x005A
837#define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1)
838#define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1)
839#define ASCV_HOST_FLAG_B (ushort)0x005D
840#define ASCV_TOTAL_READY_Q_B (ushort)0x0064
841#define ASCV_VER_SERIAL_B (ushort)0x0065
842#define ASCV_HALTCODE_SAVED_W (ushort)0x0066
843#define ASCV_WTM_FLAG_B (ushort)0x0068
844#define ASCV_RISC_FLAG_B (ushort)0x006A
845#define ASCV_REQ_SG_LIST_QP (ushort)0x006B
846#define ASC_HOST_FLAG_IN_ISR 0x01
847#define ASC_HOST_FLAG_ACK_INT 0x02
848#define ASC_RISC_FLAG_GEN_INT 0x01
849#define ASC_RISC_FLAG_REQ_SG_LIST 0x02
850#define IOP_CTRL (0x0F)
851#define IOP_STATUS (0x0E)
852#define IOP_INT_ACK IOP_STATUS
853#define IOP_REG_IFC (0x0D)
854#define IOP_SYN_OFFSET (0x0B)
855#define IOP_EXTRA_CONTROL (0x0D)
856#define IOP_REG_PC (0x0C)
857#define IOP_RAM_ADDR (0x0A)
858#define IOP_RAM_DATA (0x08)
859#define IOP_EEP_DATA (0x06)
860#define IOP_EEP_CMD (0x07)
861#define IOP_VERSION (0x03)
862#define IOP_CONFIG_HIGH (0x04)
863#define IOP_CONFIG_LOW (0x02)
864#define IOP_SIG_BYTE (0x01)
865#define IOP_SIG_WORD (0x00)
866#define IOP_REG_DC1 (0x0E)
867#define IOP_REG_DC0 (0x0C)
868#define IOP_REG_SB (0x0B)
869#define IOP_REG_DA1 (0x0A)
870#define IOP_REG_DA0 (0x08)
871#define IOP_REG_SC (0x09)
872#define IOP_DMA_SPEED (0x07)
873#define IOP_REG_FLAG (0x07)
874#define IOP_FIFO_H (0x06)
875#define IOP_FIFO_L (0x04)
876#define IOP_REG_ID (0x05)
877#define IOP_REG_QP (0x03)
878#define IOP_REG_IH (0x02)
879#define IOP_REG_IX (0x01)
880#define IOP_REG_AX (0x00)
881#define IFC_REG_LOCK (0x00)
882#define IFC_REG_UNLOCK (0x09)
883#define IFC_WR_EN_FILTER (0x10)
884#define IFC_RD_NO_EEPROM (0x10)
885#define IFC_SLEW_RATE (0x20)
886#define IFC_ACT_NEG (0x40)
887#define IFC_INP_FILTER (0x80)
888#define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK)
889#define SC_SEL (uchar)(0x80)
890#define SC_BSY (uchar)(0x40)
891#define SC_ACK (uchar)(0x20)
892#define SC_REQ (uchar)(0x10)
893#define SC_ATN (uchar)(0x08)
894#define SC_IO (uchar)(0x04)
895#define SC_CD (uchar)(0x02)
896#define SC_MSG (uchar)(0x01)
897#define SEC_SCSI_CTL (uchar)(0x80)
898#define SEC_ACTIVE_NEGATE (uchar)(0x40)
899#define SEC_SLEW_RATE (uchar)(0x20)
900#define SEC_ENABLE_FILTER (uchar)(0x10)
901#define ASC_HALT_EXTMSG_IN (ushort)0x8000
902#define ASC_HALT_CHK_CONDITION (ushort)0x8100
903#define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200
904#define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300
905#define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400
906#define ASC_HALT_SDTR_REJECTED (ushort)0x4000
907#define ASC_HALT_HOST_COPY_SG_LIST_TO_RISC ( ushort )0x2000
908#define ASC_MAX_QNO 0xF8
909#define ASC_DATA_SEC_BEG (ushort)0x0080
910#define ASC_DATA_SEC_END (ushort)0x0080
911#define ASC_CODE_SEC_BEG (ushort)0x0080
912#define ASC_CODE_SEC_END (ushort)0x0080
913#define ASC_QADR_BEG (0x4000)
914#define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64)
915#define ASC_QADR_END (ushort)0x7FFF
916#define ASC_QLAST_ADR (ushort)0x7FC0
917#define ASC_QBLK_SIZE 0x40
918#define ASC_BIOS_DATA_QBEG 0xF8
919#define ASC_MIN_ACTIVE_QNO 0x01
920#define ASC_QLINK_END 0xFF
921#define ASC_EEPROM_WORDS 0x10
922#define ASC_MAX_MGS_LEN 0x10
923#define ASC_BIOS_ADDR_DEF 0xDC00
924#define ASC_BIOS_SIZE 0x3800
925#define ASC_BIOS_RAM_OFF 0x3800
926#define ASC_BIOS_RAM_SIZE 0x800
927#define ASC_BIOS_MIN_ADDR 0xC000
928#define ASC_BIOS_MAX_ADDR 0xEC00
929#define ASC_BIOS_BANK_SIZE 0x0400
930#define ASC_MCODE_START_ADDR 0x0080
931#define ASC_CFG0_HOST_INT_ON 0x0020
932#define ASC_CFG0_BIOS_ON 0x0040
933#define ASC_CFG0_VERA_BURST_ON 0x0080
934#define ASC_CFG0_SCSI_PARITY_ON 0x0800
935#define ASC_CFG1_SCSI_TARGET_ON 0x0080
936#define ASC_CFG1_LRAM_8BITS_ON 0x0800
937#define ASC_CFG_MSW_CLR_MASK 0x3080
938#define CSW_TEST1 (ASC_CS_TYPE)0x8000
939#define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000
940#define CSW_RESERVED1 (ASC_CS_TYPE)0x2000
941#define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000
942#define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800
943#define CSW_TEST2 (ASC_CS_TYPE)0x0400
944#define CSW_TEST3 (ASC_CS_TYPE)0x0200
945#define CSW_RESERVED2 (ASC_CS_TYPE)0x0100
946#define CSW_DMA_DONE (ASC_CS_TYPE)0x0080
947#define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040
948#define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020
949#define CSW_HALTED (ASC_CS_TYPE)0x0010
950#define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008
951#define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004
952#define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002
953#define CSW_INT_PENDING (ASC_CS_TYPE)0x0001
954#define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000
955#define CIW_INT_ACK (ASC_CS_TYPE)0x0100
956#define CIW_TEST1 (ASC_CS_TYPE)0x0200
957#define CIW_TEST2 (ASC_CS_TYPE)0x0400
958#define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800
959#define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000
960#define CC_CHIP_RESET (uchar)0x80
961#define CC_SCSI_RESET (uchar)0x40
962#define CC_HALT (uchar)0x20
963#define CC_SINGLE_STEP (uchar)0x10
964#define CC_DMA_ABLE (uchar)0x08
965#define CC_TEST (uchar)0x04
966#define CC_BANK_ONE (uchar)0x02
967#define CC_DIAG (uchar)0x01
968#define ASC_1000_ID0W 0x04C1
969#define ASC_1000_ID0W_FIX 0x00C1
970#define ASC_1000_ID1B 0x25
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971#define ASC_EISA_REV_IOP_MASK (0x0C83)
972#define ASC_EISA_PID_IOP_MASK (0x0C80)
973#define ASC_EISA_CFG_IOP_MASK (0x0C86)
974#define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975#define INS_HALTINT (ushort)0x6281
976#define INS_HALT (ushort)0x6280
977#define INS_SINT (ushort)0x6200
978#define INS_RFLAG_WTM (ushort)0x7380
979#define ASC_MC_SAVE_CODE_WSIZE 0x500
980#define ASC_MC_SAVE_DATA_WSIZE 0x40
981
982typedef struct asc_mc_saved {
Matthew Wilcox27c868c2007-07-26 10:56:23 -0400983 ushort data[ASC_MC_SAVE_DATA_WSIZE];
984 ushort code[ASC_MC_SAVE_CODE_WSIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985} ASC_MC_SAVED;
986
987#define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B)
988#define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val)
989#define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W)
990#define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W)
991#define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val)
992#define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val)
993#define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B)
994#define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B)
995#define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val)
996#define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val)
997#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data));
998#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id));
999#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data);
1000#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id));
1001#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ])
1002#define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE)
1003#define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD)
1004#define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION)
1005#define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW)
1006#define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH)
1007#define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data)
1008#define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data)
1009#define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD)
1010#define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data)
1011#define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA)
1012#define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data)
1013#define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR))
1014#define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr)
1015#define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA)
1016#define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data)
1017#define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC)
1018#define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data)
1019#define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS)
1020#define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val)
1021#define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL)
1022#define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val)
1023#define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET)
1024#define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data)
1025#define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data)
1026#define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC)
1027#define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH))
1028#define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID)
1029#define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL)
1030#define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data)
1031#define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX)
1032#define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data)
1033#define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX)
1034#define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data)
1035#define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH)
1036#define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data)
1037#define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP)
1038#define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data)
1039#define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L)
1040#define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data)
1041#define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H)
1042#define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data)
1043#define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED)
1044#define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data)
1045#define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0)
1046#define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data)
1047#define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1)
1048#define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data)
1049#define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0)
1050#define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data)
1051#define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1)
1052#define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data)
1053#define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID)
1054#define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data)
1055
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001056static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg);
1057static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg);
1058static void AscWaitEEPRead(void);
1059static void AscWaitEEPWrite(void);
1060static ushort AscReadEEPWord(PortAddr, uchar);
1061static ushort AscWriteEEPWord(PortAddr, uchar, ushort);
1062static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1063static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort);
1064static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort);
1065static int AscStartChip(PortAddr);
1066static int AscStopChip(PortAddr);
1067static void AscSetChipIH(PortAddr, ushort);
1068static int AscIsChipHalted(PortAddr);
1069static void AscAckInterrupt(PortAddr);
1070static void AscDisableInterrupt(PortAddr);
1071static void AscEnableInterrupt(PortAddr);
1072static void AscSetBank(PortAddr, uchar);
1073static int AscResetChipAndScsiBus(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001075static uchar AscGetIsaDmaSpeed(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001077static uchar AscReadLramByte(PortAddr, ushort);
1078static ushort AscReadLramWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001080static ASC_DCNT AscReadLramDWord(PortAddr, ushort);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001082static void AscWriteLramWord(PortAddr, ushort, ushort);
1083static void AscWriteLramByte(PortAddr, ushort, uchar);
1084static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int);
1085static void AscMemWordSetLram(PortAddr, ushort, ushort, int);
1086static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1087static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int);
1088static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int);
1089static ushort AscInitAscDvcVar(ASC_DVC_VAR *);
1090static ushort AscInitFromEEP(ASC_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001091static ushort AscInitMicroCodeVar(ASC_DVC_VAR *);
1092static int AscTestExternalLram(ASC_DVC_VAR *);
1093static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar);
1094static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar);
1095static void AscSetChipSDTR(PortAddr, uchar, uchar);
1096static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar);
1097static uchar AscAllocFreeQueue(PortAddr, uchar);
1098static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar);
1099static int AscHostReqRiscHalt(PortAddr);
1100static int AscStopQueueExe(PortAddr);
1101static int AscSendScsiQueue(ASC_DVC_VAR *,
1102 ASC_SCSI_Q *scsiq, uchar n_q_required);
1103static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1104static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar);
1105static int AscSetChipSynRegAtID(PortAddr, uchar, uchar);
1106static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar);
1107static ushort AscInitLram(ASC_DVC_VAR *);
1108static ushort AscInitQLinkVar(ASC_DVC_VAR *);
1109static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort);
1110static int AscIsrChipHalted(ASC_DVC_VAR *);
1111static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort,
1112 ASC_QDONE_INFO *, ASC_DCNT);
1113static int AscIsrQDone(ASC_DVC_VAR *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001115static ushort AscGetEisaChipCfg(PortAddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001117static uchar AscGetChipScsiCtrl(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001118static uchar AscGetChipVersion(PortAddr, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001119static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001120static void AscToggleIRQAct(PortAddr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001121static void DvcPutScsiQ(PortAddr, ushort, uchar *, int);
1122static void DvcGetQinfo(PortAddr, ushort, uchar *, int);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001123static ushort AscInitAsc1000Driver(ASC_DVC_VAR *);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04001124static void AscAsyncFix(ASC_DVC_VAR *, struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001125static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *);
1126static int AscISR(ASC_DVC_VAR *);
1127static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar);
1128static int AscSgListToQueue(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001130static void AscEnableIsaDma(uchar);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001132static const char *advansys_info(struct Scsi_Host *shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
1134/*
1135 * --- Adv Library Constants and Macros
1136 */
1137
1138#define ADV_LIB_VERSION_MAJOR 5
1139#define ADV_LIB_VERSION_MINOR 14
1140
1141/*
1142 * Define Adv Library required special types.
1143 */
1144
1145/*
1146 * Portable Data Types
1147 *
1148 * Any instance where a 32-bit long or pointer type is assumed
1149 * for precision or HW defined structures, the following define
1150 * types must be used. In Linux the char, short, and int types
1151 * are all consistent at 8, 16, and 32 bits respectively. Pointers
1152 * and long types are 64 bits on Alpha and UltraSPARC.
1153 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001154#define ADV_PADDR __u32 /* Physical address data type. */
1155#define ADV_VADDR __u32 /* Virtual address data type. */
1156#define ADV_DCNT __u32 /* Unsigned Data count type. */
1157#define ADV_SDCNT __s32 /* Signed Data count type. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
1159/*
1160 * These macros are used to convert a virtual address to a
1161 * 32-bit value. This currently can be used on Linux Alpha
1162 * which uses 64-bit virtual address but a 32-bit bus address.
1163 * This is likely to break in the future, but doing this now
1164 * will give us time to change the HW and FW to handle 64-bit
1165 * addresses.
1166 */
1167#define ADV_VADDR_TO_U32 virt_to_bus
1168#define ADV_U32_TO_VADDR bus_to_virt
1169
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001170#define AdvPortAddr void __iomem * /* Virtual memory address size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
1172/*
1173 * Define Adv Library required memory access macros.
1174 */
1175#define ADV_MEM_READB(addr) readb(addr)
1176#define ADV_MEM_READW(addr) readw(addr)
1177#define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr)
1178#define ADV_MEM_WRITEW(addr, word) writew(word, addr)
1179#define ADV_MEM_WRITEDW(addr, dword) writel(dword, addr)
1180
1181#define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15)
1182
1183/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 * Define total number of simultaneous maximum element scatter-gather
1185 * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the
1186 * maximum number of outstanding commands per wide host adapter. Each
1187 * command uses one or more ADV_SG_BLOCK each with 15 scatter-gather
1188 * elements. Allow each command to have at least one ADV_SG_BLOCK structure.
1189 * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK
1190 * structures or 255 scatter-gather elements.
1191 *
1192 */
1193#define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG
1194
1195/*
1196 * Define Adv Library required maximum number of scatter-gather
1197 * elements per request.
1198 */
1199#define ADV_MAX_SG_LIST 255
1200
1201/* Number of SG blocks needed. */
1202#define ADV_NUM_SG_BLOCK \
1203 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)
1204
1205/* Total contiguous memory needed for SG blocks. */
1206#define ADV_SG_TOTAL_MEM_SIZE \
1207 (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK)
1208
1209#define ADV_PAGE_SIZE PAGE_SIZE
1210
1211#define ADV_NUM_PAGE_CROSSING \
1212 ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
1213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214#define ADV_EEP_DVC_CFG_BEGIN (0x00)
1215#define ADV_EEP_DVC_CFG_END (0x15)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001216#define ADV_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217#define ADV_EEP_MAX_WORD_ADDR (0x1E)
1218
1219#define ADV_EEP_DELAY_MS 100
1220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001221#define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */
1222#define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223/*
1224 * For the ASC3550 Bit 13 is Termination Polarity control bit.
1225 * For later ICs Bit 13 controls whether the CIS (Card Information
1226 * Service Section) is loaded from EEPROM.
1227 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001228#define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */
1229#define ADV_EEPROM_CIS_LD 0x2000 /* EEPROM Bit 13 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230/*
1231 * ASC38C1600 Bit 11
1232 *
1233 * If EEPROM Bit 11 is 0 for Function 0, then Function 0 will specify
1234 * INT A in the PCI Configuration Space Int Pin field. If it is 1, then
1235 * Function 0 will specify INT B.
1236 *
1237 * If EEPROM Bit 11 is 0 for Function 1, then Function 1 will specify
1238 * INT B in the PCI Configuration Space Int Pin field. If it is 1, then
1239 * Function 1 will specify INT A.
1240 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001241#define ADV_EEPROM_INTAB 0x0800 /* EEPROM Bit 11 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001243typedef struct adveep_3550_config {
1244 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001246 ushort cfg_lsw; /* 00 power up initialization */
1247 /* bit 13 set - Term Polarity Control */
1248 /* bit 14 set - BIOS Enable */
1249 /* bit 15 set - Big Endian Mode */
1250 ushort cfg_msw; /* 01 unused */
1251 ushort disc_enable; /* 02 disconnect enable */
1252 ushort wdtr_able; /* 03 Wide DTR able */
1253 ushort sdtr_able; /* 04 Synchronous DTR able */
1254 ushort start_motor; /* 05 send start up motor */
1255 ushort tagqng_able; /* 06 tag queuing able */
1256 ushort bios_scan; /* 07 BIOS device control */
1257 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001259 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1260 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001262 uchar scsi_reset_delay; /* 10 reset delay */
1263 uchar bios_id_lun; /* first boot device scsi id & lun */
1264 /* high nibble is lun */
1265 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001267 uchar termination; /* 11 0 - automatic */
1268 /* 1 - low off / high off */
1269 /* 2 - low off / high on */
1270 /* 3 - low on / high on */
1271 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001273 uchar reserved1; /* reserved byte (not used) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001275 ushort bios_ctrl; /* 12 BIOS control bits */
1276 /* bit 0 BIOS don't act as initiator. */
1277 /* bit 1 BIOS > 1 GB support */
1278 /* bit 2 BIOS > 2 Disk Support */
1279 /* bit 3 BIOS don't support removables */
1280 /* bit 4 BIOS support bootable CD */
1281 /* bit 5 BIOS scan enabled */
1282 /* bit 6 BIOS support multiple LUNs */
1283 /* bit 7 BIOS display of message */
1284 /* bit 8 SCAM disabled */
1285 /* bit 9 Reset SCSI bus during init. */
1286 /* bit 10 */
1287 /* bit 11 No verbose initialization. */
1288 /* bit 12 SCSI parity enabled */
1289 /* bit 13 */
1290 /* bit 14 */
1291 /* bit 15 */
1292 ushort ultra_able; /* 13 ULTRA speed able */
1293 ushort reserved2; /* 14 reserved */
1294 uchar max_host_qng; /* 15 maximum host queuing */
1295 uchar max_dvc_qng; /* maximum per device queuing */
1296 ushort dvc_cntl; /* 16 control bit for driver */
1297 ushort bug_fix; /* 17 control bit for bug fix */
1298 ushort serial_number_word1; /* 18 Board serial number word 1 */
1299 ushort serial_number_word2; /* 19 Board serial number word 2 */
1300 ushort serial_number_word3; /* 20 Board serial number word 3 */
1301 ushort check_sum; /* 21 EEP check sum */
1302 uchar oem_name[16]; /* 22 OEM name */
1303 ushort dvc_err_code; /* 30 last device driver error code */
1304 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1305 ushort adv_err_addr; /* 32 last uc error address */
1306 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1307 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1308 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1309 ushort num_of_err; /* 36 number of error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310} ADVEEP_3550_CONFIG;
1311
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001312typedef struct adveep_38C0800_config {
1313 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001315 ushort cfg_lsw; /* 00 power up initialization */
1316 /* bit 13 set - Load CIS */
1317 /* bit 14 set - BIOS Enable */
1318 /* bit 15 set - Big Endian Mode */
1319 ushort cfg_msw; /* 01 unused */
1320 ushort disc_enable; /* 02 disconnect enable */
1321 ushort wdtr_able; /* 03 Wide DTR able */
1322 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1323 ushort start_motor; /* 05 send start up motor */
1324 ushort tagqng_able; /* 06 tag queuing able */
1325 ushort bios_scan; /* 07 BIOS device control */
1326 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001328 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1329 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001331 uchar scsi_reset_delay; /* 10 reset delay */
1332 uchar bios_id_lun; /* first boot device scsi id & lun */
1333 /* high nibble is lun */
1334 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001336 uchar termination_se; /* 11 0 - automatic */
1337 /* 1 - low off / high off */
1338 /* 2 - low off / high on */
1339 /* 3 - low on / high on */
1340 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001342 uchar termination_lvd; /* 11 0 - automatic */
1343 /* 1 - low off / high off */
1344 /* 2 - low off / high on */
1345 /* 3 - low on / high on */
1346 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001348 ushort bios_ctrl; /* 12 BIOS control bits */
1349 /* bit 0 BIOS don't act as initiator. */
1350 /* bit 1 BIOS > 1 GB support */
1351 /* bit 2 BIOS > 2 Disk Support */
1352 /* bit 3 BIOS don't support removables */
1353 /* bit 4 BIOS support bootable CD */
1354 /* bit 5 BIOS scan enabled */
1355 /* bit 6 BIOS support multiple LUNs */
1356 /* bit 7 BIOS display of message */
1357 /* bit 8 SCAM disabled */
1358 /* bit 9 Reset SCSI bus during init. */
1359 /* bit 10 */
1360 /* bit 11 No verbose initialization. */
1361 /* bit 12 SCSI parity enabled */
1362 /* bit 13 */
1363 /* bit 14 */
1364 /* bit 15 */
1365 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1366 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1367 uchar max_host_qng; /* 15 maximum host queueing */
1368 uchar max_dvc_qng; /* maximum per device queuing */
1369 ushort dvc_cntl; /* 16 control bit for driver */
1370 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1371 ushort serial_number_word1; /* 18 Board serial number word 1 */
1372 ushort serial_number_word2; /* 19 Board serial number word 2 */
1373 ushort serial_number_word3; /* 20 Board serial number word 3 */
1374 ushort check_sum; /* 21 EEP check sum */
1375 uchar oem_name[16]; /* 22 OEM name */
1376 ushort dvc_err_code; /* 30 last device driver error code */
1377 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1378 ushort adv_err_addr; /* 32 last uc error address */
1379 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1380 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1381 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1382 ushort reserved36; /* 36 reserved */
1383 ushort reserved37; /* 37 reserved */
1384 ushort reserved38; /* 38 reserved */
1385 ushort reserved39; /* 39 reserved */
1386 ushort reserved40; /* 40 reserved */
1387 ushort reserved41; /* 41 reserved */
1388 ushort reserved42; /* 42 reserved */
1389 ushort reserved43; /* 43 reserved */
1390 ushort reserved44; /* 44 reserved */
1391 ushort reserved45; /* 45 reserved */
1392 ushort reserved46; /* 46 reserved */
1393 ushort reserved47; /* 47 reserved */
1394 ushort reserved48; /* 48 reserved */
1395 ushort reserved49; /* 49 reserved */
1396 ushort reserved50; /* 50 reserved */
1397 ushort reserved51; /* 51 reserved */
1398 ushort reserved52; /* 52 reserved */
1399 ushort reserved53; /* 53 reserved */
1400 ushort reserved54; /* 54 reserved */
1401 ushort reserved55; /* 55 reserved */
1402 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1403 ushort cisprt_msw; /* 57 CIS PTR MSW */
1404 ushort subsysvid; /* 58 SubSystem Vendor ID */
1405 ushort subsysid; /* 59 SubSystem ID */
1406 ushort reserved60; /* 60 reserved */
1407 ushort reserved61; /* 61 reserved */
1408 ushort reserved62; /* 62 reserved */
1409 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410} ADVEEP_38C0800_CONFIG;
1411
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001412typedef struct adveep_38C1600_config {
1413 /* Word Offset, Description */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001415 ushort cfg_lsw; /* 00 power up initialization */
1416 /* bit 11 set - Func. 0 INTB, Func. 1 INTA */
1417 /* clear - Func. 0 INTA, Func. 1 INTB */
1418 /* bit 13 set - Load CIS */
1419 /* bit 14 set - BIOS Enable */
1420 /* bit 15 set - Big Endian Mode */
1421 ushort cfg_msw; /* 01 unused */
1422 ushort disc_enable; /* 02 disconnect enable */
1423 ushort wdtr_able; /* 03 Wide DTR able */
1424 ushort sdtr_speed1; /* 04 SDTR Speed TID 0-3 */
1425 ushort start_motor; /* 05 send start up motor */
1426 ushort tagqng_able; /* 06 tag queuing able */
1427 ushort bios_scan; /* 07 BIOS device control */
1428 ushort scam_tolerant; /* 08 no scam */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001430 uchar adapter_scsi_id; /* 09 Host Adapter ID */
1431 uchar bios_boot_delay; /* power up wait */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001433 uchar scsi_reset_delay; /* 10 reset delay */
1434 uchar bios_id_lun; /* first boot device scsi id & lun */
1435 /* high nibble is lun */
1436 /* low nibble is scsi id */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001438 uchar termination_se; /* 11 0 - automatic */
1439 /* 1 - low off / high off */
1440 /* 2 - low off / high on */
1441 /* 3 - low on / high on */
1442 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001444 uchar termination_lvd; /* 11 0 - automatic */
1445 /* 1 - low off / high off */
1446 /* 2 - low off / high on */
1447 /* 3 - low on / high on */
1448 /* There is no low on / high off */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001450 ushort bios_ctrl; /* 12 BIOS control bits */
1451 /* bit 0 BIOS don't act as initiator. */
1452 /* bit 1 BIOS > 1 GB support */
1453 /* bit 2 BIOS > 2 Disk Support */
1454 /* bit 3 BIOS don't support removables */
1455 /* bit 4 BIOS support bootable CD */
1456 /* bit 5 BIOS scan enabled */
1457 /* bit 6 BIOS support multiple LUNs */
1458 /* bit 7 BIOS display of message */
1459 /* bit 8 SCAM disabled */
1460 /* bit 9 Reset SCSI bus during init. */
1461 /* bit 10 Basic Integrity Checking disabled */
1462 /* bit 11 No verbose initialization. */
1463 /* bit 12 SCSI parity enabled */
1464 /* bit 13 AIPP (Asyn. Info. Ph. Prot.) dis. */
1465 /* bit 14 */
1466 /* bit 15 */
1467 ushort sdtr_speed2; /* 13 SDTR speed TID 4-7 */
1468 ushort sdtr_speed3; /* 14 SDTR speed TID 8-11 */
1469 uchar max_host_qng; /* 15 maximum host queueing */
1470 uchar max_dvc_qng; /* maximum per device queuing */
1471 ushort dvc_cntl; /* 16 control bit for driver */
1472 ushort sdtr_speed4; /* 17 SDTR speed 4 TID 12-15 */
1473 ushort serial_number_word1; /* 18 Board serial number word 1 */
1474 ushort serial_number_word2; /* 19 Board serial number word 2 */
1475 ushort serial_number_word3; /* 20 Board serial number word 3 */
1476 ushort check_sum; /* 21 EEP check sum */
1477 uchar oem_name[16]; /* 22 OEM name */
1478 ushort dvc_err_code; /* 30 last device driver error code */
1479 ushort adv_err_code; /* 31 last uc and Adv Lib error code */
1480 ushort adv_err_addr; /* 32 last uc error address */
1481 ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */
1482 ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */
1483 ushort saved_adv_err_addr; /* 35 saved last uc error address */
1484 ushort reserved36; /* 36 reserved */
1485 ushort reserved37; /* 37 reserved */
1486 ushort reserved38; /* 38 reserved */
1487 ushort reserved39; /* 39 reserved */
1488 ushort reserved40; /* 40 reserved */
1489 ushort reserved41; /* 41 reserved */
1490 ushort reserved42; /* 42 reserved */
1491 ushort reserved43; /* 43 reserved */
1492 ushort reserved44; /* 44 reserved */
1493 ushort reserved45; /* 45 reserved */
1494 ushort reserved46; /* 46 reserved */
1495 ushort reserved47; /* 47 reserved */
1496 ushort reserved48; /* 48 reserved */
1497 ushort reserved49; /* 49 reserved */
1498 ushort reserved50; /* 50 reserved */
1499 ushort reserved51; /* 51 reserved */
1500 ushort reserved52; /* 52 reserved */
1501 ushort reserved53; /* 53 reserved */
1502 ushort reserved54; /* 54 reserved */
1503 ushort reserved55; /* 55 reserved */
1504 ushort cisptr_lsw; /* 56 CIS PTR LSW */
1505 ushort cisprt_msw; /* 57 CIS PTR MSW */
1506 ushort subsysvid; /* 58 SubSystem Vendor ID */
1507 ushort subsysid; /* 59 SubSystem ID */
1508 ushort reserved60; /* 60 reserved */
1509 ushort reserved61; /* 61 reserved */
1510 ushort reserved62; /* 62 reserved */
1511 ushort reserved63; /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512} ADVEEP_38C1600_CONFIG;
1513
1514/*
1515 * EEPROM Commands
1516 */
1517#define ASC_EEP_CMD_DONE 0x0200
1518#define ASC_EEP_CMD_DONE_ERR 0x0001
1519
1520/* cfg_word */
1521#define EEP_CFG_WORD_BIG_ENDIAN 0x8000
1522
1523/* bios_ctrl */
1524#define BIOS_CTRL_BIOS 0x0001
1525#define BIOS_CTRL_EXTENDED_XLAT 0x0002
1526#define BIOS_CTRL_GT_2_DISK 0x0004
1527#define BIOS_CTRL_BIOS_REMOVABLE 0x0008
1528#define BIOS_CTRL_BOOTABLE_CD 0x0010
1529#define BIOS_CTRL_MULTIPLE_LUN 0x0040
1530#define BIOS_CTRL_DISPLAY_MSG 0x0080
1531#define BIOS_CTRL_NO_SCAM 0x0100
1532#define BIOS_CTRL_RESET_SCSI_BUS 0x0200
1533#define BIOS_CTRL_INIT_VERBOSE 0x0800
1534#define BIOS_CTRL_SCSI_PARITY 0x1000
1535#define BIOS_CTRL_AIPP_DIS 0x2000
1536
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001537#define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001539#define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540
1541/*
1542 * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is
1543 * a special 16K Adv Library and Microcode version. After the issue is
1544 * resolved, should restore 32K support.
1545 *
1546 * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory *
1547 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001548#define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
1550/*
1551 * Byte I/O register address from base of 'iop_base'.
1552 */
1553#define IOPB_INTR_STATUS_REG 0x00
1554#define IOPB_CHIP_ID_1 0x01
1555#define IOPB_INTR_ENABLES 0x02
1556#define IOPB_CHIP_TYPE_REV 0x03
1557#define IOPB_RES_ADDR_4 0x04
1558#define IOPB_RES_ADDR_5 0x05
1559#define IOPB_RAM_DATA 0x06
1560#define IOPB_RES_ADDR_7 0x07
1561#define IOPB_FLAG_REG 0x08
1562#define IOPB_RES_ADDR_9 0x09
1563#define IOPB_RISC_CSR 0x0A
1564#define IOPB_RES_ADDR_B 0x0B
1565#define IOPB_RES_ADDR_C 0x0C
1566#define IOPB_RES_ADDR_D 0x0D
1567#define IOPB_SOFT_OVER_WR 0x0E
1568#define IOPB_RES_ADDR_F 0x0F
1569#define IOPB_MEM_CFG 0x10
1570#define IOPB_RES_ADDR_11 0x11
1571#define IOPB_GPIO_DATA 0x12
1572#define IOPB_RES_ADDR_13 0x13
1573#define IOPB_FLASH_PAGE 0x14
1574#define IOPB_RES_ADDR_15 0x15
1575#define IOPB_GPIO_CNTL 0x16
1576#define IOPB_RES_ADDR_17 0x17
1577#define IOPB_FLASH_DATA 0x18
1578#define IOPB_RES_ADDR_19 0x19
1579#define IOPB_RES_ADDR_1A 0x1A
1580#define IOPB_RES_ADDR_1B 0x1B
1581#define IOPB_RES_ADDR_1C 0x1C
1582#define IOPB_RES_ADDR_1D 0x1D
1583#define IOPB_RES_ADDR_1E 0x1E
1584#define IOPB_RES_ADDR_1F 0x1F
1585#define IOPB_DMA_CFG0 0x20
1586#define IOPB_DMA_CFG1 0x21
1587#define IOPB_TICKLE 0x22
1588#define IOPB_DMA_REG_WR 0x23
1589#define IOPB_SDMA_STATUS 0x24
1590#define IOPB_SCSI_BYTE_CNT 0x25
1591#define IOPB_HOST_BYTE_CNT 0x26
1592#define IOPB_BYTE_LEFT_TO_XFER 0x27
1593#define IOPB_BYTE_TO_XFER_0 0x28
1594#define IOPB_BYTE_TO_XFER_1 0x29
1595#define IOPB_BYTE_TO_XFER_2 0x2A
1596#define IOPB_BYTE_TO_XFER_3 0x2B
1597#define IOPB_ACC_GRP 0x2C
1598#define IOPB_RES_ADDR_2D 0x2D
1599#define IOPB_DEV_ID 0x2E
1600#define IOPB_RES_ADDR_2F 0x2F
1601#define IOPB_SCSI_DATA 0x30
1602#define IOPB_RES_ADDR_31 0x31
1603#define IOPB_RES_ADDR_32 0x32
1604#define IOPB_SCSI_DATA_HSHK 0x33
1605#define IOPB_SCSI_CTRL 0x34
1606#define IOPB_RES_ADDR_35 0x35
1607#define IOPB_RES_ADDR_36 0x36
1608#define IOPB_RES_ADDR_37 0x37
1609#define IOPB_RAM_BIST 0x38
1610#define IOPB_PLL_TEST 0x39
1611#define IOPB_PCI_INT_CFG 0x3A
1612#define IOPB_RES_ADDR_3B 0x3B
1613#define IOPB_RFIFO_CNT 0x3C
1614#define IOPB_RES_ADDR_3D 0x3D
1615#define IOPB_RES_ADDR_3E 0x3E
1616#define IOPB_RES_ADDR_3F 0x3F
1617
1618/*
1619 * Word I/O register address from base of 'iop_base'.
1620 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001621#define IOPW_CHIP_ID_0 0x00 /* CID0 */
1622#define IOPW_CTRL_REG 0x02 /* CC */
1623#define IOPW_RAM_ADDR 0x04 /* LA */
1624#define IOPW_RAM_DATA 0x06 /* LD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625#define IOPW_RES_ADDR_08 0x08
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001626#define IOPW_RISC_CSR 0x0A /* CSR */
1627#define IOPW_SCSI_CFG0 0x0C /* CFG0 */
1628#define IOPW_SCSI_CFG1 0x0E /* CFG1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629#define IOPW_RES_ADDR_10 0x10
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001630#define IOPW_SEL_MASK 0x12 /* SM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631#define IOPW_RES_ADDR_14 0x14
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001632#define IOPW_FLASH_ADDR 0x16 /* FA */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633#define IOPW_RES_ADDR_18 0x18
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001634#define IOPW_EE_CMD 0x1A /* EC */
1635#define IOPW_EE_DATA 0x1C /* ED */
1636#define IOPW_SFIFO_CNT 0x1E /* SFC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637#define IOPW_RES_ADDR_20 0x20
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001638#define IOPW_Q_BASE 0x22 /* QB */
1639#define IOPW_QP 0x24 /* QP */
1640#define IOPW_IX 0x26 /* IX */
1641#define IOPW_SP 0x28 /* SP */
1642#define IOPW_PC 0x2A /* PC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643#define IOPW_RES_ADDR_2C 0x2C
1644#define IOPW_RES_ADDR_2E 0x2E
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001645#define IOPW_SCSI_DATA 0x30 /* SD */
1646#define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */
1647#define IOPW_SCSI_CTRL 0x34 /* SC */
1648#define IOPW_HSHK_CFG 0x36 /* HCFG */
1649#define IOPW_SXFR_STATUS 0x36 /* SXS */
1650#define IOPW_SXFR_CNTL 0x38 /* SXL */
1651#define IOPW_SXFR_CNTH 0x3A /* SXH */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652#define IOPW_RES_ADDR_3C 0x3C
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001653#define IOPW_RFIFO_DATA 0x3E /* RFD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654
1655/*
1656 * Doubleword I/O register address from base of 'iop_base'.
1657 */
1658#define IOPDW_RES_ADDR_0 0x00
1659#define IOPDW_RAM_DATA 0x04
1660#define IOPDW_RES_ADDR_8 0x08
1661#define IOPDW_RES_ADDR_C 0x0C
1662#define IOPDW_RES_ADDR_10 0x10
1663#define IOPDW_COMMA 0x14
1664#define IOPDW_COMMB 0x18
1665#define IOPDW_RES_ADDR_1C 0x1C
1666#define IOPDW_SDMA_ADDR0 0x20
1667#define IOPDW_SDMA_ADDR1 0x24
1668#define IOPDW_SDMA_COUNT 0x28
1669#define IOPDW_SDMA_ERROR 0x2C
1670#define IOPDW_RDMA_ADDR0 0x30
1671#define IOPDW_RDMA_ADDR1 0x34
1672#define IOPDW_RDMA_COUNT 0x38
1673#define IOPDW_RDMA_ERROR 0x3C
1674
1675#define ADV_CHIP_ID_BYTE 0x25
1676#define ADV_CHIP_ID_WORD 0x04C1
1677
1678#define ADV_SC_SCSI_BUS_RESET 0x2000
1679
1680#define ADV_INTR_ENABLE_HOST_INTR 0x01
1681#define ADV_INTR_ENABLE_SEL_INTR 0x02
1682#define ADV_INTR_ENABLE_DPR_INTR 0x04
1683#define ADV_INTR_ENABLE_RTA_INTR 0x08
1684#define ADV_INTR_ENABLE_RMA_INTR 0x10
1685#define ADV_INTR_ENABLE_RST_INTR 0x20
1686#define ADV_INTR_ENABLE_DPE_INTR 0x40
1687#define ADV_INTR_ENABLE_GLOBAL_INTR 0x80
1688
1689#define ADV_INTR_STATUS_INTRA 0x01
1690#define ADV_INTR_STATUS_INTRB 0x02
1691#define ADV_INTR_STATUS_INTRC 0x04
1692
1693#define ADV_RISC_CSR_STOP (0x0000)
1694#define ADV_RISC_TEST_COND (0x2000)
1695#define ADV_RISC_CSR_RUN (0x4000)
1696#define ADV_RISC_CSR_SINGLE_STEP (0x8000)
1697
1698#define ADV_CTRL_REG_HOST_INTR 0x0100
1699#define ADV_CTRL_REG_SEL_INTR 0x0200
1700#define ADV_CTRL_REG_DPR_INTR 0x0400
1701#define ADV_CTRL_REG_RTA_INTR 0x0800
1702#define ADV_CTRL_REG_RMA_INTR 0x1000
1703#define ADV_CTRL_REG_RES_BIT14 0x2000
1704#define ADV_CTRL_REG_DPE_INTR 0x4000
1705#define ADV_CTRL_REG_POWER_DONE 0x8000
1706#define ADV_CTRL_REG_ANY_INTR 0xFF00
1707
1708#define ADV_CTRL_REG_CMD_RESET 0x00C6
1709#define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5
1710#define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4
1711#define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3
1712#define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2
1713
1714#define ADV_TICKLE_NOP 0x00
1715#define ADV_TICKLE_A 0x01
1716#define ADV_TICKLE_B 0x02
1717#define ADV_TICKLE_C 0x03
1718
1719#define ADV_SCSI_CTRL_RSTOUT 0x2000
1720
1721#define AdvIsIntPending(port) \
1722 (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR)
1723
1724/*
1725 * SCSI_CFG0 Register bit definitions
1726 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001727#define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */
1728#define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */
1729#define EVEN_PARITY 0x1000 /* Select Even Parity */
1730#define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */
1731#define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */
1732#define PRIM_MODE 0x0100 /* Primitive SCSI mode */
1733#define SCAM_EN 0x0080 /* Enable SCAM selection */
1734#define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */
1735#define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */
1736#define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */
1737#define OUR_ID 0x000F /* SCSI ID */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
1739/*
1740 * SCSI_CFG1 Register bit definitions
1741 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001742#define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */
1743#define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */
1744#define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */
1745#define FILTER_SEL 0x0C00 /* Filter Period Selection */
1746#define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */
1747#define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */
1748#define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */
1749#define ACTIVE_DBL 0x0200 /* Disable Active Negation */
1750#define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */
1751#define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */
1752#define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */
1753#define TERM_CTL 0x0030 /* External SCSI Termination Bits */
1754#define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */
1755#define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */
1756#define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
1758/*
1759 * Addendum for ASC-38C0800 Chip
1760 *
1761 * The ASC-38C1600 Chip uses the same definitions except that the
1762 * bus mode override bits [12:10] have been moved to byte register
1763 * offset 0xE (IOPB_SOFT_OVER_WR) bits [12:10]. The [12:10] bits in
1764 * SCSI_CFG1 are read-only and always available. Bit 14 (DIS_TERM_DRV)
1765 * is not needed. The [12:10] bits in IOPB_SOFT_OVER_WR are write-only.
1766 * Also each ASC-38C1600 function or channel uses only cable bits [5:4]
1767 * and [1:0]. Bits [14], [7:6], [3:2] are unused.
1768 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001769#define DIS_TERM_DRV 0x4000 /* 1: Read c_det[3:0], 0: cannot read */
1770#define HVD_LVD_SE 0x1C00 /* Device Detect Bits */
1771#define HVD 0x1000 /* HVD Device Detect */
1772#define LVD 0x0800 /* LVD Device Detect */
1773#define SE 0x0400 /* SE Device Detect */
1774#define TERM_LVD 0x00C0 /* LVD Termination Bits */
1775#define TERM_LVD_HI 0x0080 /* Enable LVD Upper Termination */
1776#define TERM_LVD_LO 0x0040 /* Enable LVD Lower Termination */
1777#define TERM_SE 0x0030 /* SE Termination Bits */
1778#define TERM_SE_HI 0x0020 /* Enable SE Upper Termination */
1779#define TERM_SE_LO 0x0010 /* Enable SE Lower Termination */
1780#define C_DET_LVD 0x000C /* LVD Cable Detect Bits */
1781#define C_DET3 0x0008 /* Cable Detect for LVD External Wide */
1782#define C_DET2 0x0004 /* Cable Detect for LVD Internal Wide */
1783#define C_DET_SE 0x0003 /* SE Cable Detect Bits */
1784#define C_DET1 0x0002 /* Cable Detect for SE Internal Wide */
1785#define C_DET0 0x0001 /* Cable Detect for SE Internal Narrow */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786
1787#define CABLE_ILLEGAL_A 0x7
1788 /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */
1789
1790#define CABLE_ILLEGAL_B 0xB
1791 /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */
1792
1793/*
1794 * MEM_CFG Register bit definitions
1795 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001796#define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */
1797#define FAST_EE_CLK 0x20 /* Diagnostic Bit */
1798#define RAM_SZ 0x1C /* Specify size of RAM to RISC */
1799#define RAM_SZ_2KB 0x00 /* 2 KB */
1800#define RAM_SZ_4KB 0x04 /* 4 KB */
1801#define RAM_SZ_8KB 0x08 /* 8 KB */
1802#define RAM_SZ_16KB 0x0C /* 16 KB */
1803#define RAM_SZ_32KB 0x10 /* 32 KB */
1804#define RAM_SZ_64KB 0x14 /* 64 KB */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
1806/*
1807 * DMA_CFG0 Register bit definitions
1808 *
1809 * This register is only accessible to the host.
1810 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001811#define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */
1812#define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */
1813#define FIFO_THRESH_16B 0x00 /* 16 bytes */
1814#define FIFO_THRESH_32B 0x20 /* 32 bytes */
1815#define FIFO_THRESH_48B 0x30 /* 48 bytes */
1816#define FIFO_THRESH_64B 0x40 /* 64 bytes */
1817#define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */
1818#define FIFO_THRESH_96B 0x60 /* 96 bytes */
1819#define FIFO_THRESH_112B 0x70 /* 112 bytes */
1820#define START_CTL 0x0C /* DMA start conditions */
1821#define START_CTL_TH 0x00 /* Wait threshold level (default) */
1822#define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */
1823#define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */
1824#define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */
1825#define READ_CMD 0x03 /* Memory Read Method */
1826#define READ_CMD_MR 0x00 /* Memory Read */
1827#define READ_CMD_MRL 0x02 /* Memory Read Long */
1828#define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
1830/*
1831 * ASC-38C0800 RAM BIST Register bit definitions
1832 */
1833#define RAM_TEST_MODE 0x80
1834#define PRE_TEST_MODE 0x40
1835#define NORMAL_MODE 0x00
1836#define RAM_TEST_DONE 0x10
1837#define RAM_TEST_STATUS 0x0F
1838#define RAM_TEST_HOST_ERROR 0x08
1839#define RAM_TEST_INTRAM_ERROR 0x04
1840#define RAM_TEST_RISC_ERROR 0x02
1841#define RAM_TEST_SCSI_ERROR 0x01
1842#define RAM_TEST_SUCCESS 0x00
1843#define PRE_TEST_VALUE 0x05
1844#define NORMAL_VALUE 0x00
1845
1846/*
1847 * ASC38C1600 Definitions
1848 *
1849 * IOPB_PCI_INT_CFG Bit Field Definitions
1850 */
1851
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001852#define INTAB_LD 0x80 /* Value loaded from EEPROM Bit 11. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853
1854/*
1855 * Bit 1 can be set to change the interrupt for the Function to operate in
1856 * Totem Pole mode. By default Bit 1 is 0 and the interrupt operates in
1857 * Open Drain mode. Both functions of the ASC38C1600 must be set to the same
1858 * mode, otherwise the operating mode is undefined.
1859 */
1860#define TOTEMPOLE 0x02
1861
1862/*
1863 * Bit 0 can be used to change the Int Pin for the Function. The value is
1864 * 0 by default for both Functions with Function 0 using INT A and Function
1865 * B using INT B. For Function 0 if set, INT B is used. For Function 1 if set,
1866 * INT A is used.
1867 *
1868 * EEPROM Word 0 Bit 11 for each Function may change the initial Int Pin
1869 * value specified in the PCI Configuration Space.
1870 */
1871#define INTAB 0x01
1872
1873/* a_advlib.h */
1874
1875/*
1876 * Adv Library Status Definitions
1877 */
1878#define ADV_TRUE 1
1879#define ADV_FALSE 0
1880#define ADV_NOERROR 1
1881#define ADV_SUCCESS 1
1882#define ADV_BUSY 0
1883#define ADV_ERROR (-1)
1884
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885/*
1886 * ADV_DVC_VAR 'warn_code' values
1887 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001888#define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */
1889#define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */
1890#define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */
1891#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */
1892#define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001894#define ADV_MAX_TID 15 /* max. target identifier */
1895#define ADV_MAX_LUN 7 /* max. logical unit number */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
1897/*
1898 * Error code values are set in ADV_DVC_VAR 'err_code'.
1899 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001900#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */
1901#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */
1902#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */
1903#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */
1904#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */
1905#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */
1906#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */
1907#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */
1908#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */
1909#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */
1910#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */
1911#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */
1912#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */
1913#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914
1915/*
1916 * Fixed locations of microcode operating variables.
1917 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001918#define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */
1919#define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */
1920#define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */
1921#define ASC_MC_VERSION_DATE 0x0038 /* microcode version */
1922#define ASC_MC_VERSION_NUM 0x003A /* microcode number */
1923#define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */
1924#define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */
1925#define ASC_MC_BIOS_SIGNATURE 0x0058 /* BIOS Signature 0x55AA */
1926#define ASC_MC_BIOS_VERSION 0x005A /* BIOS Version (2 bytes) */
1927#define ASC_MC_SDTR_SPEED1 0x0090 /* SDTR Speed for TID 0-3 */
1928#define ASC_MC_SDTR_SPEED2 0x0092 /* SDTR Speed for TID 4-7 */
1929#define ASC_MC_SDTR_SPEED3 0x0094 /* SDTR Speed for TID 8-11 */
1930#define ASC_MC_SDTR_SPEED4 0x0096 /* SDTR Speed for TID 12-15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931#define ASC_MC_CHIP_TYPE 0x009A
1932#define ASC_MC_INTRB_CODE 0x009B
1933#define ASC_MC_WDTR_ABLE 0x009C
1934#define ASC_MC_SDTR_ABLE 0x009E
1935#define ASC_MC_TAGQNG_ABLE 0x00A0
1936#define ASC_MC_DISC_ENABLE 0x00A2
1937#define ASC_MC_IDLE_CMD_STATUS 0x00A4
1938#define ASC_MC_IDLE_CMD 0x00A6
1939#define ASC_MC_IDLE_CMD_PARAMETER 0x00A8
1940#define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC
1941#define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE
1942#define ASC_MC_DEFAULT_MEM_CFG 0x00B0
1943#define ASC_MC_DEFAULT_SEL_MASK 0x00B2
1944#define ASC_MC_SDTR_DONE 0x00B6
1945#define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0
1946#define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0
1947#define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001948#define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949#define ASC_MC_WDTR_DONE 0x0124
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001950#define ASC_MC_CAM_MODE_MASK 0x015E /* CAM mode TID bitmask. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951#define ASC_MC_ICQ 0x0160
1952#define ASC_MC_IRQ 0x0164
1953#define ASC_MC_PPR_ABLE 0x017A
1954
1955/*
1956 * BIOS LRAM variable absolute offsets.
1957 */
1958#define BIOS_CODESEG 0x54
1959#define BIOS_CODELEN 0x56
1960#define BIOS_SIGNATURE 0x58
1961#define BIOS_VERSION 0x5A
1962
1963/*
1964 * Microcode Control Flags
1965 *
1966 * Flags set by the Adv Library in RISC variable 'control_flag' (0x122)
1967 * and handled by the microcode.
1968 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001969#define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */
1970#define CONTROL_FLAG_ENABLE_AIPP 0x0002 /* Enabled AIPP checking. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971
1972/*
1973 * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format
1974 */
1975#define HSHK_CFG_WIDE_XFR 0x8000
1976#define HSHK_CFG_RATE 0x0F00
1977#define HSHK_CFG_OFFSET 0x001F
1978
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001979#define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */
1980#define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */
1981#define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */
1982#define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001984#define ASC_QC_DATA_CHECK 0x01 /* Require ASC_QC_DATA_OUT set or clear. */
1985#define ASC_QC_DATA_OUT 0x02 /* Data out DMA transfer. */
1986#define ASC_QC_START_MOTOR 0x04 /* Send auto-start motor before request. */
1987#define ASC_QC_NO_OVERRUN 0x08 /* Don't report overrun. */
1988#define ASC_QC_FREEZE_TIDQ 0x10 /* Freeze TID queue after request. XXX TBD */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001990#define ASC_QSC_NO_DISC 0x01 /* Don't allow disconnect for request. */
1991#define ASC_QSC_NO_TAGMSG 0x02 /* Don't allow tag queuing for request. */
1992#define ASC_QSC_NO_SYNC 0x04 /* Don't use Synch. transfer on request. */
1993#define ASC_QSC_NO_WIDE 0x08 /* Don't use Wide transfer on request. */
1994#define ASC_QSC_REDO_DTR 0x10 /* Renegotiate WDTR/SDTR before request. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995/*
1996 * Note: If a Tag Message is to be sent and neither ASC_QSC_HEAD_TAG or
1997 * ASC_QSC_ORDERED_TAG is set, then a Simple Tag Message (0x20) is used.
1998 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04001999#define ASC_QSC_HEAD_TAG 0x40 /* Use Head Tag Message (0x21). */
2000#define ASC_QSC_ORDERED_TAG 0x80 /* Use Ordered Tag Message (0x22). */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
2002/*
2003 * All fields here are accessed by the board microcode and need to be
2004 * little-endian.
2005 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002006typedef struct adv_carr_t {
2007 ADV_VADDR carr_va; /* Carrier Virtual Address */
2008 ADV_PADDR carr_pa; /* Carrier Physical Address */
2009 ADV_VADDR areq_vpa; /* ASC_SCSI_REQ_Q Virtual or Physical Address */
2010 /*
2011 * next_vpa [31:4] Carrier Virtual or Physical Next Pointer
2012 *
2013 * next_vpa [3:1] Reserved Bits
2014 * next_vpa [0] Done Flag set in Response Queue.
2015 */
2016 ADV_VADDR next_vpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017} ADV_CARR_T;
2018
2019/*
2020 * Mask used to eliminate low 4 bits of carrier 'next_vpa' field.
2021 */
2022#define ASC_NEXT_VPA_MASK 0xFFFFFFF0
2023
2024#define ASC_RQ_DONE 0x00000001
2025#define ASC_RQ_GOOD 0x00000002
2026#define ASC_CQ_STOPPER 0x00000000
2027
2028#define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK)
2029
2030#define ADV_CARRIER_NUM_PAGE_CROSSING \
2031 (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \
2032 (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE)
2033
2034#define ADV_CARRIER_BUFSIZE \
2035 ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T))
2036
2037/*
2038 * ASC_SCSI_REQ_Q 'a_flag' definitions
2039 *
2040 * The Adv Library should limit use to the lower nibble (4 bits) of
2041 * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag.
2042 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002043#define ADV_POLL_REQUEST 0x01 /* poll for request completion */
2044#define ADV_SCSIQ_DONE 0x02 /* request done */
2045#define ADV_DONT_RETRY 0x08 /* don't do retry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002047#define ADV_CHIP_ASC3550 0x01 /* Ultra-Wide IC */
2048#define ADV_CHIP_ASC38C0800 0x02 /* Ultra2-Wide/LVD IC */
2049#define ADV_CHIP_ASC38C1600 0x03 /* Ultra3-Wide/LVD2 IC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
2051/*
2052 * Adapter temporary configuration structure
2053 *
2054 * This structure can be discarded after initialization. Don't add
2055 * fields here needed after initialization.
2056 *
2057 * Field naming convention:
2058 *
2059 * *_enable indicates the field enables or disables a feature. The
2060 * value of the field is never reset.
2061 */
2062typedef struct adv_dvc_cfg {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002063 ushort disc_enable; /* enable disconnection */
2064 uchar chip_version; /* chip version */
2065 uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */
2066 ushort lib_version; /* Adv Library version number */
2067 ushort control_flag; /* Microcode Control Flag */
2068 ushort mcode_date; /* Microcode date */
2069 ushort mcode_version; /* Microcode version */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002070 ushort serial1; /* EEPROM serial number word 1 */
2071 ushort serial2; /* EEPROM serial number word 2 */
2072 ushort serial3; /* EEPROM serial number word 3 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073} ADV_DVC_CFG;
2074
2075struct adv_dvc_var;
2076struct adv_scsi_req_q;
2077
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078/*
2079 * Adapter operation variable structure.
2080 *
2081 * One structure is required per host adapter.
2082 *
2083 * Field naming convention:
2084 *
2085 * *_able indicates both whether a feature should be enabled or disabled
2086 * and whether a device isi capable of the feature. At initialization
2087 * this field may be set, but later if a device is found to be incapable
2088 * of the feature, the field is cleared.
2089 */
2090typedef struct adv_dvc_var {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002091 AdvPortAddr iop_base; /* I/O port address */
2092 ushort err_code; /* fatal error code */
2093 ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002094 ushort wdtr_able; /* try WDTR for a device */
2095 ushort sdtr_able; /* try SDTR for a device */
2096 ushort ultra_able; /* try SDTR Ultra speed for a device */
2097 ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */
2098 ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */
2099 ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */
2100 ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */
2101 ushort tagqng_able; /* try tagged queuing with a device */
2102 ushort ppr_able; /* PPR message capable per TID bitmask. */
2103 uchar max_dvc_qng; /* maximum number of tagged commands per device */
2104 ushort start_motor; /* start motor command allowed */
2105 uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */
2106 uchar chip_no; /* should be assigned by caller */
2107 uchar max_host_qng; /* maximum number of Q'ed command allowed */
2108 uchar irq_no; /* IRQ number */
2109 ushort no_scam; /* scam_tolerant of EEPROM */
2110 struct asc_board *drv_ptr; /* driver pointer to private structure */
2111 uchar chip_scsi_id; /* chip SCSI target ID */
2112 uchar chip_type;
2113 uchar bist_err_code;
2114 ADV_CARR_T *carrier_buf;
2115 ADV_CARR_T *carr_freelist; /* Carrier free list. */
2116 ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */
2117 ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */
2118 ushort carr_pending_cnt; /* Count of pending carriers. */
2119 /*
2120 * Note: The following fields will not be used after initialization. The
2121 * driver may discard the buffer after initialization is done.
2122 */
2123 ADV_DVC_CFG *cfg; /* temporary configuration structure */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124} ADV_DVC_VAR;
2125
2126#define NO_OF_SG_PER_BLOCK 15
2127
2128typedef struct asc_sg_block {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002129 uchar reserved1;
2130 uchar reserved2;
2131 uchar reserved3;
2132 uchar sg_cnt; /* Valid entries in block. */
2133 ADV_PADDR sg_ptr; /* Pointer to next sg block. */
2134 struct {
2135 ADV_PADDR sg_addr; /* SG element address. */
2136 ADV_DCNT sg_count; /* SG element count. */
2137 } sg_list[NO_OF_SG_PER_BLOCK];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138} ADV_SG_BLOCK;
2139
2140/*
2141 * ADV_SCSI_REQ_Q - microcode request structure
2142 *
2143 * All fields in this structure up to byte 60 are used by the microcode.
2144 * The microcode makes assumptions about the size and ordering of fields
2145 * in this structure. Do not change the structure definition here without
2146 * coordinating the change with the microcode.
2147 *
2148 * All fields accessed by microcode must be maintained in little_endian
2149 * order.
2150 */
2151typedef struct adv_scsi_req_q {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002152 uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */
2153 uchar target_cmd;
2154 uchar target_id; /* Device target identifier. */
2155 uchar target_lun; /* Device target logical unit number. */
2156 ADV_PADDR data_addr; /* Data buffer physical address. */
2157 ADV_DCNT data_cnt; /* Data count. Ucode sets to residual. */
2158 ADV_PADDR sense_addr;
2159 ADV_PADDR carr_pa;
2160 uchar mflag;
2161 uchar sense_len;
2162 uchar cdb_len; /* SCSI CDB length. Must <= 16 bytes. */
2163 uchar scsi_cntl;
2164 uchar done_status; /* Completion status. */
2165 uchar scsi_status; /* SCSI status byte. */
2166 uchar host_status; /* Ucode host status. */
2167 uchar sg_working_ix;
2168 uchar cdb[12]; /* SCSI CDB bytes 0-11. */
2169 ADV_PADDR sg_real_addr; /* SG list physical address. */
2170 ADV_PADDR scsiq_rptr;
2171 uchar cdb16[4]; /* SCSI CDB bytes 12-15. */
2172 ADV_VADDR scsiq_ptr;
2173 ADV_VADDR carr_va;
2174 /*
2175 * End of microcode structure - 60 bytes. The rest of the structure
2176 * is used by the Adv Library and ignored by the microcode.
2177 */
2178 ADV_VADDR srb_ptr;
2179 ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */
2180 char *vdata_addr; /* Data buffer virtual address. */
2181 uchar a_flag;
2182 uchar pad[2]; /* Pad out to a word boundary. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183} ADV_SCSI_REQ_Q;
2184
2185/*
2186 * Microcode idle loop commands
2187 */
2188#define IDLE_CMD_COMPLETED 0
2189#define IDLE_CMD_STOP_CHIP 0x0001
2190#define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002
2191#define IDLE_CMD_SEND_INT 0x0004
2192#define IDLE_CMD_ABORT 0x0008
2193#define IDLE_CMD_DEVICE_RESET 0x0010
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002194#define IDLE_CMD_SCSI_RESET_START 0x0020 /* Assert SCSI Bus Reset */
2195#define IDLE_CMD_SCSI_RESET_END 0x0040 /* Deassert SCSI Bus Reset */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196#define IDLE_CMD_SCSIREQ 0x0080
2197
2198#define IDLE_CMD_STATUS_SUCCESS 0x0001
2199#define IDLE_CMD_STATUS_FAILURE 0x0002
2200
2201/*
2202 * AdvSendIdleCmd() flag definitions.
2203 */
2204#define ADV_NOWAIT 0x01
2205
2206/*
2207 * Wait loop time out values.
2208 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002209#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */
2210#define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */
2211#define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */
2212#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */
2213#define SCSI_MAX_RETRY 10 /* retry count */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002215#define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */
2216#define ADV_ASYNC_SCSI_BUS_RESET_DET 0x02 /* Detected SCSI Bus Reset. */
2217#define ADV_ASYNC_CARRIER_READY_FAILURE 0x03 /* Carrier Ready failure. */
2218#define ADV_RDMA_IN_CARR_AND_Q_INVALID 0x04 /* RDMAed-in data invalid. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002220#define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002222static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *,
2223 uchar *, ASC_SDCNT *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
2225/*
2226 * Adv Library functions available to drivers.
2227 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002228static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
2229static int AdvISR(ADV_DVC_VAR *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002230static int AdvInitAsc3550Driver(ADV_DVC_VAR *);
2231static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *);
2232static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *);
2233static int AdvResetChipAndSB(ADV_DVC_VAR *);
2234static int AdvResetSB(ADV_DVC_VAR *asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235
2236/*
2237 * Internal Adv Library functions.
2238 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002239static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002240static int AdvInitFrom3550EEP(ADV_DVC_VAR *);
2241static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *);
2242static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *);
2243static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
2244static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *);
2245static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
2246static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *);
2247static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
2248static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *);
2249static void AdvWaitEEPCmd(AdvPortAddr);
2250static ushort AdvReadEEPWord(AdvPortAddr, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252/* Read byte from a register. */
2253#define AdvReadByteRegister(iop_base, reg_off) \
2254 (ADV_MEM_READB((iop_base) + (reg_off)))
2255
2256/* Write byte to a register. */
2257#define AdvWriteByteRegister(iop_base, reg_off, byte) \
2258 (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte)))
2259
2260/* Read word (2 bytes) from a register. */
2261#define AdvReadWordRegister(iop_base, reg_off) \
2262 (ADV_MEM_READW((iop_base) + (reg_off)))
2263
2264/* Write word (2 bytes) to a register. */
2265#define AdvWriteWordRegister(iop_base, reg_off, word) \
2266 (ADV_MEM_WRITEW((iop_base) + (reg_off), (word)))
2267
2268/* Write dword (4 bytes) to a register. */
2269#define AdvWriteDWordRegister(iop_base, reg_off, dword) \
2270 (ADV_MEM_WRITEDW((iop_base) + (reg_off), (dword)))
2271
2272/* Read byte from LRAM. */
2273#define AdvReadByteLram(iop_base, addr, byte) \
2274do { \
2275 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2276 (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \
2277} while (0)
2278
2279/* Write byte to LRAM. */
2280#define AdvWriteByteLram(iop_base, addr, byte) \
2281 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2282 ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte)))
2283
2284/* Read word (2 bytes) from LRAM. */
2285#define AdvReadWordLram(iop_base, addr, word) \
2286do { \
2287 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \
2288 (word) = (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)); \
2289} while (0)
2290
2291/* Write word (2 bytes) to LRAM. */
2292#define AdvWriteWordLram(iop_base, addr, word) \
2293 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2294 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2295
2296/* Write little-endian double word (4 bytes) to LRAM */
2297/* Because of unspecified C language ordering don't use auto-increment. */
2298#define AdvWriteDWordLramNoSwap(iop_base, addr, dword) \
2299 ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \
2300 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2301 cpu_to_le16((ushort) ((dword) & 0xFFFF)))), \
2302 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \
2303 ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \
2304 cpu_to_le16((ushort) ((dword >> 16) & 0xFFFF)))))
2305
2306/* Read word (2 bytes) from LRAM assuming that the address is already set. */
2307#define AdvReadWordAutoIncLram(iop_base) \
2308 (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA))
2309
2310/* Write word (2 bytes) to LRAM assuming that the address is already set. */
2311#define AdvWriteWordAutoIncLram(iop_base, word) \
2312 (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word)))
2313
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314/*
2315 * Define macro to check for Condor signature.
2316 *
2317 * Evaluate to ADV_TRUE if a Condor chip is found the specified port
2318 * address 'iop_base'. Otherwise evalue to ADV_FALSE.
2319 */
2320#define AdvFindSignature(iop_base) \
2321 (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \
2322 ADV_CHIP_ID_BYTE) && \
2323 (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \
2324 ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE)
2325
2326/*
2327 * Define macro to Return the version number of the chip at 'iop_base'.
2328 *
2329 * The second parameter 'bus_type' is currently unused.
2330 */
2331#define AdvGetChipVersion(iop_base, bus_type) \
2332 AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV)
2333
2334/*
2335 * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must
2336 * match the ASC_SCSI_REQ_Q 'srb_ptr' field.
2337 *
2338 * If the request has not yet been sent to the device it will simply be
2339 * aborted from RISC memory. If the request is disconnected it will be
2340 * aborted on reselection by sending an Abort Message to the target ID.
2341 *
2342 * Return value:
2343 * ADV_TRUE(1) - Queue was successfully aborted.
2344 * ADV_FALSE(0) - Queue was not found on the active queue list.
2345 */
2346#define AdvAbortQueue(asc_dvc, scsiq) \
2347 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \
2348 (ADV_DCNT) (scsiq))
2349
2350/*
2351 * Send a Bus Device Reset Message to the specified target ID.
2352 *
2353 * All outstanding commands will be purged if sending the
2354 * Bus Device Reset Message is successful.
2355 *
2356 * Return Value:
2357 * ADV_TRUE(1) - All requests on the target are purged.
2358 * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests
2359 * are not purged.
2360 */
2361#define AdvResetDevice(asc_dvc, target_id) \
2362 AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \
2363 (ADV_DCNT) (target_id))
2364
2365/*
2366 * SCSI Wide Type definition.
2367 */
2368#define ADV_SCSI_BIT_ID_TYPE ushort
2369
2370/*
2371 * AdvInitScsiTarget() 'cntl_flag' options.
2372 */
2373#define ADV_SCAN_LUN 0x01
2374#define ADV_CAPINFO_NOLUN 0x02
2375
2376/*
2377 * Convert target id to target id bit mask.
2378 */
2379#define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID))
2380
2381/*
2382 * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values.
2383 */
2384
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002385#define QD_NO_STATUS 0x00 /* Request not completed yet. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386#define QD_NO_ERROR 0x01
2387#define QD_ABORTED_BY_HOST 0x02
2388#define QD_WITH_ERROR 0x04
2389
2390#define QHSTA_NO_ERROR 0x00
2391#define QHSTA_M_SEL_TIMEOUT 0x11
2392#define QHSTA_M_DATA_OVER_RUN 0x12
2393#define QHSTA_M_UNEXPECTED_BUS_FREE 0x13
2394#define QHSTA_M_QUEUE_ABORTED 0x15
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002395#define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */
2396#define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */
2397#define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */
2398#define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */
2399#define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */
2400#define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */
2401#define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402/* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002403#define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */
2404#define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */
2405#define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */
2406#define QHSTA_M_SCSI_BUS_RESET 0x30 /* Request aborted from SBR */
2407#define QHSTA_M_SCSI_BUS_RESET_UNSOL 0x31 /* Request aborted from unsol. SBR */
2408#define QHSTA_M_BUS_DEVICE_RESET 0x32 /* Request aborted from BDR */
2409#define QHSTA_M_DIRECTION_ERR 0x35 /* Data Phase mismatch */
2410#define QHSTA_M_DIRECTION_ERR_HUNG 0x36 /* Data Phase mismatch and bus hang */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411#define QHSTA_M_WTM_TIMEOUT 0x41
2412#define QHSTA_M_BAD_CMPL_STATUS_IN 0x42
2413#define QHSTA_M_NO_AUTO_REQ_SENSE 0x43
2414#define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002415#define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */
2416#define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */
2417#define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
2419/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 * DvcGetPhyAddr() flag arguments
2421 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002422#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */
2423#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */
2424#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */
2425#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */
2426#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */
2427#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
2429/* Return the address that is aligned at the next doubleword >= to 'addr'. */
2430#define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7)
2431#define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF)
2432#define ADV_32BALIGN(addr) (((ulong) (addr) + 0x1F) & ~0x1F)
2433
2434/*
2435 * Total contiguous memory needed for driver SG blocks.
2436 *
2437 * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum
2438 * number of scatter-gather elements the driver supports in a
2439 * single request.
2440 */
2441
2442#define ADV_SG_LIST_MAX_BYTE_SIZE \
2443 (sizeof(ADV_SG_BLOCK) * \
2444 ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK))
2445
2446/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 * --- Driver Constants and Macros
2448 */
2449
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450/* Reference Scsi_Host hostdata */
2451#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata))
2452
2453/* asc_board_t flags */
2454#define ASC_HOST_IN_RESET 0x01
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002455#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456#define ASC_SELECT_QUEUE_DEPTHS 0x08
2457
2458#define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0)
2459#define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD)
2460
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002461#define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002463#define ASC_INFO_SIZE 128 /* advansys_info() line size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
2465#ifdef CONFIG_PROC_FS
2466/* /proc/scsi/advansys/[0...] related definitions */
2467#define ASC_PRTBUF_SIZE 2048
2468#define ASC_PRTLINE_SIZE 160
2469
2470#define ASC_PRT_NEXT() \
2471 if (cp) { \
2472 totlen += len; \
2473 leftlen -= len; \
2474 if (leftlen == 0) { \
2475 return totlen; \
2476 } \
2477 cp += len; \
2478 }
2479#endif /* CONFIG_PROC_FS */
2480
2481/* Asc Library return codes */
2482#define ASC_TRUE 1
2483#define ASC_FALSE 0
2484#define ASC_NOERROR 1
2485#define ASC_BUSY 0
2486#define ASC_ERROR (-1)
2487
2488/* struct scsi_cmnd function return codes */
2489#define STATUS_BYTE(byte) (byte)
2490#define MSG_BYTE(byte) ((byte) << 8)
2491#define HOST_BYTE(byte) ((byte) << 16)
2492#define DRIVER_BYTE(byte) ((byte) << 24)
2493
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494#ifndef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002495#define ASC_STATS(shost, counter)
2496#define ASC_STATS_ADD(shost, counter, count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497#else /* ADVANSYS_STATS */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002498#define ASC_STATS(shost, counter) \
2499 (ASC_BOARDP(shost)->asc_stats.counter++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002501#define ASC_STATS_ADD(shost, counter, count) \
2502 (ASC_BOARDP(shost)->asc_stats.counter += (count))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503#endif /* ADVANSYS_STATS */
2504
2505#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
2506
2507/* If the result wraps when calculating tenths, return 0. */
2508#define ASC_TENTHS(num, den) \
2509 (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
2510 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
2511
2512/*
2513 * Display a message to the console.
2514 */
2515#define ASC_PRINT(s) \
2516 { \
2517 printk("advansys: "); \
2518 printk(s); \
2519 }
2520
2521#define ASC_PRINT1(s, a1) \
2522 { \
2523 printk("advansys: "); \
2524 printk((s), (a1)); \
2525 }
2526
2527#define ASC_PRINT2(s, a1, a2) \
2528 { \
2529 printk("advansys: "); \
2530 printk((s), (a1), (a2)); \
2531 }
2532
2533#define ASC_PRINT3(s, a1, a2, a3) \
2534 { \
2535 printk("advansys: "); \
2536 printk((s), (a1), (a2), (a3)); \
2537 }
2538
2539#define ASC_PRINT4(s, a1, a2, a3, a4) \
2540 { \
2541 printk("advansys: "); \
2542 printk((s), (a1), (a2), (a3), (a4)); \
2543 }
2544
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545#ifndef ADVANSYS_DEBUG
2546
2547#define ASC_DBG(lvl, s)
2548#define ASC_DBG1(lvl, s, a1)
2549#define ASC_DBG2(lvl, s, a1, a2)
2550#define ASC_DBG3(lvl, s, a1, a2, a3)
2551#define ASC_DBG4(lvl, s, a1, a2, a3, a4)
2552#define ASC_DBG_PRT_SCSI_HOST(lvl, s)
2553#define ASC_DBG_PRT_SCSI_CMND(lvl, s)
2554#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp)
2555#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2556#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone)
2557#define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp)
2558#define ASC_DBG_PRT_HEX(lvl, name, start, length)
2559#define ASC_DBG_PRT_CDB(lvl, cdb, len)
2560#define ASC_DBG_PRT_SENSE(lvl, sense, len)
2561#define ASC_DBG_PRT_INQUIRY(lvl, inq, len)
2562
2563#else /* ADVANSYS_DEBUG */
2564
2565/*
2566 * Debugging Message Levels:
2567 * 0: Errors Only
2568 * 1: High-Level Tracing
2569 * 2-N: Verbose Tracing
2570 */
2571
2572#define ASC_DBG(lvl, s) \
2573 { \
2574 if (asc_dbglvl >= (lvl)) { \
2575 printk(s); \
2576 } \
2577 }
2578
2579#define ASC_DBG1(lvl, s, a1) \
2580 { \
2581 if (asc_dbglvl >= (lvl)) { \
2582 printk((s), (a1)); \
2583 } \
2584 }
2585
2586#define ASC_DBG2(lvl, s, a1, a2) \
2587 { \
2588 if (asc_dbglvl >= (lvl)) { \
2589 printk((s), (a1), (a2)); \
2590 } \
2591 }
2592
2593#define ASC_DBG3(lvl, s, a1, a2, a3) \
2594 { \
2595 if (asc_dbglvl >= (lvl)) { \
2596 printk((s), (a1), (a2), (a3)); \
2597 } \
2598 }
2599
2600#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \
2601 { \
2602 if (asc_dbglvl >= (lvl)) { \
2603 printk((s), (a1), (a2), (a3), (a4)); \
2604 } \
2605 }
2606
2607#define ASC_DBG_PRT_SCSI_HOST(lvl, s) \
2608 { \
2609 if (asc_dbglvl >= (lvl)) { \
2610 asc_prt_scsi_host(s); \
2611 } \
2612 }
2613
2614#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \
2615 { \
2616 if (asc_dbglvl >= (lvl)) { \
2617 asc_prt_scsi_cmnd(s); \
2618 } \
2619 }
2620
2621#define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \
2622 { \
2623 if (asc_dbglvl >= (lvl)) { \
2624 asc_prt_asc_scsi_q(scsiqp); \
2625 } \
2626 }
2627
2628#define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \
2629 { \
2630 if (asc_dbglvl >= (lvl)) { \
2631 asc_prt_asc_qdone_info(qdone); \
2632 } \
2633 }
2634
2635#define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \
2636 { \
2637 if (asc_dbglvl >= (lvl)) { \
2638 asc_prt_adv_scsi_req_q(scsiqp); \
2639 } \
2640 }
2641
2642#define ASC_DBG_PRT_HEX(lvl, name, start, length) \
2643 { \
2644 if (asc_dbglvl >= (lvl)) { \
2645 asc_prt_hex((name), (start), (length)); \
2646 } \
2647 }
2648
2649#define ASC_DBG_PRT_CDB(lvl, cdb, len) \
2650 ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len));
2651
2652#define ASC_DBG_PRT_SENSE(lvl, sense, len) \
2653 ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len));
2654
2655#define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \
2656 ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len));
2657#endif /* ADVANSYS_DEBUG */
2658
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659#ifdef ADVANSYS_STATS
2660
2661/* Per board statistics structure */
2662struct asc_stats {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002663 /* Driver Entrypoint Statistics */
2664 ADV_DCNT queuecommand; /* # calls to advansys_queuecommand() */
2665 ADV_DCNT reset; /* # calls to advansys_eh_bus_reset() */
2666 ADV_DCNT biosparam; /* # calls to advansys_biosparam() */
2667 ADV_DCNT interrupt; /* # advansys_interrupt() calls */
2668 ADV_DCNT callback; /* # calls to asc/adv_isr_callback() */
2669 ADV_DCNT done; /* # calls to request's scsi_done function */
2670 ADV_DCNT build_error; /* # asc/adv_build_req() ASC_ERROR returns. */
2671 ADV_DCNT adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */
2672 ADV_DCNT adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */
2673 /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */
2674 ADV_DCNT exe_noerror; /* # ASC_NOERROR returns. */
2675 ADV_DCNT exe_busy; /* # ASC_BUSY returns. */
2676 ADV_DCNT exe_error; /* # ASC_ERROR returns. */
2677 ADV_DCNT exe_unknown; /* # unknown returns. */
2678 /* Data Transfer Statistics */
2679 ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */
2680 ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */
2681 ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */
2682 ADV_DCNT sg_elem; /* # scatter-gather elements */
2683 ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684};
2685#endif /* ADVANSYS_STATS */
2686
2687/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 * Adv Library Request Structures
2689 *
2690 * The following two structures are used to process Wide Board requests.
2691 *
2692 * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library
2693 * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the
2694 * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the
2695 * Mid-Level SCSI request structure.
2696 *
2697 * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each
2698 * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux
2699 * up to 255 scatter-gather elements may be used per request or
2700 * ADV_SCSI_REQ_Q.
2701 *
2702 * Both structures must be 32 byte aligned.
2703 */
2704typedef struct adv_sgblk {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002705 ADV_SG_BLOCK sg_block; /* Sgblock structure. */
2706 uchar align[32]; /* Sgblock structure padding. */
2707 struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708} adv_sgblk_t;
2709
2710typedef struct adv_req {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002711 ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */
2712 uchar align[32]; /* Request structure padding. */
2713 struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */
2714 adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */
2715 struct adv_req *next_reqp; /* Next Request Structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716} adv_req_t;
2717
2718/*
2719 * Structure allocated for each board.
2720 *
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06002721 * This structure is allocated by scsi_host_alloc() at the end
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 * of the 'Scsi_Host' structure starting at the 'hostdata'
2723 * field. It is guaranteed to be allocated from DMA-able memory.
2724 */
2725typedef struct asc_board {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04002726 struct device *dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002727 int id; /* Board Id */
2728 uint flags; /* Board flags */
2729 union {
2730 ASC_DVC_VAR asc_dvc_var; /* Narrow board */
2731 ADV_DVC_VAR adv_dvc_var; /* Wide board */
2732 } dvc_var;
2733 union {
2734 ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */
2735 ADV_DVC_CFG adv_dvc_cfg; /* Wide board */
2736 } dvc_cfg;
2737 ushort asc_n_io_port; /* Number I/O ports. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002738 ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */
2739 struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */
2740 ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */
2741 ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */
2742 ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */
2743 union {
2744 ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */
2745 ADVEEP_3550_CONFIG adv_3550_eep; /* 3550 EEPROM config. */
2746 ADVEEP_38C0800_CONFIG adv_38C0800_eep; /* 38C0800 EEPROM config. */
2747 ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */
2748 } eep_config;
2749 ulong last_reset; /* Saved last reset time */
2750 spinlock_t lock; /* Board spinlock */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002751 /* /proc/scsi/advansys/[0...] */
2752 char *prtbuf; /* /proc print buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002754 struct asc_stats asc_stats; /* Board statistics */
2755#endif /* ADVANSYS_STATS */
2756 /*
2757 * The following fields are used only for Narrow Boards.
2758 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002759 uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */
2760 /*
2761 * The following fields are used only for Wide Boards.
2762 */
2763 void __iomem *ioremap_addr; /* I/O Memory remap address. */
2764 ushort ioport; /* I/O Port address. */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -06002765 ADV_CARR_T *carrp; /* ADV_CARR_T memory block. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002766 adv_req_t *orig_reqp; /* adv_req_t memory block. */
2767 adv_req_t *adv_reqp; /* Request structures. */
2768 adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */
2769 ushort bios_signature; /* BIOS Signature. */
2770 ushort bios_version; /* BIOS Version. */
2771 ushort bios_codeseg; /* BIOS Code Segment. */
2772 ushort bios_codelen; /* BIOS Code Segment Length. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773} asc_board_t;
2774
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06002775#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \
2776 dvc_var.adv_dvc_var)
2777#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev)
2778
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779/* Number of boards detected in system. */
Matthew Wilcox78e77d82007-07-29 21:46:15 -06002780static int asc_board_count;
2781
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782/* Overrun buffer used by all narrow boards. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002783static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784
2785/*
2786 * Global structures required to issue a command.
2787 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002788static ASC_SCSI_Q asc_scsi_q = { {0} };
2789static ASC_SG_HEAD asc_sg_head = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002792static int asc_dbglvl = 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793#endif /* ADVANSYS_DEBUG */
2794
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795/*
2796 * --- Driver Function Prototypes
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 */
2798
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002799static int advansys_slave_configure(struct scsi_device *);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002800static int asc_execute_scsi_cmnd(struct scsi_cmnd *);
2801static int asc_build_req(asc_board_t *, struct scsi_cmnd *);
2802static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **);
2803static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002805static int asc_proc_copy(off_t, off_t, char *, int, char *, int);
2806static int asc_prt_board_devices(struct Scsi_Host *, char *, int);
2807static int asc_prt_adv_bios(struct Scsi_Host *, char *, int);
2808static int asc_get_eeprom_string(ushort *serialnum, uchar *cp);
2809static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int);
2810static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int);
2811static int asc_prt_driver_conf(struct Scsi_Host *, char *, int);
2812static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int);
2813static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int);
2814static int asc_prt_line(char *, int, char *fmt, ...);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815#endif /* CONFIG_PROC_FS */
2816
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817/* Statistics function prototypes. */
2818#ifdef ADVANSYS_STATS
2819#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002820static int asc_prt_board_stats(struct Scsi_Host *, char *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821#endif /* CONFIG_PROC_FS */
2822#endif /* ADVANSYS_STATS */
2823
2824/* Debug function prototypes. */
2825#ifdef ADVANSYS_DEBUG
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002826static void asc_prt_scsi_host(struct Scsi_Host *);
2827static void asc_prt_scsi_cmnd(struct scsi_cmnd *);
2828static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *);
2829static void asc_prt_asc_dvc_var(ASC_DVC_VAR *);
2830static void asc_prt_asc_scsi_q(ASC_SCSI_Q *);
2831static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *);
2832static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *);
2833static void asc_prt_adv_dvc_var(ADV_DVC_VAR *);
2834static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *);
2835static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *);
2836static void asc_prt_hex(char *f, uchar *, int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837#endif /* ADVANSYS_DEBUG */
2838
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839#ifdef CONFIG_PROC_FS
2840/*
Matthew Wilcoxc304ec92007-07-30 09:18:45 -06002841 * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 *
2843 * *buffer: I/O buffer
2844 * **start: if inout == FALSE pointer into buffer where user read should start
2845 * offset: current offset into a /proc/scsi/advansys/[0...] file
2846 * length: length of buffer
2847 * hostno: Scsi_Host host_no
2848 * inout: TRUE - user is writing; FALSE - user is reading
2849 *
2850 * Return the number of bytes read from or written to a
2851 * /proc/scsi/advansys/[0...] file.
2852 *
2853 * Note: This function uses the per board buffer 'prtbuf' which is
2854 * allocated when the board is initialized in advansys_detect(). The
2855 * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is
2856 * used to write to the buffer. The way asc_proc_copy() is written
2857 * if 'prtbuf' is too small it will not be overwritten. Instead the
2858 * user just won't get all the available statistics.
2859 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07002860static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002862 off_t offset, int length, int inout)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002864 asc_board_t *boardp;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002865 char *cp;
2866 int cplen;
2867 int cnt;
2868 int totcnt;
2869 int leftlen;
2870 char *curbuf;
2871 off_t advoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002872
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002873 ASC_DBG(1, "advansys_proc_info: begin\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002875 /*
2876 * User write not supported.
2877 */
2878 if (inout == TRUE) {
2879 return (-ENOSYS);
2880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002882 /*
2883 * User read of /proc/scsi/advansys/[0...] file.
2884 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885
Matthew Wilcox2a437952007-07-26 11:00:51 -04002886 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002888 /* Copy read data starting at the beginning of the buffer. */
2889 *start = buffer;
2890 curbuf = buffer;
2891 advoffset = 0;
2892 totcnt = 0;
2893 leftlen = length;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002895 /*
2896 * Get board configuration information.
2897 *
2898 * advansys_info() returns the board string from its own static buffer.
2899 */
Matthew Wilcox2a437952007-07-26 11:00:51 -04002900 cp = (char *)advansys_info(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002901 strcat(cp, "\n");
2902 cplen = strlen(cp);
2903 /* Copy board information. */
2904 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2905 totcnt += cnt;
2906 leftlen -= cnt;
2907 if (leftlen == 0) {
2908 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2909 return totcnt;
2910 }
2911 advoffset += cplen;
2912 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002914 /*
2915 * Display Wide Board BIOS Information.
2916 */
2917 if (ASC_WIDE_BOARD(boardp)) {
2918 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04002919 cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002920 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06002921 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002922 cplen);
2923 totcnt += cnt;
2924 leftlen -= cnt;
2925 if (leftlen == 0) {
2926 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2927 return totcnt;
2928 }
2929 advoffset += cplen;
2930 curbuf += cnt;
2931 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002933 /*
2934 * Display driver information for each device attached to the board.
2935 */
2936 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04002937 cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002938 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002939 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2940 totcnt += cnt;
2941 leftlen -= cnt;
2942 if (leftlen == 0) {
2943 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2944 return totcnt;
2945 }
2946 advoffset += cplen;
2947 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002949 /*
2950 * Display EEPROM configuration for the board.
2951 */
2952 cp = boardp->prtbuf;
2953 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04002954 cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002955 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04002956 cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002957 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002958 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002959 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2960 totcnt += cnt;
2961 leftlen -= cnt;
2962 if (leftlen == 0) {
2963 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2964 return totcnt;
2965 }
2966 advoffset += cplen;
2967 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002969 /*
2970 * Display driver configuration and information for the board.
2971 */
2972 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04002973 cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002974 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002975 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2976 totcnt += cnt;
2977 leftlen -= cnt;
2978 if (leftlen == 0) {
2979 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2980 return totcnt;
2981 }
2982 advoffset += cplen;
2983 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984
2985#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002986 /*
2987 * Display driver statistics for the board.
2988 */
2989 cp = boardp->prtbuf;
Matthew Wilcox2a437952007-07-26 11:00:51 -04002990 cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06002991 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04002992 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
2993 totcnt += cnt;
2994 leftlen -= cnt;
2995 if (leftlen == 0) {
2996 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
2997 return totcnt;
2998 }
2999 advoffset += cplen;
3000 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001#endif /* ADVANSYS_STATS */
3002
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003003 /*
3004 * Display Asc Library dynamic configuration information
3005 * for the board.
3006 */
3007 cp = boardp->prtbuf;
3008 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003009 cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003010 } else {
Matthew Wilcox2a437952007-07-26 11:00:51 -04003011 cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003012 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06003013 BUG_ON(cplen >= ASC_PRTBUF_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003014 cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen);
3015 totcnt += cnt;
3016 leftlen -= cnt;
3017 if (leftlen == 0) {
3018 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
3019 return totcnt;
3020 }
3021 advoffset += cplen;
3022 curbuf += cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003024 ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003026 return totcnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027}
3028#endif /* CONFIG_PROC_FS */
3029
3030/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 * advansys_info()
3032 *
3033 * Return suitable for printing on the console with the argument
3034 * adapter's configuration information.
3035 *
3036 * Note: The information line should not exceed ASC_INFO_SIZE bytes,
3037 * otherwise the static 'info' array will be overrun.
3038 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003039static const char *advansys_info(struct Scsi_Host *shost)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003041 static char info[ASC_INFO_SIZE];
3042 asc_board_t *boardp;
3043 ASC_DVC_VAR *asc_dvc_varp;
3044 ADV_DVC_VAR *adv_dvc_varp;
3045 char *busname;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003046 char *widename = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003048 boardp = ASC_BOARDP(shost);
3049 if (ASC_NARROW_BOARD(boardp)) {
3050 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
3051 ASC_DBG(1, "advansys_info: begin\n");
3052 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
3053 if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) ==
3054 ASC_IS_ISAPNP) {
3055 busname = "ISA PnP";
3056 } else {
3057 busname = "ISA";
3058 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003059 sprintf(info,
3060 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X",
3061 ASC_VERSION, busname,
3062 (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003063 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3064 shost->irq, shost->dma_channel);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003065 } else {
3066 if (asc_dvc_varp->bus_type & ASC_IS_VL) {
3067 busname = "VL";
3068 } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
3069 busname = "EISA";
3070 } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
3071 if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
3072 == ASC_IS_PCI_ULTRA) {
3073 busname = "PCI Ultra";
3074 } else {
3075 busname = "PCI";
3076 }
3077 } else {
3078 busname = "?";
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003079 ASC_PRINT2("advansys_info: board %d: unknown "
3080 "bus type %d\n", boardp->id,
3081 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003082 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003083 sprintf(info,
3084 "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X",
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003085 ASC_VERSION, busname, (ulong)shost->io_port,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003086 (ulong)shost->io_port + ASC_IOADR_GAP - 1,
3087 shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003088 }
3089 } else {
3090 /*
3091 * Wide Adapter Information
3092 *
3093 * Memory-mapped I/O is used instead of I/O space to access
3094 * the adapter, but display the I/O Port range. The Memory
3095 * I/O address is displayed through the driver /proc file.
3096 */
3097 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
3098 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003099 widename = "Ultra-Wide";
3100 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003101 widename = "Ultra2-Wide";
3102 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003103 widename = "Ultra3-Wide";
3104 }
3105 sprintf(info,
3106 "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X",
3107 ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base,
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04003108 (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, shost->irq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003109 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06003110 BUG_ON(strlen(info) >= ASC_INFO_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003111 ASC_DBG(1, "advansys_info: end\n");
3112 return info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113}
3114
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003115static void asc_scsi_done(struct scsi_cmnd *scp)
3116{
3117 struct asc_board *boardp = ASC_BOARDP(scp->device->host);
3118
3119 if (scp->use_sg)
3120 dma_unmap_sg(boardp->dev,
3121 (struct scatterlist *)scp->request_buffer,
3122 scp->use_sg, scp->sc_data_direction);
3123 else if (scp->request_bufflen)
3124 dma_unmap_single(boardp->dev, scp->SCp.dma_handle,
3125 scp->request_bufflen, scp->sc_data_direction);
3126
3127 ASC_STATS(scp->device->host, done);
3128
3129 scp->scsi_done(scp);
3130}
3131
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132/*
3133 * advansys_queuecommand() - interrupt-driven I/O entrypoint.
3134 *
3135 * This function always returns 0. Command return status is saved
3136 * in the 'scp' result field.
3137 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003138static int
Matthew Wilcoxb2a7a4b2007-09-09 08:56:35 -06003139advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140{
Matthew Wilcoxb2a7a4b2007-09-09 08:56:35 -06003141 struct Scsi_Host *shost = scp->device->host;
3142 asc_board_t *boardp = ASC_BOARDP(shost);
3143 unsigned long flags;
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003144 int asc_res, result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003146 ASC_STATS(shost, queuecommand);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003147 scp->scsi_done = done;
Matthew Wilcoxb2a7a4b2007-09-09 08:56:35 -06003148
3149 /*
3150 * host_lock taken by mid-level prior to call, but need
3151 * to protect against own ISR
3152 */
3153 spin_lock_irqsave(&boardp->lock, flags);
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003154 asc_res = asc_execute_scsi_cmnd(scp);
Matthew Wilcoxb2a7a4b2007-09-09 08:56:35 -06003155 spin_unlock_irqrestore(&boardp->lock, flags);
3156
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003157 switch (asc_res) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003158 case ASC_NOERROR:
3159 break;
3160 case ASC_BUSY:
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003161 result = SCSI_MLQUEUE_HOST_BUSY;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003162 break;
3163 case ASC_ERROR:
3164 default:
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003165 asc_scsi_done(scp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003166 break;
3167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003169 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170}
3171
3172/*
3173 * advansys_reset()
3174 *
3175 * Reset the bus associated with the command 'scp'.
3176 *
3177 * This function runs its own thread. Interrupts must be blocked but
3178 * sleeping is allowed and no locking other than for host structures is
3179 * required. Returns SUCCESS or FAILED.
3180 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003181static int advansys_reset(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003183 struct Scsi_Host *shost;
3184 asc_board_t *boardp;
3185 ASC_DVC_VAR *asc_dvc_varp;
3186 ADV_DVC_VAR *adv_dvc_varp;
3187 ulong flags;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003188 int status;
3189 int ret = SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003191 ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192
3193#ifdef ADVANSYS_STATS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003194 if (scp->device->host != NULL) {
3195 ASC_STATS(scp->device->host, reset);
3196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197#endif /* ADVANSYS_STATS */
3198
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003199 if ((shost = scp->device->host) == NULL) {
3200 scp->result = HOST_BYTE(DID_ERROR);
3201 return FAILED;
3202 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003204 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003206 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n",
3207 boardp->id);
3208 /*
3209 * Check for re-entrancy.
3210 */
3211 spin_lock_irqsave(&boardp->lock, flags);
3212 if (boardp->flags & ASC_HOST_IN_RESET) {
3213 spin_unlock_irqrestore(&boardp->lock, flags);
3214 return FAILED;
3215 }
3216 boardp->flags |= ASC_HOST_IN_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003219 if (ASC_NARROW_BOARD(boardp)) {
3220 /*
3221 * Narrow Board
3222 */
3223 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003225 /*
3226 * Reset the chip and SCSI bus.
3227 */
3228 ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n");
3229 status = AscInitAsc1000Driver(asc_dvc_varp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003231 /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */
3232 if (asc_dvc_varp->err_code) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003233 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
3234 "error: 0x%x\n", boardp->id,
3235 asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003236 ret = FAILED;
3237 } else if (status) {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003238 ASC_PRINT2("advansys_reset: board %d: SCSI bus reset "
3239 "warning: 0x%x\n", boardp->id, status);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003240 } else {
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003241 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3242 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003245 ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n");
3246 spin_lock_irqsave(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003248 } else {
3249 /*
3250 * Wide Board
3251 *
3252 * If the suggest reset bus flags are set, then reset the bus.
3253 * Otherwise only reset the device.
3254 */
3255 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003257 /*
3258 * Reset the target's SCSI bus.
3259 */
3260 ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n");
3261 switch (AdvResetChipAndSB(adv_dvc_varp)) {
3262 case ASC_TRUE:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003263 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3264 "successful.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003265 break;
3266 case ASC_FALSE:
3267 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003268 ASC_PRINT1("advansys_reset: board %d: SCSI bus reset "
3269 "error.\n", boardp->id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003270 ret = FAILED;
3271 break;
3272 }
3273 spin_lock_irqsave(&boardp->lock, flags);
3274 (void)AdvISR(adv_dvc_varp);
3275 }
3276 /* Board lock is held. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003278 /* Save the time of the most recently completed reset. */
3279 boardp->last_reset = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003281 /* Clear reset flag. */
3282 boardp->flags &= ~ASC_HOST_IN_RESET;
3283 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003285 ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003287 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288}
3289
3290/*
3291 * advansys_biosparam()
3292 *
3293 * Translate disk drive geometry if the "BIOS greater than 1 GB"
3294 * support is enabled for a drive.
3295 *
3296 * ip (information pointer) is an int array with the following definition:
3297 * ip[0]: heads
3298 * ip[1]: sectors
3299 * ip[2]: cylinders
3300 */
Adrian Bunk70c8d892007-05-23 14:41:35 -07003301static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003303 sector_t capacity, int ip[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003305 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003307 ASC_DBG(1, "advansys_biosparam: begin\n");
3308 ASC_STATS(sdev->host, biosparam);
3309 boardp = ASC_BOARDP(sdev->host);
3310 if (ASC_NARROW_BOARD(boardp)) {
3311 if ((boardp->dvc_var.asc_dvc_var.dvc_cntl &
3312 ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) {
3313 ip[0] = 255;
3314 ip[1] = 63;
3315 } else {
3316 ip[0] = 64;
3317 ip[1] = 32;
3318 }
3319 } else {
3320 if ((boardp->dvc_var.adv_dvc_var.bios_ctrl &
3321 BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) {
3322 ip[0] = 255;
3323 ip[1] = 63;
3324 } else {
3325 ip[0] = 64;
3326 ip[1] = 32;
3327 }
3328 }
3329 ip[2] = (unsigned long)capacity / (ip[0] * ip[1]);
3330 ASC_DBG(1, "advansys_biosparam: end\n");
3331 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332}
3333
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003334static struct scsi_host_template advansys_template = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003335 .proc_name = "advansys",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336#ifdef CONFIG_PROC_FS
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003337 .proc_info = advansys_proc_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338#endif
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003339 .name = "advansys",
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003340 .info = advansys_info,
3341 .queuecommand = advansys_queuecommand,
3342 .eh_bus_reset_handler = advansys_reset,
3343 .bios_param = advansys_biosparam,
3344 .slave_configure = advansys_slave_configure,
3345 /*
3346 * Because the driver may control an ISA adapter 'unchecked_isa_dma'
Matthew Wilcox8dfb5372007-07-30 09:08:34 -06003347 * must be set. The flag will be cleared in advansys_board_found
3348 * for non-ISA adapters.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003349 */
3350 .unchecked_isa_dma = 1,
3351 /*
3352 * All adapters controlled by this driver are capable of large
3353 * scatter-gather lists. According to the mid-level SCSI documentation
3354 * this obviates any performance gain provided by setting
3355 * 'use_clustering'. But empirically while CPU utilization is increased
3356 * by enabling clustering, I/O throughput increases as well.
3357 */
3358 .use_clustering = ENABLE_CLUSTERING,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361/*
3362 * --- Miscellaneous Driver Functions
3363 */
3364
3365/*
3366 * First-level interrupt handler.
3367 *
3368 * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because
3369 * all boards are currently checked for interrupts on each interrupt, 'dev_id'
3370 * is not referenced. 'dev_id' could be used to identify an interrupt passed
3371 * to the AdvanSys driver which is for a device sharing an interrupt with
3372 * an AdvanSys adapter.
3373 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003374static irqreturn_t advansys_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375{
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003376 unsigned long flags;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003377 struct Scsi_Host *shost = dev_id;
3378 asc_board_t *boardp = ASC_BOARDP(shost);
3379 irqreturn_t result = IRQ_NONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003381 ASC_DBG1(2, "advansys_interrupt: boardp 0x%p\n", boardp);
3382 spin_lock_irqsave(&boardp->lock, flags);
3383 if (ASC_NARROW_BOARD(boardp)) {
3384 /*
3385 * Narrow Board
3386 */
3387 if (AscIsIntPending(shost->io_port)) {
3388 result = IRQ_HANDLED;
3389 ASC_STATS(shost, interrupt);
3390 ASC_DBG(1, "advansys_interrupt: before AscISR()\n");
3391 AscISR(&boardp->dvc_var.asc_dvc_var);
3392 }
3393 } else {
3394 /*
3395 * Wide Board
3396 */
3397 ASC_DBG(1, "advansys_interrupt: before AdvISR()\n");
3398 if (AdvISR(&boardp->dvc_var.adv_dvc_var)) {
3399 result = IRQ_HANDLED;
3400 ASC_STATS(shost, interrupt);
3401 }
3402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003404 spin_unlock_irqrestore(&boardp->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003406 /*
3407 * If interrupts were enabled on entry, then they
3408 * are now enabled here.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003409 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003411 ASC_DBG(1, "advansys_interrupt: end\n");
Matthew Wilcox074c8fe2007-07-28 23:11:05 -06003412 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413}
3414
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003415static void
3416advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc)
3417{
3418 ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id;
3419 ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng;
3420
3421 if (sdev->lun == 0) {
3422 ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr;
3423 if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) {
3424 asc_dvc->init_sdtr |= tid_bit;
3425 } else {
3426 asc_dvc->init_sdtr &= ~tid_bit;
3427 }
3428
3429 if (orig_init_sdtr != asc_dvc->init_sdtr)
3430 AscAsyncFix(asc_dvc, sdev);
3431 }
3432
3433 if (sdev->tagged_supported) {
3434 if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) {
3435 if (sdev->lun == 0) {
3436 asc_dvc->cfg->can_tagged_qng |= tid_bit;
3437 asc_dvc->use_tagged_qng |= tid_bit;
3438 }
3439 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
3440 asc_dvc->max_dvc_qng[sdev->id]);
3441 }
3442 } else {
3443 if (sdev->lun == 0) {
3444 asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
3445 asc_dvc->use_tagged_qng &= ~tid_bit;
3446 }
3447 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
3448 }
3449
3450 if ((sdev->lun == 0) &&
3451 (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) {
3452 AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
3453 asc_dvc->cfg->disc_enable);
3454 AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
3455 asc_dvc->use_tagged_qng);
3456 AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
3457 asc_dvc->cfg->can_tagged_qng);
3458
3459 asc_dvc->max_dvc_qng[sdev->id] =
3460 asc_dvc->cfg->max_tag_qng[sdev->id];
3461 AscWriteLramByte(asc_dvc->iop_base,
3462 (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id),
3463 asc_dvc->max_dvc_qng[sdev->id]);
3464 }
3465}
3466
3467/*
3468 * Wide Transfers
3469 *
3470 * If the EEPROM enabled WDTR for the device and the device supports wide
3471 * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and
3472 * write the new value to the microcode.
3473 */
3474static void
3475advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask)
3476{
3477 unsigned short cfg_word;
3478 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
3479 if ((cfg_word & tidmask) != 0)
3480 return;
3481
3482 cfg_word |= tidmask;
3483 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word);
3484
3485 /*
3486 * Clear the microcode SDTR and WDTR negotiation done indicators for
3487 * the target to cause it to negotiate with the new setting set above.
3488 * WDTR when accepted causes the target to enter asynchronous mode, so
3489 * SDTR must be negotiated.
3490 */
3491 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3492 cfg_word &= ~tidmask;
3493 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3494 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
3495 cfg_word &= ~tidmask;
3496 AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word);
3497}
3498
3499/*
3500 * Synchronous Transfers
3501 *
3502 * If the EEPROM enabled SDTR for the device and the device
3503 * supports synchronous transfers, then turn on the device's
3504 * 'sdtr_able' bit. Write the new value to the microcode.
3505 */
3506static void
3507advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask)
3508{
3509 unsigned short cfg_word;
3510 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
3511 if ((cfg_word & tidmask) != 0)
3512 return;
3513
3514 cfg_word |= tidmask;
3515 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word);
3516
3517 /*
3518 * Clear the microcode "SDTR negotiation" done indicator for the
3519 * target to cause it to negotiate with the new setting set above.
3520 */
3521 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3522 cfg_word &= ~tidmask;
3523 AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word);
3524}
3525
3526/*
3527 * PPR (Parallel Protocol Request) Capable
3528 *
3529 * If the device supports DT mode, then it must be PPR capable.
3530 * The PPR message will be used in place of the SDTR and WDTR
3531 * messages to negotiate synchronous speed and offset, transfer
3532 * width, and protocol options.
3533 */
3534static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc,
3535 AdvPortAddr iop_base, unsigned short tidmask)
3536{
3537 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
3538 adv_dvc->ppr_able |= tidmask;
3539 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able);
3540}
3541
3542static void
3543advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc)
3544{
3545 AdvPortAddr iop_base = adv_dvc->iop_base;
3546 unsigned short tidmask = 1 << sdev->id;
3547
3548 if (sdev->lun == 0) {
3549 /*
3550 * Handle WDTR, SDTR, and Tag Queuing. If the feature
3551 * is enabled in the EEPROM and the device supports the
3552 * feature, then enable it in the microcode.
3553 */
3554
3555 if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr)
3556 advansys_wide_enable_wdtr(iop_base, tidmask);
3557 if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr)
3558 advansys_wide_enable_sdtr(iop_base, tidmask);
3559 if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr)
3560 advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask);
3561
3562 /*
3563 * Tag Queuing is disabled for the BIOS which runs in polled
3564 * mode and would see no benefit from Tag Queuing. Also by
3565 * disabling Tag Queuing in the BIOS devices with Tag Queuing
3566 * bugs will at least work with the BIOS.
3567 */
3568 if ((adv_dvc->tagqng_able & tidmask) &&
3569 sdev->tagged_supported) {
3570 unsigned short cfg_word;
3571 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word);
3572 cfg_word |= tidmask;
3573 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
3574 cfg_word);
3575 AdvWriteByteLram(iop_base,
3576 ASC_MC_NUMBER_OF_MAX_CMD + sdev->id,
3577 adv_dvc->max_dvc_qng);
3578 }
3579 }
3580
3581 if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) {
3582 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG,
3583 adv_dvc->max_dvc_qng);
3584 } else {
3585 scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
3586 }
3587}
3588
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589/*
3590 * Set the number of commands to queue per device for the
3591 * specified host adapter.
3592 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003593static int advansys_slave_configure(struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003594{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003595 asc_board_t *boardp = ASC_BOARDP(sdev->host);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003596 boardp->flags |= ASC_SELECT_QUEUE_DEPTHS;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003597
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003598 /*
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003599 * Save a pointer to the sdev and set its initial/maximum
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003600 * queue depth. Only save the pointer for a lun0 dev though.
3601 */
Matthew Wilcox47d853c2007-07-26 11:41:33 -04003602 if (sdev->lun == 0)
3603 boardp->device[sdev->id] = sdev;
3604
3605 if (ASC_NARROW_BOARD(boardp))
3606 advansys_narrow_slave_configure(sdev,
3607 &boardp->dvc_var.asc_dvc_var);
3608 else
3609 advansys_wide_slave_configure(sdev,
3610 &boardp->dvc_var.adv_dvc_var);
3611
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003612 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613}
3614
3615/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 * Execute a single 'Scsi_Cmnd'.
3617 *
3618 * The function 'done' is called when the request has been completed.
3619 *
3620 * Scsi_Cmnd:
3621 *
3622 * host - board controlling device
3623 * device - device to send command
3624 * target - target of device
3625 * lun - lun of device
3626 * cmd_len - length of SCSI CDB
3627 * cmnd - buffer for SCSI 8, 10, or 12 byte CDB
3628 * use_sg - if non-zero indicates scatter-gather request with use_sg elements
3629 *
3630 * if (use_sg == 0) {
3631 * request_buffer - buffer address for request
3632 * request_bufflen - length of request buffer
3633 * } else {
3634 * request_buffer - pointer to scatterlist structure
3635 * }
3636 *
3637 * sense_buffer - sense command buffer
3638 *
3639 * result (4 bytes of an int):
3640 * Byte Meaning
3641 * 0 SCSI Status Byte Code
3642 * 1 SCSI One Byte Message Code
3643 * 2 Host Error Code
3644 * 3 Mid-Level Error Code
3645 *
3646 * host driver fields:
3647 * SCp - Scsi_Pointer used for command processing status
3648 * scsi_done - used to save caller's done function
3649 * host_scribble - used for pointer to another struct scsi_cmnd
3650 *
Matthew Wilcox349d2c42007-09-09 08:56:34 -06003651 * If this function returns ASC_NOERROR the request will be completed
3652 * from the interrupt handler.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 *
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003654 * If this function returns ASC_ERROR the host error code has been set,
3655 * and the called must call asc_scsi_done.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 *
Matthew Wilcoxb6622922007-09-09 08:56:31 -06003657 * If ASC_BUSY is returned the request will be returned to the midlayer
3658 * and re-tried later.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003660static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003662 asc_board_t *boardp;
3663 ASC_DVC_VAR *asc_dvc_varp;
3664 ADV_DVC_VAR *adv_dvc_varp;
3665 ADV_SCSI_REQ_Q *adv_scsiqp;
3666 struct scsi_device *device;
3667 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003669 ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n",
3670 (ulong)scp, (ulong)scp->scsi_done);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003672 boardp = ASC_BOARDP(scp->device->host);
3673 device = boardp->device[scp->device->id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003675 if (ASC_NARROW_BOARD(boardp)) {
3676 /*
3677 * Build and execute Narrow Board request.
3678 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003680 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003682 /*
3683 * Build Asc Library request structure using the
3684 * global structures 'asc_scsi_req' and 'asc_sg_head'.
3685 *
3686 * If an error is returned, then the request has been
3687 * queued on the board done queue. It will be completed
3688 * by the caller.
3689 *
3690 * asc_build_req() can not return ASC_BUSY.
3691 */
3692 if (asc_build_req(boardp, scp) == ASC_ERROR) {
3693 ASC_STATS(scp->device->host, build_error);
3694 return ASC_ERROR;
3695 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003697 switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
3698 case ASC_NOERROR:
3699 ASC_STATS(scp->device->host, exe_noerror);
3700 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003701 * Increment monotonically increasing per device
3702 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003703 */
3704 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003705 ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), "
3706 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003707 break;
3708 case ASC_BUSY:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003709 ASC_STATS(scp->device->host, exe_busy);
3710 break;
3711 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003712 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3713 "AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
3714 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003715 ASC_STATS(scp->device->host, exe_error);
3716 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003717 break;
3718 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003719 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3720 "AscExeScsiQueue() unknown, err_code 0x%x\n",
3721 boardp->id, asc_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003722 ASC_STATS(scp->device->host, exe_unknown);
3723 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003724 break;
3725 }
3726 } else {
3727 /*
3728 * Build and execute Wide Board request.
3729 */
3730 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003732 /*
3733 * Build and get a pointer to an Adv Library request structure.
3734 *
3735 * If the request is successfully built then send it below,
3736 * otherwise return with an error.
3737 */
3738 switch (adv_build_req(boardp, scp, &adv_scsiqp)) {
3739 case ASC_NOERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003740 ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req "
3741 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003742 break;
3743 case ASC_BUSY:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003744 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
3745 "ASC_BUSY\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003746 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003747 * The asc_stats fields 'adv_build_noreq' and
3748 * 'adv_build_nosg' count wide board busy conditions.
3749 * They are updated in adv_build_req and
3750 * adv_get_sglist, respectively.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003751 */
3752 return ASC_BUSY;
3753 case ASC_ERROR:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003754 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003755 ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req "
3756 "ASC_ERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003757 ASC_STATS(scp->device->host, build_error);
3758 return ASC_ERROR;
3759 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003761 switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) {
3762 case ASC_NOERROR:
3763 ASC_STATS(scp->device->host, exe_noerror);
3764 /*
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003765 * Increment monotonically increasing per device
3766 * successful request counter. Wrapping doesn't matter.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003767 */
3768 boardp->reqcnt[scp->device->id]++;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003769 ASC_DBG(1, "asc_execute_scsi_cmnd: AdvExeScsiQueue(), "
3770 "ASC_NOERROR\n");
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003771 break;
3772 case ASC_BUSY:
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003773 ASC_STATS(scp->device->host, exe_busy);
3774 break;
3775 case ASC_ERROR:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003776 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3777 "AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n",
3778 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003779 ASC_STATS(scp->device->host, exe_error);
3780 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003781 break;
3782 default:
Matthew Wilcoxecec1942007-07-30 08:08:22 -06003783 ASC_PRINT2("asc_execute_scsi_cmnd: board %d: "
3784 "AdvExeScsiQueue() unknown, err_code 0x%x\n",
3785 boardp->id, adv_dvc_varp->err_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003786 ASC_STATS(scp->device->host, exe_unknown);
3787 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003788 break;
3789 }
3790 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003792 ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
3793 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794}
3795
3796/*
3797 * Build a request structure for the Asc Library (Narrow Board).
3798 *
3799 * The global structures 'asc_scsi_q' and 'asc_sg_head' are
3800 * used to build the request.
3801 *
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06003802 * If an error occurs, then return ASC_ERROR.
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003804static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003806 /*
3807 * Mutually exclusive access is required to 'asc_scsi_q' and
3808 * 'asc_sg_head' until after the request is started.
3809 */
3810 memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003812 /*
3813 * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'.
3814 */
3815 asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003817 /*
3818 * Build the ASC_SCSI_Q request.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003819 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003820 asc_scsi_q.cdbptr = &scp->cmnd[0];
3821 asc_scsi_q.q2.cdb_len = scp->cmd_len;
3822 asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id);
3823 asc_scsi_q.q1.target_lun = scp->device->lun;
3824 asc_scsi_q.q2.target_ix =
3825 ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun);
3826 asc_scsi_q.q1.sense_addr =
3827 cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
3828 asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003830 /*
3831 * If there are any outstanding requests for the current target,
3832 * then every 255th request send an ORDERED request. This heuristic
3833 * tries to retain the benefit of request sorting while preventing
3834 * request starvation. 255 is the max number of tags or pending commands
3835 * a device may have outstanding.
3836 *
3837 * The request count is incremented below for every successfully
3838 * started request.
3839 *
3840 */
3841 if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) &&
3842 (boardp->reqcnt[scp->device->id] % 255) == 0) {
3843 asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG;
3844 } else {
3845 asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG;
3846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003848 /*
3849 * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
3850 * buffer command.
3851 */
3852 if (scp->use_sg == 0) {
3853 /*
3854 * CDB request of single contiguous buffer.
3855 */
3856 ASC_STATS(scp->device->host, cont_cnt);
3857 scp->SCp.dma_handle = scp->request_bufflen ?
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003858 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003859 scp->request_bufflen,
3860 scp->sc_data_direction) : 0;
3861 asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle);
3862 asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen);
3863 ASC_STATS_ADD(scp->device->host, cont_xfer,
3864 ASC_CEILING(scp->request_bufflen, 512));
3865 asc_scsi_q.q1.sg_queue_cnt = 0;
3866 asc_scsi_q.sg_head = NULL;
3867 } else {
3868 /*
3869 * CDB scatter-gather request list.
3870 */
3871 int sgcnt;
3872 int use_sg;
3873 struct scatterlist *slp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003874
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003875 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003876 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
3877 scp->sc_data_direction);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003879 if (use_sg > scp->device->host->sg_tablesize) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04003880 ASC_PRINT3("asc_build_req: board %d: use_sg %d > "
3881 "sg_tablesize %d\n", boardp->id, use_sg,
3882 scp->device->host->sg_tablesize);
3883 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003884 scp->sc_data_direction);
3885 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003886 return ASC_ERROR;
3887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003889 ASC_STATS(scp->device->host, sg_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003891 /*
3892 * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q
3893 * structure to point to it.
3894 */
3895 memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003897 asc_scsi_q.q1.cntl |= QC_SG_HEAD;
3898 asc_scsi_q.sg_head = &asc_sg_head;
3899 asc_scsi_q.q1.data_cnt = 0;
3900 asc_scsi_q.q1.data_addr = 0;
3901 /* This is a byte value, otherwise it would need to be swapped. */
3902 asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg;
3903 ASC_STATS_ADD(scp->device->host, sg_elem,
3904 asc_sg_head.entry_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003906 /*
3907 * Convert scatter-gather list into ASC_SG_HEAD list.
3908 */
3909 for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) {
3910 asc_sg_head.sg_list[sgcnt].addr =
3911 cpu_to_le32(sg_dma_address(slp));
3912 asc_sg_head.sg_list[sgcnt].bytes =
3913 cpu_to_le32(sg_dma_len(slp));
3914 ASC_STATS_ADD(scp->device->host, sg_xfer,
3915 ASC_CEILING(sg_dma_len(slp), 512));
3916 }
3917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003919 ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q);
3920 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003922 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923}
3924
3925/*
3926 * Build a request structure for the Adv Library (Wide Board).
3927 *
3928 * If an adv_req_t can not be allocated to issue the request,
3929 * then return ASC_BUSY. If an error occurs, then return ASC_ERROR.
3930 *
3931 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the
3932 * microcode for DMA addresses or math operations are byte swapped
3933 * to little-endian order.
3934 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003935static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07003936adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003937 ADV_SCSI_REQ_Q **adv_scsiqpp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003939 adv_req_t *reqp;
3940 ADV_SCSI_REQ_Q *scsiqp;
3941 int i;
3942 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003943
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003944 /*
3945 * Allocate an adv_req_t structure from the board to execute
3946 * the command.
3947 */
3948 if (boardp->adv_reqp == NULL) {
3949 ASC_DBG(1, "adv_build_req: no free adv_req_t\n");
3950 ASC_STATS(scp->device->host, adv_build_noreq);
3951 return ASC_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003952 } else {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003953 reqp = boardp->adv_reqp;
3954 boardp->adv_reqp = reqp->next_reqp;
3955 reqp->next_reqp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003958 /*
3959 * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers.
3960 */
3961 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003963 /*
3964 * Initialize the structure.
3965 */
3966 scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003968 /*
3969 * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure.
3970 */
3971 scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003973 /*
3974 * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure.
3975 */
3976 reqp->cmndp = scp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003978 /*
3979 * Build the ADV_SCSI_REQ_Q request.
3980 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003981
Matthew Wilcoxf05ec592007-09-09 08:56:36 -06003982 /* Set CDB length and copy it to the request structure. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003983 scsiqp->cdb_len = scp->cmd_len;
3984 /* Copy first 12 CDB bytes to cdb[]. */
3985 for (i = 0; i < scp->cmd_len && i < 12; i++) {
3986 scsiqp->cdb[i] = scp->cmnd[i];
3987 }
3988 /* Copy last 4 CDB bytes, if present, to cdb16[]. */
3989 for (; i < scp->cmd_len; i++) {
3990 scsiqp->cdb16[i - 12] = scp->cmnd[i];
3991 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003993 scsiqp->target_id = scp->device->id;
3994 scsiqp->target_lun = scp->device->lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003996 scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0]));
3997 scsiqp->sense_len = sizeof(scp->sense_buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003998
Matthew Wilcox27c868c2007-07-26 10:56:23 -04003999 /*
4000 * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather
4001 * buffer command.
4002 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004004 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4005 scsiqp->vdata_addr = scp->request_buffer;
4006 scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer));
4007
4008 if (scp->use_sg == 0) {
4009 /*
4010 * CDB request of single contiguous buffer.
4011 */
4012 reqp->sgblkp = NULL;
4013 scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen);
4014 if (scp->request_bufflen) {
4015 scsiqp->vdata_addr = scp->request_buffer;
4016 scp->SCp.dma_handle =
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004017 dma_map_single(boardp->dev, scp->request_buffer,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004018 scp->request_bufflen,
4019 scp->sc_data_direction);
4020 } else {
4021 scsiqp->vdata_addr = NULL;
4022 scp->SCp.dma_handle = 0;
4023 }
4024 scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle);
4025 scsiqp->sg_list_ptr = NULL;
4026 scsiqp->sg_real_addr = 0;
4027 ASC_STATS(scp->device->host, cont_cnt);
4028 ASC_STATS_ADD(scp->device->host, cont_xfer,
4029 ASC_CEILING(scp->request_bufflen, 512));
4030 } else {
4031 /*
4032 * CDB scatter-gather request list.
4033 */
4034 struct scatterlist *slp;
4035 int use_sg;
4036
4037 slp = (struct scatterlist *)scp->request_buffer;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004038 use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg,
4039 scp->sc_data_direction);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004040
4041 if (use_sg > ADV_MAX_SG_LIST) {
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004042 ASC_PRINT3("adv_build_req: board %d: use_sg %d > "
4043 "ADV_MAX_SG_LIST %d\n", boardp->id, use_sg,
4044 scp->device->host->sg_tablesize);
4045 dma_unmap_sg(boardp->dev, slp, scp->use_sg,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004046 scp->sc_data_direction);
4047 scp->result = HOST_BYTE(DID_ERROR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004048
4049 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004050 * Free the 'adv_req_t' structure by adding it back
4051 * to the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004052 */
4053 reqp->next_reqp = boardp->adv_reqp;
4054 boardp->adv_reqp = reqp;
4055
4056 return ASC_ERROR;
4057 }
4058
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004059 ret = adv_get_sglist(boardp, reqp, scp, use_sg);
4060 if (ret != ADV_SUCCESS) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004061 /*
Matthew Wilcox394dbf32007-07-26 11:56:40 -04004062 * Free the adv_req_t structure by adding it back to
4063 * the board free list.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004064 */
4065 reqp->next_reqp = boardp->adv_reqp;
4066 boardp->adv_reqp = reqp;
4067
4068 return ret;
4069 }
4070
4071 ASC_STATS(scp->device->host, sg_cnt);
4072 ASC_STATS_ADD(scp->device->host, sg_elem, use_sg);
4073 }
4074
4075 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
4076 ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len);
4077
4078 *adv_scsiqpp = scsiqp;
4079
4080 return ASC_NOERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081}
4082
4083/*
4084 * Build scatter-gather list for Adv Library (Wide Board).
4085 *
4086 * Additional ADV_SG_BLOCK structures will need to be allocated
4087 * if the total number of scatter-gather elements exceeds
4088 * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are
4089 * assumed to be physically contiguous.
4090 *
4091 * Return:
4092 * ADV_SUCCESS(1) - SG List successfully created
4093 * ADV_ERROR(-1) - SG List creation failed
4094 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004095static int
4096adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp,
4097 int use_sg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004099 adv_sgblk_t *sgblkp;
4100 ADV_SCSI_REQ_Q *scsiqp;
4101 struct scatterlist *slp;
4102 int sg_elem_cnt;
4103 ADV_SG_BLOCK *sg_block, *prev_sg_block;
4104 ADV_PADDR sg_block_paddr;
4105 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004107 scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q);
4108 slp = (struct scatterlist *)scp->request_buffer;
4109 sg_elem_cnt = use_sg;
4110 prev_sg_block = NULL;
4111 reqp->sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004113 do {
4114 /*
4115 * Allocate a 'adv_sgblk_t' structure from the board free
4116 * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK
4117 * (15) scatter-gather elements.
4118 */
4119 if ((sgblkp = boardp->adv_sgblkp) == NULL) {
4120 ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n");
4121 ASC_STATS(scp->device->host, adv_build_nosg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004123 /*
4124 * Allocation failed. Free 'adv_sgblk_t' structures already
4125 * allocated for the request.
4126 */
4127 while ((sgblkp = reqp->sgblkp) != NULL) {
4128 /* Remove 'sgblkp' from the request list. */
4129 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004131 /* Add 'sgblkp' to the board free list. */
4132 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4133 boardp->adv_sgblkp = sgblkp;
4134 }
4135 return ASC_BUSY;
4136 } else {
4137 /* Complete 'adv_sgblk_t' board allocation. */
4138 boardp->adv_sgblkp = sgblkp->next_sgblkp;
4139 sgblkp->next_sgblkp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004141 /*
4142 * Get 8 byte aligned virtual and physical addresses for
4143 * the allocated ADV_SG_BLOCK structure.
4144 */
4145 sg_block =
4146 (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block);
4147 sg_block_paddr = virt_to_bus(sg_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004149 /*
4150 * Check if this is the first 'adv_sgblk_t' for the request.
4151 */
4152 if (reqp->sgblkp == NULL) {
4153 /* Request's first scatter-gather block. */
4154 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004156 /*
4157 * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical
4158 * address pointers.
4159 */
4160 scsiqp->sg_list_ptr = sg_block;
4161 scsiqp->sg_real_addr =
4162 cpu_to_le32(sg_block_paddr);
4163 } else {
4164 /* Request's second or later scatter-gather block. */
4165 sgblkp->next_sgblkp = reqp->sgblkp;
4166 reqp->sgblkp = sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004168 /*
4169 * Point the previous ADV_SG_BLOCK structure to
4170 * the newly allocated ADV_SG_BLOCK structure.
4171 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004172 prev_sg_block->sg_ptr =
4173 cpu_to_le32(sg_block_paddr);
4174 }
4175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004177 for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) {
4178 sg_block->sg_list[i].sg_addr =
4179 cpu_to_le32(sg_dma_address(slp));
4180 sg_block->sg_list[i].sg_count =
4181 cpu_to_le32(sg_dma_len(slp));
4182 ASC_STATS_ADD(scp->device->host, sg_xfer,
4183 ASC_CEILING(sg_dma_len(slp), 512));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004185 if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */
4186 sg_block->sg_cnt = i + 1;
4187 sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */
4188 return ADV_SUCCESS;
4189 }
4190 slp++;
4191 }
4192 sg_block->sg_cnt = NO_OF_SG_PER_BLOCK;
4193 prev_sg_block = sg_block;
4194 }
4195 while (1);
4196 /* NOTREACHED */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197}
4198
4199/*
4200 * asc_isr_callback() - Second Level Interrupt Handler called by AscISR().
4201 *
4202 * Interrupt callback function for the Narrow SCSI Asc Library.
4203 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004204static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004206 asc_board_t *boardp;
4207 struct scsi_cmnd *scp;
4208 struct Scsi_Host *shost;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004210 ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n",
4211 (ulong)asc_dvc_varp, (ulong)qdonep);
4212 ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004214 /*
4215 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4216 * command that has been completed.
4217 */
4218 scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr);
4219 ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004220
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004221 if (scp == NULL) {
4222 ASC_PRINT("asc_isr_callback: scp is NULL\n");
4223 return;
4224 }
4225 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004227 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004228 ASC_STATS(shost, callback);
4229 ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004231 boardp = ASC_BOARDP(shost);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06004232 BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004234 /*
4235 * 'qdonep' contains the command's ending status.
4236 */
4237 switch (qdonep->d3.done_stat) {
4238 case QD_NO_ERROR:
4239 ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n");
4240 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004242 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004243 * Check for an underrun condition.
4244 *
4245 * If there was no error and an underrun condition, then
Matthew Wilcox47d853c2007-07-26 11:41:33 -04004246 * return the number of underrun bytes.
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004247 */
4248 if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 &&
4249 qdonep->remain_bytes <= scp->request_bufflen) {
4250 ASC_DBG1(1,
4251 "asc_isr_callback: underrun condition %u bytes\n",
4252 (unsigned)qdonep->remain_bytes);
4253 scp->resid = qdonep->remain_bytes;
4254 }
4255 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004257 case QD_WITH_ERROR:
4258 ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n");
4259 switch (qdonep->d3.host_stat) {
4260 case QHSTA_NO_ERROR:
4261 if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) {
4262 ASC_DBG(2,
4263 "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4264 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4265 sizeof(scp->sense_buffer));
4266 /*
4267 * Note: The 'status_byte()' macro used by target drivers
4268 * defined in scsi.h shifts the status byte returned by
4269 * host drivers right by 1 bit. This is why target drivers
4270 * also use right shifted status byte definitions. For
4271 * instance target drivers use CHECK_CONDITION, defined to
4272 * 0x1, instead of the SCSI defined check condition value
4273 * of 0x2. Host drivers are supposed to return the status
4274 * byte as it is defined by SCSI.
4275 */
4276 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4277 STATUS_BYTE(qdonep->d3.scsi_stat);
4278 } else {
4279 scp->result = STATUS_BYTE(qdonep->d3.scsi_stat);
4280 }
4281 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004283 default:
4284 /* QHSTA error occurred */
4285 ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n",
4286 qdonep->d3.host_stat);
4287 scp->result = HOST_BYTE(DID_BAD_TARGET);
4288 break;
4289 }
4290 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004292 case QD_ABORTED_BY_HOST:
4293 ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n");
4294 scp->result =
4295 HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.
4296 scsi_msg) |
4297 STATUS_BYTE(qdonep->d3.scsi_stat);
4298 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004300 default:
4301 ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n",
4302 qdonep->d3.done_stat);
4303 scp->result =
4304 HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.
4305 scsi_msg) |
4306 STATUS_BYTE(qdonep->d3.scsi_stat);
4307 break;
4308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004309
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004310 /*
4311 * If the 'init_tidmask' bit isn't already set for the target and the
4312 * current request finished normally, then set the bit for the target
4313 * to indicate that a device is present.
4314 */
4315 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4316 qdonep->d3.done_stat == QD_NO_ERROR &&
4317 qdonep->d3.host_stat == QHSTA_NO_ERROR) {
4318 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004320
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004321 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004322
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004323 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324}
4325
4326/*
4327 * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR().
4328 *
4329 * Callback function for the Wide SCSI Adv Library.
4330 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004331static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004333 asc_board_t *boardp;
4334 adv_req_t *reqp;
4335 adv_sgblk_t *sgblkp;
4336 struct scsi_cmnd *scp;
4337 struct Scsi_Host *shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004338 ADV_DCNT resid_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004339
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004340 ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n",
4341 (ulong)adv_dvc_varp, (ulong)scsiqp);
4342 ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004344 /*
4345 * Get the adv_req_t structure for the command that has been
4346 * completed. The adv_req_t structure actually contains the
4347 * completed ADV_SCSI_REQ_Q structure.
4348 */
4349 reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr);
4350 ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp);
4351 if (reqp == NULL) {
4352 ASC_PRINT("adv_isr_callback: reqp is NULL\n");
4353 return;
4354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004356 /*
4357 * Get the struct scsi_cmnd structure and Scsi_Host structure for the
4358 * command that has been completed.
4359 *
4360 * Note: The adv_req_t request structure and adv_sgblk_t structure,
4361 * if any, are dropped, because a board structure pointer can not be
4362 * determined.
4363 */
4364 scp = reqp->cmndp;
4365 ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp);
4366 if (scp == NULL) {
4367 ASC_PRINT
4368 ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n");
4369 return;
4370 }
4371 ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004373 shost = scp->device->host;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004374 ASC_STATS(shost, callback);
4375 ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004377 boardp = ASC_BOARDP(shost);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06004378 BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004380 /*
4381 * 'done_status' contains the command's ending status.
4382 */
4383 switch (scsiqp->done_status) {
4384 case QD_NO_ERROR:
4385 ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n");
4386 scp->result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004388 /*
4389 * Check for an underrun condition.
4390 *
4391 * If there was no error and an underrun condition, then
4392 * then return the number of underrun bytes.
4393 */
4394 resid_cnt = le32_to_cpu(scsiqp->data_cnt);
4395 if (scp->request_bufflen != 0 && resid_cnt != 0 &&
4396 resid_cnt <= scp->request_bufflen) {
4397 ASC_DBG1(1,
4398 "adv_isr_callback: underrun condition %lu bytes\n",
4399 (ulong)resid_cnt);
4400 scp->resid = resid_cnt;
4401 }
4402 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004404 case QD_WITH_ERROR:
4405 ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n");
4406 switch (scsiqp->host_status) {
4407 case QHSTA_NO_ERROR:
4408 if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) {
4409 ASC_DBG(2,
4410 "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n");
4411 ASC_DBG_PRT_SENSE(2, scp->sense_buffer,
4412 sizeof(scp->sense_buffer));
4413 /*
4414 * Note: The 'status_byte()' macro used by target drivers
4415 * defined in scsi.h shifts the status byte returned by
4416 * host drivers right by 1 bit. This is why target drivers
4417 * also use right shifted status byte definitions. For
4418 * instance target drivers use CHECK_CONDITION, defined to
4419 * 0x1, instead of the SCSI defined check condition value
4420 * of 0x2. Host drivers are supposed to return the status
4421 * byte as it is defined by SCSI.
4422 */
4423 scp->result = DRIVER_BYTE(DRIVER_SENSE) |
4424 STATUS_BYTE(scsiqp->scsi_status);
4425 } else {
4426 scp->result = STATUS_BYTE(scsiqp->scsi_status);
4427 }
4428 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004430 default:
4431 /* Some other QHSTA error occurred. */
4432 ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n",
4433 scsiqp->host_status);
4434 scp->result = HOST_BYTE(DID_BAD_TARGET);
4435 break;
4436 }
4437 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004439 case QD_ABORTED_BY_HOST:
4440 ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n");
4441 scp->result =
4442 HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status);
4443 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004445 default:
4446 ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n",
4447 scsiqp->done_status);
4448 scp->result =
4449 HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
4450 break;
4451 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004453 /*
4454 * If the 'init_tidmask' bit isn't already set for the target and the
4455 * current request finished normally, then set the bit for the target
4456 * to indicate that a device is present.
4457 */
4458 if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 &&
4459 scsiqp->done_status == QD_NO_ERROR &&
4460 scsiqp->host_status == QHSTA_NO_ERROR) {
4461 boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id);
4462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004463
Matthew Wilcox6ed1ef02007-09-09 08:56:33 -06004464 asc_scsi_done(scp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004466 /*
4467 * Free all 'adv_sgblk_t' structures allocated for the request.
4468 */
4469 while ((sgblkp = reqp->sgblkp) != NULL) {
4470 /* Remove 'sgblkp' from the request list. */
4471 reqp->sgblkp = sgblkp->next_sgblkp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004473 /* Add 'sgblkp' to the board free list. */
4474 sgblkp->next_sgblkp = boardp->adv_sgblkp;
4475 boardp->adv_sgblkp = sgblkp;
4476 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004478 /*
4479 * Free the adv_req_t structure used with the command by adding
4480 * it back to the board free list.
4481 */
4482 reqp->next_reqp = boardp->adv_reqp;
4483 boardp->adv_reqp = reqp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004485 ASC_DBG(1, "adv_isr_callback: done\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07004486
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004487 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488}
4489
4490/*
4491 * adv_async_callback() - Adv Library asynchronous event callback function.
4492 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004493static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004495 switch (code) {
4496 case ADV_ASYNC_SCSI_BUS_RESET_DET:
4497 /*
4498 * The firmware detected a SCSI Bus reset.
4499 */
4500 ASC_DBG(0,
4501 "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n");
4502 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004504 case ADV_ASYNC_RDMA_FAILURE:
4505 /*
4506 * Handle RDMA failure by resetting the SCSI Bus and
4507 * possibly the chip if it is unresponsive. Log the error
4508 * with a unique code.
4509 */
4510 ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n");
4511 AdvResetChipAndSB(adv_dvc_varp);
4512 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004514 case ADV_HOST_SCSI_BUS_RESET:
4515 /*
4516 * Host generated SCSI bus reset occurred.
4517 */
4518 ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n");
4519 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004521 default:
4522 ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code);
4523 break;
4524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525}
4526
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527#ifdef CONFIG_PROC_FS
4528/*
4529 * asc_prt_board_devices()
4530 *
4531 * Print driver information for devices attached to the board.
4532 *
4533 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4534 * cf. asc_prt_line().
4535 *
4536 * Return the number of characters copied into 'cp'. No more than
4537 * 'cplen' characters will be copied to 'cp'.
4538 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004539static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004541 asc_board_t *boardp;
4542 int leftlen;
4543 int totlen;
4544 int len;
4545 int chip_scsi_id;
4546 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004548 boardp = ASC_BOARDP(shost);
4549 leftlen = cplen;
4550 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004552 len = asc_prt_line(cp, leftlen,
4553 "\nDevice Information for AdvanSys SCSI Host %d:\n",
4554 shost->host_no);
4555 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004557 if (ASC_NARROW_BOARD(boardp)) {
4558 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
4559 } else {
4560 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
4561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004563 len = asc_prt_line(cp, leftlen, "Target IDs Detected:");
4564 ASC_PRT_NEXT();
4565 for (i = 0; i <= ADV_MAX_TID; i++) {
4566 if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) {
4567 len = asc_prt_line(cp, leftlen, " %X,", i);
4568 ASC_PRT_NEXT();
4569 }
4570 }
4571 len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id);
4572 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004574 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004575}
4576
4577/*
4578 * Display Wide Board BIOS Information.
4579 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004580static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004582 asc_board_t *boardp;
4583 int leftlen;
4584 int totlen;
4585 int len;
4586 ushort major, minor, letter;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004588 boardp = ASC_BOARDP(shost);
4589 leftlen = cplen;
4590 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004591
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004592 len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: ");
4593 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004594
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004595 /*
4596 * If the BIOS saved a valid signature, then fill in
4597 * the BIOS code segment base address.
4598 */
4599 if (boardp->bios_signature != 0x55AA) {
4600 len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n");
4601 ASC_PRT_NEXT();
4602 len = asc_prt_line(cp, leftlen,
4603 "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n");
4604 ASC_PRT_NEXT();
4605 len = asc_prt_line(cp, leftlen,
4606 "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n");
4607 ASC_PRT_NEXT();
4608 } else {
4609 major = (boardp->bios_version >> 12) & 0xF;
4610 minor = (boardp->bios_version >> 8) & 0xF;
4611 letter = (boardp->bios_version & 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004612
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004613 len = asc_prt_line(cp, leftlen, "%d.%d%c\n",
4614 major, minor,
4615 letter >= 26 ? '?' : letter + 'A');
4616 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004618 /*
4619 * Current available ROM BIOS release is 3.1I for UW
4620 * and 3.2I for U2W. This code doesn't differentiate
4621 * UW and U2W boards.
4622 */
4623 if (major < 3 || (major <= 3 && minor < 1) ||
4624 (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) {
4625 len = asc_prt_line(cp, leftlen,
4626 "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n");
4627 ASC_PRT_NEXT();
4628 len = asc_prt_line(cp, leftlen,
4629 "ftp://ftp.connectcom.net/pub\n");
4630 ASC_PRT_NEXT();
4631 }
4632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004634 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635}
4636
4637/*
4638 * Add serial number to information bar if signature AAh
4639 * is found in at bit 15-9 (7 bits) of word 1.
4640 *
4641 * Serial Number consists fo 12 alpha-numeric digits.
4642 *
4643 * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
4644 * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
4645 * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits)
4646 * 5 - Product revision (A-J) Word0: " "
4647 *
4648 * Signature Word1: 15-9 (7 bits)
4649 * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
4650 * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits)
4651 *
4652 * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
4653 *
4654 * Note 1: Only production cards will have a serial number.
4655 *
4656 * Note 2: Signature is most significant 7 bits (0xFE).
4657 *
4658 * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE.
4659 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004660static int asc_get_eeprom_string(ushort *serialnum, uchar *cp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004661{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004662 ushort w, num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004664 if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) {
4665 return ASC_FALSE;
4666 } else {
4667 /*
4668 * First word - 6 digits.
4669 */
4670 w = serialnum[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004671
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004672 /* Product type - 1st digit. */
4673 if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
4674 /* Product type is P=Prototype */
4675 *cp += 0x8;
4676 }
4677 cp++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004678
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004679 /* Manufacturing location - 2nd digit. */
4680 *cp++ = 'A' + ((w & 0x1C00) >> 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004682 /* Product ID - 3rd, 4th digits. */
4683 num = w & 0x3FF;
4684 *cp++ = '0' + (num / 100);
4685 num %= 100;
4686 *cp++ = '0' + (num / 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004687
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004688 /* Product revision - 5th digit. */
4689 *cp++ = 'A' + (num % 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004690
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004691 /*
4692 * Second word
4693 */
4694 w = serialnum[1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004696 /*
4697 * Year - 6th digit.
4698 *
4699 * If bit 15 of third word is set, then the
4700 * last digit of the year is greater than 7.
4701 */
4702 if (serialnum[2] & 0x8000) {
4703 *cp++ = '8' + ((w & 0x1C0) >> 6);
4704 } else {
4705 *cp++ = '0' + ((w & 0x1C0) >> 6);
4706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004708 /* Week of year - 7th, 8th digits. */
4709 num = w & 0x003F;
4710 *cp++ = '0' + num / 10;
4711 num %= 10;
4712 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004714 /*
4715 * Third word
4716 */
4717 w = serialnum[2] & 0x7FFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004719 /* Serial number - 9th digit. */
4720 *cp++ = 'A' + (w / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004722 /* 10th, 11th, 12th digits. */
4723 num = w % 1000;
4724 *cp++ = '0' + num / 100;
4725 num %= 100;
4726 *cp++ = '0' + num / 10;
4727 num %= 10;
4728 *cp++ = '0' + num;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004730 *cp = '\0'; /* Null Terminate the string. */
4731 return ASC_TRUE;
4732 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004733}
4734
4735/*
4736 * asc_prt_asc_board_eeprom()
4737 *
4738 * Print board EEPROM configuration.
4739 *
4740 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4741 * cf. asc_prt_line().
4742 *
4743 * Return the number of characters copied into 'cp'. No more than
4744 * 'cplen' characters will be copied to 'cp'.
4745 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004746static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004748 asc_board_t *boardp;
4749 ASC_DVC_VAR *asc_dvc_varp;
4750 int leftlen;
4751 int totlen;
4752 int len;
4753 ASCEEP_CONFIG *ep;
4754 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004755#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004756 int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07004757#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004758 uchar serialstr[13];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004760 boardp = ASC_BOARDP(shost);
4761 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
4762 ep = &boardp->eep_config.asc_eep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004764 leftlen = cplen;
4765 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004767 len = asc_prt_line(cp, leftlen,
4768 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
4769 shost->host_no);
4770 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004771
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004772 if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr)
4773 == ASC_TRUE) {
4774 len =
4775 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
4776 serialstr);
4777 ASC_PRT_NEXT();
4778 } else {
4779 if (ep->adapter_info[5] == 0xBB) {
4780 len = asc_prt_line(cp, leftlen,
4781 " Default Settings Used for EEPROM-less Adapter.\n");
4782 ASC_PRT_NEXT();
4783 } else {
4784 len = asc_prt_line(cp, leftlen,
4785 " Serial Number Signature Not Present.\n");
4786 ASC_PRT_NEXT();
4787 }
4788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004789
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004790 len = asc_prt_line(cp, leftlen,
4791 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4792 ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng,
4793 ep->max_tag_qng);
4794 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004796 len = asc_prt_line(cp, leftlen,
4797 " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam);
4798 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004799
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004800 len = asc_prt_line(cp, leftlen, " Target ID: ");
4801 ASC_PRT_NEXT();
4802 for (i = 0; i <= ASC_MAX_TID; i++) {
4803 len = asc_prt_line(cp, leftlen, " %d", i);
4804 ASC_PRT_NEXT();
4805 }
4806 len = asc_prt_line(cp, leftlen, "\n");
4807 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004808
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004809 len = asc_prt_line(cp, leftlen, " Disconnects: ");
4810 ASC_PRT_NEXT();
4811 for (i = 0; i <= ASC_MAX_TID; i++) {
4812 len = asc_prt_line(cp, leftlen, " %c",
4813 (ep->
4814 disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4815 'N');
4816 ASC_PRT_NEXT();
4817 }
4818 len = asc_prt_line(cp, leftlen, "\n");
4819 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004820
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004821 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
4822 ASC_PRT_NEXT();
4823 for (i = 0; i <= ASC_MAX_TID; i++) {
4824 len = asc_prt_line(cp, leftlen, " %c",
4825 (ep->
4826 use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4827 'N');
4828 ASC_PRT_NEXT();
4829 }
4830 len = asc_prt_line(cp, leftlen, "\n");
4831 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004832
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004833 len = asc_prt_line(cp, leftlen, " Start Motor: ");
4834 ASC_PRT_NEXT();
4835 for (i = 0; i <= ASC_MAX_TID; i++) {
4836 len = asc_prt_line(cp, leftlen, " %c",
4837 (ep->
4838 start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4839 'N');
4840 ASC_PRT_NEXT();
4841 }
4842 len = asc_prt_line(cp, leftlen, "\n");
4843 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004845 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
4846 ASC_PRT_NEXT();
4847 for (i = 0; i <= ASC_MAX_TID; i++) {
4848 len = asc_prt_line(cp, leftlen, " %c",
4849 (ep->
4850 init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
4851 'N');
4852 ASC_PRT_NEXT();
4853 }
4854 len = asc_prt_line(cp, leftlen, "\n");
4855 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004856
4857#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004858 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
4859 len = asc_prt_line(cp, leftlen,
4860 " Host ISA DMA speed: %d MB/S\n",
4861 isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]);
4862 ASC_PRT_NEXT();
4863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004864#endif /* CONFIG_ISA */
4865
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004866 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004867}
4868
4869/*
4870 * asc_prt_adv_board_eeprom()
4871 *
4872 * Print board EEPROM configuration.
4873 *
4874 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
4875 * cf. asc_prt_line().
4876 *
4877 * Return the number of characters copied into 'cp'. No more than
4878 * 'cplen' characters will be copied to 'cp'.
4879 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004880static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004881{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004882 asc_board_t *boardp;
4883 ADV_DVC_VAR *adv_dvc_varp;
4884 int leftlen;
4885 int totlen;
4886 int len;
4887 int i;
4888 char *termstr;
4889 uchar serialstr[13];
4890 ADVEEP_3550_CONFIG *ep_3550 = NULL;
4891 ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL;
4892 ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL;
4893 ushort word;
4894 ushort *wordp;
4895 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004897 boardp = ASC_BOARDP(shost);
4898 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
4899 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4900 ep_3550 = &boardp->eep_config.adv_3550_eep;
4901 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4902 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
4903 } else {
4904 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
4905 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004907 leftlen = cplen;
4908 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004910 len = asc_prt_line(cp, leftlen,
4911 "\nEEPROM Settings for AdvanSys SCSI Host %d:\n",
4912 shost->host_no);
4913 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004915 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4916 wordp = &ep_3550->serial_number_word1;
4917 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4918 wordp = &ep_38C0800->serial_number_word1;
4919 } else {
4920 wordp = &ep_38C1600->serial_number_word1;
4921 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004923 if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) {
4924 len =
4925 asc_prt_line(cp, leftlen, " Serial Number: %s\n",
4926 serialstr);
4927 ASC_PRT_NEXT();
4928 } else {
4929 len = asc_prt_line(cp, leftlen,
4930 " Serial Number Signature Not Present.\n");
4931 ASC_PRT_NEXT();
4932 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004934 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4935 len = asc_prt_line(cp, leftlen,
4936 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4937 ep_3550->adapter_scsi_id,
4938 ep_3550->max_host_qng, ep_3550->max_dvc_qng);
4939 ASC_PRT_NEXT();
4940 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4941 len = asc_prt_line(cp, leftlen,
4942 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4943 ep_38C0800->adapter_scsi_id,
4944 ep_38C0800->max_host_qng,
4945 ep_38C0800->max_dvc_qng);
4946 ASC_PRT_NEXT();
4947 } else {
4948 len = asc_prt_line(cp, leftlen,
4949 " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n",
4950 ep_38C1600->adapter_scsi_id,
4951 ep_38C1600->max_host_qng,
4952 ep_38C1600->max_dvc_qng);
4953 ASC_PRT_NEXT();
4954 }
4955 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4956 word = ep_3550->termination;
4957 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4958 word = ep_38C0800->termination_lvd;
4959 } else {
4960 word = ep_38C1600->termination_lvd;
4961 }
4962 switch (word) {
4963 case 1:
4964 termstr = "Low Off/High Off";
4965 break;
4966 case 2:
4967 termstr = "Low Off/High On";
4968 break;
4969 case 3:
4970 termstr = "Low On/High On";
4971 break;
4972 default:
4973 case 0:
4974 termstr = "Automatic";
4975 break;
4976 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004978 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
4979 len = asc_prt_line(cp, leftlen,
4980 " termination: %u (%s), bios_ctrl: 0x%x\n",
4981 ep_3550->termination, termstr,
4982 ep_3550->bios_ctrl);
4983 ASC_PRT_NEXT();
4984 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
4985 len = asc_prt_line(cp, leftlen,
4986 " termination: %u (%s), bios_ctrl: 0x%x\n",
4987 ep_38C0800->termination_lvd, termstr,
4988 ep_38C0800->bios_ctrl);
4989 ASC_PRT_NEXT();
4990 } else {
4991 len = asc_prt_line(cp, leftlen,
4992 " termination: %u (%s), bios_ctrl: 0x%x\n",
4993 ep_38C1600->termination_lvd, termstr,
4994 ep_38C1600->bios_ctrl);
4995 ASC_PRT_NEXT();
4996 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997
Matthew Wilcox27c868c2007-07-26 10:56:23 -04004998 len = asc_prt_line(cp, leftlen, " Target ID: ");
4999 ASC_PRT_NEXT();
5000 for (i = 0; i <= ADV_MAX_TID; i++) {
5001 len = asc_prt_line(cp, leftlen, " %X", i);
5002 ASC_PRT_NEXT();
5003 }
5004 len = asc_prt_line(cp, leftlen, "\n");
5005 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005007 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5008 word = ep_3550->disc_enable;
5009 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5010 word = ep_38C0800->disc_enable;
5011 } else {
5012 word = ep_38C1600->disc_enable;
5013 }
5014 len = asc_prt_line(cp, leftlen, " Disconnects: ");
5015 ASC_PRT_NEXT();
5016 for (i = 0; i <= ADV_MAX_TID; i++) {
5017 len = asc_prt_line(cp, leftlen, " %c",
5018 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5019 ASC_PRT_NEXT();
5020 }
5021 len = asc_prt_line(cp, leftlen, "\n");
5022 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005024 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5025 word = ep_3550->tagqng_able;
5026 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5027 word = ep_38C0800->tagqng_able;
5028 } else {
5029 word = ep_38C1600->tagqng_able;
5030 }
5031 len = asc_prt_line(cp, leftlen, " Command Queuing: ");
5032 ASC_PRT_NEXT();
5033 for (i = 0; i <= ADV_MAX_TID; i++) {
5034 len = asc_prt_line(cp, leftlen, " %c",
5035 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5036 ASC_PRT_NEXT();
5037 }
5038 len = asc_prt_line(cp, leftlen, "\n");
5039 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005041 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5042 word = ep_3550->start_motor;
5043 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5044 word = ep_38C0800->start_motor;
5045 } else {
5046 word = ep_38C1600->start_motor;
5047 }
5048 len = asc_prt_line(cp, leftlen, " Start Motor: ");
5049 ASC_PRT_NEXT();
5050 for (i = 0; i <= ADV_MAX_TID; i++) {
5051 len = asc_prt_line(cp, leftlen, " %c",
5052 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5053 ASC_PRT_NEXT();
5054 }
5055 len = asc_prt_line(cp, leftlen, "\n");
5056 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005057
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005058 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5059 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5060 ASC_PRT_NEXT();
5061 for (i = 0; i <= ADV_MAX_TID; i++) {
5062 len = asc_prt_line(cp, leftlen, " %c",
5063 (ep_3550->
5064 sdtr_able & ADV_TID_TO_TIDMASK(i)) ?
5065 'Y' : 'N');
5066 ASC_PRT_NEXT();
5067 }
5068 len = asc_prt_line(cp, leftlen, "\n");
5069 ASC_PRT_NEXT();
5070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005072 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5073 len = asc_prt_line(cp, leftlen, " Ultra Transfer: ");
5074 ASC_PRT_NEXT();
5075 for (i = 0; i <= ADV_MAX_TID; i++) {
5076 len = asc_prt_line(cp, leftlen, " %c",
5077 (ep_3550->
5078 ultra_able & ADV_TID_TO_TIDMASK(i))
5079 ? 'Y' : 'N');
5080 ASC_PRT_NEXT();
5081 }
5082 len = asc_prt_line(cp, leftlen, "\n");
5083 ASC_PRT_NEXT();
5084 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005086 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
5087 word = ep_3550->wdtr_able;
5088 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
5089 word = ep_38C0800->wdtr_able;
5090 } else {
5091 word = ep_38C1600->wdtr_able;
5092 }
5093 len = asc_prt_line(cp, leftlen, " Wide Transfer: ");
5094 ASC_PRT_NEXT();
5095 for (i = 0; i <= ADV_MAX_TID; i++) {
5096 len = asc_prt_line(cp, leftlen, " %c",
5097 (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N');
5098 ASC_PRT_NEXT();
5099 }
5100 len = asc_prt_line(cp, leftlen, "\n");
5101 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005103 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 ||
5104 adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) {
5105 len = asc_prt_line(cp, leftlen,
5106 " Synchronous Transfer Speed (Mhz):\n ");
5107 ASC_PRT_NEXT();
5108 for (i = 0; i <= ADV_MAX_TID; i++) {
5109 char *speed_str;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005111 if (i == 0) {
5112 sdtr_speed = adv_dvc_varp->sdtr_speed1;
5113 } else if (i == 4) {
5114 sdtr_speed = adv_dvc_varp->sdtr_speed2;
5115 } else if (i == 8) {
5116 sdtr_speed = adv_dvc_varp->sdtr_speed3;
5117 } else if (i == 12) {
5118 sdtr_speed = adv_dvc_varp->sdtr_speed4;
5119 }
5120 switch (sdtr_speed & ADV_MAX_TID) {
5121 case 0:
5122 speed_str = "Off";
5123 break;
5124 case 1:
5125 speed_str = " 5";
5126 break;
5127 case 2:
5128 speed_str = " 10";
5129 break;
5130 case 3:
5131 speed_str = " 20";
5132 break;
5133 case 4:
5134 speed_str = " 40";
5135 break;
5136 case 5:
5137 speed_str = " 80";
5138 break;
5139 default:
5140 speed_str = "Unk";
5141 break;
5142 }
5143 len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str);
5144 ASC_PRT_NEXT();
5145 if (i == 7) {
5146 len = asc_prt_line(cp, leftlen, "\n ");
5147 ASC_PRT_NEXT();
5148 }
5149 sdtr_speed >>= 4;
5150 }
5151 len = asc_prt_line(cp, leftlen, "\n");
5152 ASC_PRT_NEXT();
5153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005155 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156}
5157
5158/*
5159 * asc_prt_driver_conf()
5160 *
5161 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5162 * cf. asc_prt_line().
5163 *
5164 * Return the number of characters copied into 'cp'. No more than
5165 * 'cplen' characters will be copied to 'cp'.
5166 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005167static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005168{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005169 asc_board_t *boardp;
5170 int leftlen;
5171 int totlen;
5172 int len;
5173 int chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005174
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005175 boardp = ASC_BOARDP(shost);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005177 leftlen = cplen;
5178 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005180 len = asc_prt_line(cp, leftlen,
5181 "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n",
5182 shost->host_no);
5183 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005185 len = asc_prt_line(cp, leftlen,
5186 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
5187 shost->host_busy, shost->last_reset, shost->max_id,
5188 shost->max_lun, shost->max_channel);
5189 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005190
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005191 len = asc_prt_line(cp, leftlen,
5192 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
5193 shost->unique_id, shost->can_queue, shost->this_id,
5194 shost->sg_tablesize, shost->cmd_per_lun);
5195 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005197 len = asc_prt_line(cp, leftlen,
5198 " unchecked_isa_dma %d, use_clustering %d\n",
5199 shost->unchecked_isa_dma, shost->use_clustering);
5200 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005202 len = asc_prt_line(cp, leftlen,
5203 " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n",
5204 boardp->flags, boardp->last_reset, jiffies,
5205 boardp->asc_n_io_port);
5206 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04005208 len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005209 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005210
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005211 if (ASC_NARROW_BOARD(boardp)) {
5212 chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id;
5213 } else {
5214 chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id;
5215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005217 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005218}
5219
5220/*
5221 * asc_prt_asc_board_info()
5222 *
5223 * Print dynamic board configuration information.
5224 *
5225 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5226 * cf. asc_prt_line().
5227 *
5228 * Return the number of characters copied into 'cp'. No more than
5229 * 'cplen' characters will be copied to 'cp'.
5230 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005231static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005233 asc_board_t *boardp;
5234 int chip_scsi_id;
5235 int leftlen;
5236 int totlen;
5237 int len;
5238 ASC_DVC_VAR *v;
5239 ASC_DVC_CFG *c;
5240 int i;
5241 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005243 boardp = ASC_BOARDP(shost);
5244 v = &boardp->dvc_var.asc_dvc_var;
5245 c = &boardp->dvc_cfg.asc_dvc_cfg;
5246 chip_scsi_id = c->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005248 leftlen = cplen;
5249 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005251 len = asc_prt_line(cp, leftlen,
5252 "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5253 shost->host_no);
5254 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005255
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005256 len = asc_prt_line(cp, leftlen,
5257 " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n",
5258 c->chip_version, c->lib_version, c->lib_serial_no,
5259 c->mcode_date);
5260 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005261
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005262 len = asc_prt_line(cp, leftlen,
5263 " mcode_version 0x%x, err_code %u\n",
5264 c->mcode_version, v->err_code);
5265 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005267 /* Current number of commands waiting for the host. */
5268 len = asc_prt_line(cp, leftlen,
5269 " Total Command Pending: %d\n", v->cur_total_qng);
5270 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005272 len = asc_prt_line(cp, leftlen, " Command Queuing:");
5273 ASC_PRT_NEXT();
5274 for (i = 0; i <= ASC_MAX_TID; i++) {
5275 if ((chip_scsi_id == i) ||
5276 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5277 continue;
5278 }
5279 len = asc_prt_line(cp, leftlen, " %X:%c",
5280 i,
5281 (v->
5282 use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ?
5283 'Y' : 'N');
5284 ASC_PRT_NEXT();
5285 }
5286 len = asc_prt_line(cp, leftlen, "\n");
5287 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005289 /* Current number of commands waiting for a device. */
5290 len = asc_prt_line(cp, leftlen, " Command Queue Pending:");
5291 ASC_PRT_NEXT();
5292 for (i = 0; i <= ASC_MAX_TID; i++) {
5293 if ((chip_scsi_id == i) ||
5294 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5295 continue;
5296 }
5297 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]);
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 /* Current limit on number of commands that can be sent to a device. */
5304 len = asc_prt_line(cp, leftlen, " Command Queue Limit:");
5305 ASC_PRT_NEXT();
5306 for (i = 0; i <= ASC_MAX_TID; i++) {
5307 if ((chip_scsi_id == i) ||
5308 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5309 continue;
5310 }
5311 len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]);
5312 ASC_PRT_NEXT();
5313 }
5314 len = asc_prt_line(cp, leftlen, "\n");
5315 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005317 /* Indicate whether the device has returned queue full status. */
5318 len = asc_prt_line(cp, leftlen, " Command Queue Full:");
5319 ASC_PRT_NEXT();
5320 for (i = 0; i <= ASC_MAX_TID; i++) {
5321 if ((chip_scsi_id == i) ||
5322 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5323 continue;
5324 }
5325 if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) {
5326 len = asc_prt_line(cp, leftlen, " %X:Y-%d",
5327 i, boardp->queue_full_cnt[i]);
5328 } else {
5329 len = asc_prt_line(cp, leftlen, " %X:N", i);
5330 }
5331 ASC_PRT_NEXT();
5332 }
5333 len = asc_prt_line(cp, leftlen, "\n");
5334 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005336 len = asc_prt_line(cp, leftlen, " Synchronous Transfer:");
5337 ASC_PRT_NEXT();
5338 for (i = 0; i <= ASC_MAX_TID; i++) {
5339 if ((chip_scsi_id == i) ||
5340 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5341 continue;
5342 }
5343 len = asc_prt_line(cp, leftlen, " %X:%c",
5344 i,
5345 (v->
5346 sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5347 'N');
5348 ASC_PRT_NEXT();
5349 }
5350 len = asc_prt_line(cp, leftlen, "\n");
5351 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005352
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005353 for (i = 0; i <= ASC_MAX_TID; i++) {
5354 uchar syn_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005356 if ((chip_scsi_id == i) ||
5357 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5358 ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) {
5359 continue;
5360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005362 len = asc_prt_line(cp, leftlen, " %X:", i);
5363 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005365 if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) {
5366 len = asc_prt_line(cp, leftlen, " Asynchronous");
5367 ASC_PRT_NEXT();
5368 } else {
5369 syn_period_ix =
5370 (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index -
5371 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005373 len = asc_prt_line(cp, leftlen,
5374 " Transfer Period Factor: %d (%d.%d Mhz),",
5375 v->sdtr_period_tbl[syn_period_ix],
5376 250 /
5377 v->sdtr_period_tbl[syn_period_ix],
5378 ASC_TENTHS(250,
5379 v->
5380 sdtr_period_tbl
5381 [syn_period_ix]));
5382 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005384 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5385 boardp->
5386 sdtr_data[i] & ASC_SYN_MAX_OFFSET);
5387 ASC_PRT_NEXT();
5388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005390 if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5391 len = asc_prt_line(cp, leftlen, "*\n");
5392 renegotiate = 1;
5393 } else {
5394 len = asc_prt_line(cp, leftlen, "\n");
5395 }
5396 ASC_PRT_NEXT();
5397 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005399 if (renegotiate) {
5400 len = asc_prt_line(cp, leftlen,
5401 " * = Re-negotiation pending before next command.\n");
5402 ASC_PRT_NEXT();
5403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005405 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406}
5407
5408/*
5409 * asc_prt_adv_board_info()
5410 *
5411 * Print dynamic board configuration information.
5412 *
5413 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5414 * cf. asc_prt_line().
5415 *
5416 * Return the number of characters copied into 'cp'. No more than
5417 * 'cplen' characters will be copied to 'cp'.
5418 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005419static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005421 asc_board_t *boardp;
5422 int leftlen;
5423 int totlen;
5424 int len;
5425 int i;
5426 ADV_DVC_VAR *v;
5427 ADV_DVC_CFG *c;
5428 AdvPortAddr iop_base;
5429 ushort chip_scsi_id;
5430 ushort lramword;
5431 uchar lrambyte;
5432 ushort tagqng_able;
5433 ushort sdtr_able, wdtr_able;
5434 ushort wdtr_done, sdtr_done;
5435 ushort period = 0;
5436 int renegotiate = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005438 boardp = ASC_BOARDP(shost);
5439 v = &boardp->dvc_var.adv_dvc_var;
5440 c = &boardp->dvc_cfg.adv_dvc_cfg;
5441 iop_base = v->iop_base;
5442 chip_scsi_id = v->chip_scsi_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005444 leftlen = cplen;
5445 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005447 len = asc_prt_line(cp, leftlen,
5448 "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n",
5449 shost->host_no);
5450 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005452 len = asc_prt_line(cp, leftlen,
5453 " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
5454 v->iop_base,
5455 AdvReadWordRegister(iop_base,
5456 IOPW_SCSI_CFG1) & CABLE_DETECT,
5457 v->err_code);
5458 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005459
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005460 len = asc_prt_line(cp, leftlen,
5461 " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n",
5462 c->chip_version, c->lib_version, c->mcode_date,
5463 c->mcode_version);
5464 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005466 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
5467 len = asc_prt_line(cp, leftlen, " Queuing Enabled:");
5468 ASC_PRT_NEXT();
5469 for (i = 0; i <= ADV_MAX_TID; i++) {
5470 if ((chip_scsi_id == i) ||
5471 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5472 continue;
5473 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005474
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005475 len = asc_prt_line(cp, leftlen, " %X:%c",
5476 i,
5477 (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5478 'N');
5479 ASC_PRT_NEXT();
5480 }
5481 len = asc_prt_line(cp, leftlen, "\n");
5482 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005484 len = asc_prt_line(cp, leftlen, " Queue Limit:");
5485 ASC_PRT_NEXT();
5486 for (i = 0; i <= ADV_MAX_TID; i++) {
5487 if ((chip_scsi_id == i) ||
5488 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5489 continue;
5490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005492 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i,
5493 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005495 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5496 ASC_PRT_NEXT();
5497 }
5498 len = asc_prt_line(cp, leftlen, "\n");
5499 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005501 len = asc_prt_line(cp, leftlen, " Command Pending:");
5502 ASC_PRT_NEXT();
5503 for (i = 0; i <= ADV_MAX_TID; i++) {
5504 if ((chip_scsi_id == i) ||
5505 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5506 continue;
5507 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005508
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005509 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i,
5510 lrambyte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005512 len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte);
5513 ASC_PRT_NEXT();
5514 }
5515 len = asc_prt_line(cp, leftlen, "\n");
5516 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005517
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005518 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
5519 len = asc_prt_line(cp, leftlen, " Wide Enabled:");
5520 ASC_PRT_NEXT();
5521 for (i = 0; i <= ADV_MAX_TID; i++) {
5522 if ((chip_scsi_id == i) ||
5523 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5524 continue;
5525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005526
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005527 len = asc_prt_line(cp, leftlen, " %X:%c",
5528 i,
5529 (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5530 'N');
5531 ASC_PRT_NEXT();
5532 }
5533 len = asc_prt_line(cp, leftlen, "\n");
5534 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005535
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005536 AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done);
5537 len = asc_prt_line(cp, leftlen, " Transfer Bit Width:");
5538 ASC_PRT_NEXT();
5539 for (i = 0; i <= ADV_MAX_TID; i++) {
5540 if ((chip_scsi_id == i) ||
5541 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5542 continue;
5543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005544
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005545 AdvReadWordLram(iop_base,
5546 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
5547 lramword);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005548
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005549 len = asc_prt_line(cp, leftlen, " %X:%d",
5550 i, (lramword & 0x8000) ? 16 : 8);
5551 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005553 if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) &&
5554 (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5555 len = asc_prt_line(cp, leftlen, "*");
5556 ASC_PRT_NEXT();
5557 renegotiate = 1;
5558 }
5559 }
5560 len = asc_prt_line(cp, leftlen, "\n");
5561 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005562
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005563 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
5564 len = asc_prt_line(cp, leftlen, " Synchronous Enabled:");
5565 ASC_PRT_NEXT();
5566 for (i = 0; i <= ADV_MAX_TID; i++) {
5567 if ((chip_scsi_id == i) ||
5568 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) {
5569 continue;
5570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005571
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005572 len = asc_prt_line(cp, leftlen, " %X:%c",
5573 i,
5574 (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' :
5575 'N');
5576 ASC_PRT_NEXT();
5577 }
5578 len = asc_prt_line(cp, leftlen, "\n");
5579 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005580
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005581 AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done);
5582 for (i = 0; i <= ADV_MAX_TID; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005584 AdvReadWordLram(iop_base,
5585 ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i),
5586 lramword);
5587 lramword &= ~0x8000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005589 if ((chip_scsi_id == i) ||
5590 ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) ||
5591 ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) {
5592 continue;
5593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005594
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005595 len = asc_prt_line(cp, leftlen, " %X:", i);
5596 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005597
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005598 if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */
5599 len = asc_prt_line(cp, leftlen, " Asynchronous");
5600 ASC_PRT_NEXT();
5601 } else {
5602 len =
5603 asc_prt_line(cp, leftlen,
5604 " Transfer Period Factor: ");
5605 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005607 if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */
5608 len =
5609 asc_prt_line(cp, leftlen, "9 (80.0 Mhz),");
5610 ASC_PRT_NEXT();
5611 } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */
5612 len =
5613 asc_prt_line(cp, leftlen, "10 (40.0 Mhz),");
5614 ASC_PRT_NEXT();
5615 } else { /* 20 Mhz or below. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005616
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005617 period = (((lramword >> 8) * 25) + 50) / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005618
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005619 if (period == 0) { /* Should never happen. */
5620 len =
5621 asc_prt_line(cp, leftlen,
5622 "%d (? Mhz), ");
5623 ASC_PRT_NEXT();
5624 } else {
5625 len = asc_prt_line(cp, leftlen,
5626 "%d (%d.%d Mhz),",
5627 period, 250 / period,
5628 ASC_TENTHS(250,
5629 period));
5630 ASC_PRT_NEXT();
5631 }
5632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005633
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005634 len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d",
5635 lramword & 0x1F);
5636 ASC_PRT_NEXT();
5637 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005639 if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) {
5640 len = asc_prt_line(cp, leftlen, "*\n");
5641 renegotiate = 1;
5642 } else {
5643 len = asc_prt_line(cp, leftlen, "\n");
5644 }
5645 ASC_PRT_NEXT();
5646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005648 if (renegotiate) {
5649 len = asc_prt_line(cp, leftlen,
5650 " * = Re-negotiation pending before next command.\n");
5651 ASC_PRT_NEXT();
5652 }
5653
5654 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005655}
5656
5657/*
5658 * asc_proc_copy()
5659 *
5660 * Copy proc information to a read buffer taking into account the current
5661 * read offset in the file and the remaining space in the read buffer.
5662 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005663static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07005664asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005665 char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005667 int cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005668
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005669 ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n",
5670 (unsigned)offset, (unsigned)advoffset, cplen);
5671 if (offset <= advoffset) {
5672 /* Read offset below current offset, copy everything. */
5673 cnt = min(cplen, leftlen);
5674 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
5675 (ulong)curbuf, (ulong)cp, cnt);
5676 memcpy(curbuf, cp, cnt);
5677 } else if (offset < advoffset + cplen) {
5678 /* Read offset within current range, partial copy. */
5679 cnt = (advoffset + cplen) - offset;
5680 cp = (cp + cplen) - cnt;
5681 cnt = min(cnt, leftlen);
5682 ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n",
5683 (ulong)curbuf, (ulong)cp, cnt);
5684 memcpy(curbuf, cp, cnt);
5685 }
5686 return cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005687}
5688
5689/*
5690 * asc_prt_line()
5691 *
5692 * If 'cp' is NULL print to the console, otherwise print to a buffer.
5693 *
5694 * Return 0 if printing to the console, otherwise return the number of
5695 * bytes written to the buffer.
5696 *
5697 * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack
5698 * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes.
5699 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005700static int asc_prt_line(char *buf, int buflen, char *fmt, ...)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005702 va_list args;
5703 int ret;
5704 char s[ASC_PRTLINE_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005706 va_start(args, fmt);
5707 ret = vsprintf(s, fmt, args);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06005708 BUG_ON(ret >= ASC_PRTLINE_SIZE);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005709 if (buf == NULL) {
5710 (void)printk(s);
5711 ret = 0;
5712 } else {
5713 ret = min(buflen, ret);
5714 memcpy(buf, s, ret);
5715 }
5716 va_end(args);
5717 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718}
5719#endif /* CONFIG_PROC_FS */
5720
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721/*
5722 * --- Functions Required by the Asc Library
5723 */
5724
5725/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726 * void
5727 * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
5728 *
5729 * Calling/Exit State:
5730 * none
5731 *
5732 * Description:
5733 * Output an ASC_SCSI_Q structure to the chip
5734 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005735static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words)
5737{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005738 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005740 ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words);
5741 AscSetChipLramAddr(iop_base, s_addr);
5742 for (i = 0; i < 2 * words; i += 2) {
5743 if (i == 4 || i == 20) {
5744 continue;
5745 }
5746 outpw(iop_base + IOP_RAM_DATA,
5747 ((ushort)outbuf[i + 1] << 8) | outbuf[i]);
5748 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005749}
5750
5751/*
5752 * void
5753 * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
5754 *
5755 * Calling/Exit State:
5756 * none
5757 *
5758 * Description:
5759 * Input an ASC_QDONE_INFO structure from the chip
5760 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005761static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words)
5763{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005764 int i;
5765 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005767 AscSetChipLramAddr(iop_base, s_addr);
5768 for (i = 0; i < 2 * words; i += 2) {
5769 if (i == 10) {
5770 continue;
5771 }
5772 word = inpw(iop_base + IOP_RAM_DATA);
5773 inbuf[i] = word & 0xff;
5774 inbuf[i + 1] = (word >> 8) & 0xff;
5775 }
5776 ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005777}
5778
5779/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780 * Return the BIOS address of the adapter at the specified
5781 * I/O port and with the specified bus type.
5782 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005783static unsigned short __devinit
5784AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005786 unsigned short cfg_lsw;
5787 unsigned short bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005789 /*
5790 * The PCI BIOS is re-located by the motherboard BIOS. Because
5791 * of this the driver can not determine where a PCI BIOS is
5792 * loaded and executes.
5793 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005794 if (bus_type & ASC_IS_PCI)
5795 return 0;
5796
Linus Torvalds1da177e2005-04-16 15:20:36 -07005797#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005798 if ((bus_type & ASC_IS_EISA) != 0) {
5799 cfg_lsw = AscGetEisaChipCfg(iop_base);
5800 cfg_lsw &= 0x000F;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005801 bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE;
5802 return bios_addr;
5803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005804#endif /* CONFIG_ISA */
5805
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005806 cfg_lsw = AscGetChipCfgLsw(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005808 /*
5809 * ISA PnP uses the top bit as the 32K BIOS flag
5810 */
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005811 if (bus_type == ASC_IS_ISAPNP)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005812 cfg_lsw &= 0x7FFF;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06005813 bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE;
5814 return bios_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815}
5816
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817/*
5818 * --- Functions Required by the Adv Library
5819 */
5820
5821/*
5822 * DvcGetPhyAddr()
5823 *
5824 * Return the physical address of 'vaddr' and set '*lenp' to the
5825 * number of physically contiguous bytes that follow 'vaddr'.
5826 * 'flag' indicates the type of structure whose physical address
5827 * is being translated.
5828 *
5829 * Note: Because Linux currently doesn't page the kernel and all
5830 * kernel buffers are physically contiguous, leave '*lenp' unchanged.
5831 */
5832ADV_PADDR
5833DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005834 uchar *vaddr, ADV_SDCNT *lenp, int flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005835{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005836 ADV_PADDR paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005838 paddr = virt_to_bus(vaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005839
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005840 ASC_DBG4(4,
5841 "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n",
5842 (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp),
5843 (ulong)paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005844
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005845 return paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846}
5847
5848/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849 * --- Tracing and Debugging Functions
5850 */
5851
5852#ifdef ADVANSYS_STATS
5853#ifdef CONFIG_PROC_FS
5854/*
5855 * asc_prt_board_stats()
5856 *
5857 * Note: no single line should be greater than ASC_PRTLINE_SIZE,
5858 * cf. asc_prt_line().
5859 *
5860 * Return the number of characters copied into 'cp'. No more than
5861 * 'cplen' characters will be copied to 'cp'.
5862 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005863static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005865 int leftlen;
5866 int totlen;
5867 int len;
5868 struct asc_stats *s;
5869 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005871 leftlen = cplen;
5872 totlen = len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005874 boardp = ASC_BOARDP(shost);
5875 s = &boardp->asc_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005877 len = asc_prt_line(cp, leftlen,
5878 "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n",
5879 shost->host_no);
5880 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005882 len = asc_prt_line(cp, leftlen,
5883 " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n",
5884 s->queuecommand, s->reset, s->biosparam,
5885 s->interrupt);
5886 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005887
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005888 len = asc_prt_line(cp, leftlen,
5889 " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n",
5890 s->callback, s->done, s->build_error,
5891 s->adv_build_noreq, s->adv_build_nosg);
5892 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005893
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005894 len = asc_prt_line(cp, leftlen,
5895 " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n",
5896 s->exe_noerror, s->exe_busy, s->exe_error,
5897 s->exe_unknown);
5898 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005900 /*
5901 * Display data transfer statistics.
5902 */
5903 if (s->cont_cnt > 0) {
5904 len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt);
5905 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005906
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005907 len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ",
5908 s->cont_xfer / 2,
5909 ASC_TENTHS(s->cont_xfer, 2));
5910 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005912 /* Contiguous transfer average size */
5913 len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n",
5914 (s->cont_xfer / 2) / s->cont_cnt,
5915 ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt));
5916 ASC_PRT_NEXT();
5917 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005918
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005919 if (s->sg_cnt > 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005920
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005921 len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ",
5922 s->sg_cnt, s->sg_elem);
5923 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005925 len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n",
5926 s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2));
5927 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005929 /* Scatter gather transfer statistics */
5930 len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ",
5931 s->sg_elem / s->sg_cnt,
5932 ASC_TENTHS(s->sg_elem, s->sg_cnt));
5933 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005935 len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ",
5936 (s->sg_xfer / 2) / s->sg_elem,
5937 ASC_TENTHS((s->sg_xfer / 2), s->sg_elem));
5938 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005940 len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n",
5941 (s->sg_xfer / 2) / s->sg_cnt,
5942 ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt));
5943 ASC_PRT_NEXT();
5944 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005946 /*
5947 * Display request queuing statistics.
5948 */
5949 len = asc_prt_line(cp, leftlen,
5950 " Active and Waiting Request Queues (Time Unit: %d HZ):\n",
5951 HZ);
5952 ASC_PRT_NEXT();
Linus Torvalds1da177e2005-04-16 15:20:36 -07005953
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005954 return totlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956#endif /* CONFIG_PROC_FS */
5957#endif /* ADVANSYS_STATS */
5958
5959#ifdef ADVANSYS_DEBUG
5960/*
5961 * asc_prt_scsi_host()
5962 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005963static void asc_prt_scsi_host(struct Scsi_Host *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005964{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005965 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005966
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005967 boardp = ASC_BOARDP(s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005968
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005969 printk("Scsi_Host at addr 0x%lx\n", (ulong)s);
5970 printk(" host_busy %u, host_no %d, last_reset %d,\n",
5971 s->host_busy, s->host_no, (unsigned)s->last_reset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972
Matthew Wilcox4a2d31c2007-07-26 11:55:34 -04005973 printk(" base 0x%lx, io_port 0x%lx, irq 0x%x,\n",
5974 (ulong)s->base, (ulong)s->io_port, s->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005976 printk(" dma_channel %d, this_id %d, can_queue %d,\n",
5977 s->dma_channel, s->this_id, s->can_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005979 printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n",
5980 s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005981
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005982 if (ASC_NARROW_BOARD(boardp)) {
5983 asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var);
5984 asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg);
5985 } else {
5986 asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var);
5987 asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg);
5988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005989}
5990
5991/*
5992 * asc_prt_scsi_cmnd()
5993 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005994static void asc_prt_scsi_cmnd(struct scsi_cmnd *s)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005995{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005996 printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005997
Matthew Wilcox27c868c2007-07-26 10:56:23 -04005998 printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n",
5999 (ulong)s->device->host, (ulong)s->device, s->device->id,
6000 s->device->lun, s->device->channel);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006001
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006002 asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006004 printk("sc_data_direction %u, resid %d\n",
6005 s->sc_data_direction, s->resid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006006
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006007 printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006009 printk(" serial_number 0x%x, retries %d, allowed %d\n",
6010 (unsigned)s->serial_number, s->retries, s->allowed);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006012 printk(" timeout_per_command %d\n", s->timeout_per_command);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006014 printk(" scsi_done 0x%p, done 0x%p, host_scribble 0x%p, result 0x%x\n",
6015 s->scsi_done, s->done, s->host_scribble, s->result);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006016
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006017 printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018}
6019
6020/*
6021 * asc_prt_asc_dvc_var()
6022 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006023static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006024{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006025 printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006027 printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl "
6028 "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029
Matthew Wilcox895d6b42007-07-26 11:57:06 -04006030 printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type,
6031 (unsigned)h->init_sdtr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006033 printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, "
6034 "chip_no 0x%x,\n", (unsigned)h->sdtr_done,
6035 (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready,
6036 (unsigned)h->chip_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006038 printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait "
6039 "%u,\n", (unsigned)h->queue_full_or_busy,
6040 (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006041
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006042 printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, "
6043 "in_critical_cnt %u,\n", (unsigned)h->is_in_int,
6044 (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng,
6045 (unsigned)h->in_critical_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006047 printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, "
6048 "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage,
6049 (unsigned)h->init_state, (unsigned)h->no_scam,
6050 (unsigned)h->pci_fix_asyn_xfer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006051
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006052 printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053}
6054
6055/*
6056 * asc_prt_asc_dvc_cfg()
6057 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006058static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006059{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006060 printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006061
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006062 printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n",
6063 h->can_tagged_qng, h->cmd_qng_enabled);
6064 printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n",
6065 h->disc_enable, h->sdtr_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006067 printk
6068 (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
6069 h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel,
6070 h->chip_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006072 printk
6073 (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n",
6074 to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version,
6075 h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006076
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006077 printk(" mcode_version %d, overrun_buf 0x%lx\n",
6078 h->mcode_version, (ulong)h->overrun_buf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079}
6080
6081/*
6082 * asc_prt_asc_scsi_q()
6083 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006084static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006085{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006086 ASC_SG_HEAD *sgp;
6087 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006089 printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006091 printk
6092 (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n",
6093 q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr,
6094 q->q2.tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006096 printk
6097 (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6098 (ulong)le32_to_cpu(q->q1.data_addr),
6099 (ulong)le32_to_cpu(q->q1.data_cnt),
6100 (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006101
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006102 printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n",
6103 (ulong)q->cdbptr, q->q2.cdb_len,
6104 (ulong)q->sg_head, q->q1.sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006105
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006106 if (q->sg_head) {
6107 sgp = q->sg_head;
6108 printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp);
6109 printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt,
6110 sgp->queue_cnt);
6111 for (i = 0; i < sgp->entry_cnt; i++) {
6112 printk(" [%u]: addr 0x%lx, bytes %lu\n",
6113 i, (ulong)le32_to_cpu(sgp->sg_list[i].addr),
6114 (ulong)le32_to_cpu(sgp->sg_list[i].bytes));
6115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118}
6119
6120/*
6121 * asc_prt_asc_qdone_info()
6122 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006123static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006125 printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q);
6126 printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n",
6127 (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len,
6128 q->d2.tag_code);
6129 printk
6130 (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n",
6131 q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132}
6133
6134/*
6135 * asc_prt_adv_dvc_var()
6136 *
6137 * Display an ADV_DVC_VAR structure.
6138 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006139static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006140{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006141 printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006143 printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n",
6144 (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006146 printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n",
6147 (ulong)h->isr_callback, (unsigned)h->sdtr_able,
6148 (unsigned)h->wdtr_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006149
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006150 printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n",
6151 (unsigned)h->start_motor,
6152 (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006154 printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n",
6155 (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng,
6156 (ulong)h->carr_freelist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006157
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006158 printk(" icq_sp 0x%lx, irq_sp 0x%lx\n",
6159 (ulong)h->icq_sp, (ulong)h->irq_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006161 printk(" no_scam 0x%x, tagqng_able 0x%x\n",
6162 (unsigned)h->no_scam, (unsigned)h->tagqng_able);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006163
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006164 printk(" chip_scsi_id 0x%x, cfg 0x%lx\n",
6165 (unsigned)h->chip_scsi_id, (ulong)h->cfg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166}
6167
6168/*
6169 * asc_prt_adv_dvc_cfg()
6170 *
6171 * Display an ADV_DVC_CFG structure.
6172 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006173static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006174{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006175 printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006177 printk(" disc_enable 0x%x, termination 0x%x\n",
6178 h->disc_enable, h->termination);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006179
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006180 printk(" chip_version 0x%x, mcode_date 0x%x\n",
6181 h->chip_version, h->mcode_date);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006182
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006183 printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n",
6184 h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006185
Matthew Wilcox13ac2d92007-07-30 08:10:23 -06006186 printk(" control_flag 0x%x\n", h->control_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187}
6188
6189/*
6190 * asc_prt_adv_scsi_req_q()
6191 *
6192 * Display an ADV_SCSI_REQ_Q structure.
6193 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006194static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006196 int sg_blk_cnt;
6197 struct asc_sg_block *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006198
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006199 printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006201 printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n",
6202 q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006204 printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n",
6205 q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006206
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006207 printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n",
6208 (ulong)le32_to_cpu(q->data_cnt),
6209 (ulong)le32_to_cpu(q->sense_addr), q->sense_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006211 printk
6212 (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n",
6213 q->cdb_len, q->done_status, q->host_status, q->scsi_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006214
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006215 printk(" sg_working_ix 0x%x, target_cmd %u\n",
6216 q->sg_working_ix, q->target_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006217
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006218 printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n",
6219 (ulong)le32_to_cpu(q->scsiq_rptr),
6220 (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006221
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006222 /* Display the request's ADV_SG_BLOCK structures. */
6223 if (q->sg_list_ptr != NULL) {
6224 sg_blk_cnt = 0;
6225 while (1) {
6226 /*
6227 * 'sg_ptr' is a physical address. Convert it to a virtual
6228 * address by indexing 'sg_blk_cnt' into the virtual address
6229 * array 'sg_list_ptr'.
6230 *
6231 * XXX - Assumes all SG physical blocks are virtually contiguous.
6232 */
6233 sg_ptr =
6234 &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]);
6235 asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr);
6236 if (sg_ptr->sg_ptr == 0) {
6237 break;
6238 }
6239 sg_blk_cnt++;
6240 }
6241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006242}
6243
6244/*
6245 * asc_prt_adv_sgblock()
6246 *
6247 * Display an ADV_SG_BLOCK structure.
6248 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006249static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006251 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006253 printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n",
6254 (ulong)b, sgblockno);
6255 printk(" sg_cnt %u, sg_ptr 0x%lx\n",
6256 b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr));
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06006257 BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK);
6258 if (b->sg_ptr != 0)
6259 BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006260 for (i = 0; i < b->sg_cnt; i++) {
6261 printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n",
6262 i, (ulong)b->sg_list[i].sg_addr,
6263 (ulong)b->sg_list[i].sg_count);
6264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265}
6266
6267/*
6268 * asc_prt_hex()
6269 *
6270 * Print hexadecimal output in 4 byte groupings 32 bytes
6271 * or 8 double-words per line.
6272 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006273static void asc_prt_hex(char *f, uchar *s, int l)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006275 int i;
6276 int j;
6277 int k;
6278 int m;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006279
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006280 printk("%s: (%d bytes)\n", f, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006282 for (i = 0; i < l; i += 32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006283
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006284 /* Display a maximum of 8 double-words per line. */
6285 if ((k = (l - i) / 4) >= 8) {
6286 k = 8;
6287 m = 0;
6288 } else {
6289 m = (l - i) % 4;
6290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006292 for (j = 0; j < k; j++) {
6293 printk(" %2.2X%2.2X%2.2X%2.2X",
6294 (unsigned)s[i + (j * 4)],
6295 (unsigned)s[i + (j * 4) + 1],
6296 (unsigned)s[i + (j * 4) + 2],
6297 (unsigned)s[i + (j * 4) + 3]);
6298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006300 switch (m) {
6301 case 0:
6302 default:
6303 break;
6304 case 1:
6305 printk(" %2.2X", (unsigned)s[i + (j * 4)]);
6306 break;
6307 case 2:
6308 printk(" %2.2X%2.2X",
6309 (unsigned)s[i + (j * 4)],
6310 (unsigned)s[i + (j * 4) + 1]);
6311 break;
6312 case 3:
6313 printk(" %2.2X%2.2X%2.2X",
6314 (unsigned)s[i + (j * 4) + 1],
6315 (unsigned)s[i + (j * 4) + 2],
6316 (unsigned)s[i + (j * 4) + 3]);
6317 break;
6318 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006319
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006320 printk("\n");
6321 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006322}
6323#endif /* ADVANSYS_DEBUG */
6324
6325/*
6326 * --- Asc Library Functions
6327 */
6328
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006329static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006330{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006331 PortAddr eisa_cfg_iop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006333 eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6334 (PortAddr) (ASC_EISA_CFG_IOP_MASK);
6335 return (inpw(eisa_cfg_iop));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336}
6337
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006338static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006339{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006340 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006341
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006342 if (AscGetChipScsiID(iop_base) == new_host_id) {
6343 return (new_host_id);
6344 }
6345 cfg_lsw = AscGetChipCfgLsw(iop_base);
6346 cfg_lsw &= 0xF8FF;
6347 cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8);
6348 AscSetChipCfgLsw(iop_base, cfg_lsw);
6349 return (AscGetChipScsiID(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006350}
6351
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006352static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006353{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006354 unsigned char sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006355
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006356 AscSetBank(iop_base, 1);
6357 sc = inp(iop_base + IOP_REG_SC);
6358 AscSetBank(iop_base, 0);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006359 return sc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006360}
6361
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006362static unsigned char __devinit
6363AscGetChipVersion(PortAddr iop_base, unsigned short bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006364{
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006365 if (bus_type & ASC_IS_EISA) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006366 PortAddr eisa_iop;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006367 unsigned char revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006368 eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) |
6369 (PortAddr) ASC_EISA_REV_IOP_MASK;
6370 revision = inp(eisa_iop);
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006371 return ASC_CHIP_MIN_VER_EISA - 1 + revision;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006372 }
Matthew Wilcoxecec1942007-07-30 08:08:22 -06006373 return AscGetChipVerNo(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006374}
6375
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006376static ASC_DCNT
6377AscLoadMicroCode(PortAddr iop_base,
6378 ushort s_addr, uchar *mcode_buf, ushort mcode_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006379{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006380 ASC_DCNT chksum;
6381 ushort mcode_word_size;
6382 ushort mcode_chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006383
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006384 /* Write the microcode buffer starting at LRAM address 0. */
6385 mcode_word_size = (ushort)(mcode_size >> 1);
6386 AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size);
6387 AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006388
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006389 chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size);
6390 ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum);
6391 mcode_chksum = (ushort)AscMemSumLramWord(iop_base,
6392 (ushort)ASC_CODE_SEC_BEG,
6393 (ushort)((mcode_size -
6394 s_addr - (ushort)
6395 ASC_CODE_SEC_BEG) /
6396 2));
6397 ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n",
6398 (ulong)mcode_chksum);
6399 AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum);
6400 AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size);
6401 return (chksum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006402}
6403
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006404static int AscFindSignature(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006405{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006406 ushort sig_word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006407
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006408 ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n",
6409 iop_base, AscGetChipSignatureByte(iop_base));
6410 if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) {
6411 ASC_DBG2(1,
6412 "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n",
6413 iop_base, AscGetChipSignatureWord(iop_base));
6414 sig_word = AscGetChipSignatureWord(iop_base);
6415 if ((sig_word == (ushort)ASC_1000_ID0W) ||
6416 (sig_word == (ushort)ASC_1000_ID0W_FIX)) {
6417 return (1);
6418 }
6419 }
6420 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006421}
6422
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006423static void __devinit AscToggleIRQAct(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006424{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006425 AscSetChipStatus(iop_base, CIW_IRQ_ACT);
6426 AscSetChipStatus(iop_base, 0);
6427 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006428}
6429
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006430static uchar __devinit AscGetChipIRQ(PortAddr iop_base, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006431{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006432 ushort cfg_lsw;
6433 uchar chip_irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006435 if ((bus_type & ASC_IS_EISA) != 0) {
6436 cfg_lsw = AscGetEisaChipCfg(iop_base);
6437 chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10);
6438 if ((chip_irq == 13) || (chip_irq > 15)) {
6439 return (0);
6440 }
6441 return (chip_irq);
6442 }
6443 if ((bus_type & ASC_IS_VL) != 0) {
6444 cfg_lsw = AscGetChipCfgLsw(iop_base);
6445 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07));
6446 if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) {
6447 return (0);
6448 }
6449 return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1)));
6450 }
6451 cfg_lsw = AscGetChipCfgLsw(iop_base);
6452 chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03));
6453 if (chip_irq == 3)
6454 chip_irq += (uchar)2;
6455 return ((uchar)(chip_irq + ASC_MIN_IRQ_NO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006456}
6457
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006458static uchar __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006459AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006461 ushort cfg_lsw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006462
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006463 if ((bus_type & ASC_IS_VL) != 0) {
6464 if (irq_no != 0) {
6465 if ((irq_no < ASC_MIN_IRQ_NO)
6466 || (irq_no > ASC_MAX_IRQ_NO)) {
6467 irq_no = 0;
6468 } else {
6469 irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1));
6470 }
6471 }
6472 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3);
6473 cfg_lsw |= (ushort)0x0010;
6474 AscSetChipCfgLsw(iop_base, cfg_lsw);
6475 AscToggleIRQAct(iop_base);
6476 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0);
6477 cfg_lsw |= (ushort)((irq_no & 0x07) << 2);
6478 AscSetChipCfgLsw(iop_base, cfg_lsw);
6479 AscToggleIRQAct(iop_base);
6480 return (AscGetChipIRQ(iop_base, bus_type));
6481 }
6482 if ((bus_type & (ASC_IS_ISA)) != 0) {
6483 if (irq_no == 15)
6484 irq_no -= (uchar)2;
6485 irq_no -= (uchar)ASC_MIN_IRQ_NO;
6486 cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3);
6487 cfg_lsw |= (ushort)((irq_no & 0x03) << 2);
6488 AscSetChipCfgLsw(iop_base, cfg_lsw);
6489 return (AscGetChipIRQ(iop_base, bus_type));
6490 }
6491 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006492}
6493
6494#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06006495static void __devinit AscEnableIsaDma(uchar dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006496{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006497 if (dma_channel < 4) {
6498 outp(0x000B, (ushort)(0xC0 | dma_channel));
6499 outp(0x000A, dma_channel);
6500 } else if (dma_channel < 8) {
6501 outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4)));
6502 outp(0x00D4, (ushort)(dma_channel - 4));
6503 }
6504 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006505}
6506#endif /* CONFIG_ISA */
6507
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006508static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006509{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006510 EXT_MSG ext_msg;
6511 EXT_MSG out_msg;
6512 ushort halt_q_addr;
6513 int sdtr_accept;
6514 ushort int_halt_code;
6515 ASC_SCSI_BIT_ID_TYPE scsi_busy;
6516 ASC_SCSI_BIT_ID_TYPE target_id;
6517 PortAddr iop_base;
6518 uchar tag_code;
6519 uchar q_status;
6520 uchar halt_qp;
6521 uchar sdtr_data;
6522 uchar target_ix;
6523 uchar q_cntl, tid_no;
6524 uchar cur_dvc_qng;
6525 uchar asyn_sdtr;
6526 uchar scsi_status;
6527 asc_board_t *boardp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006528
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06006529 BUG_ON(!asc_dvc->drv_ptr);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006530 boardp = asc_dvc->drv_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006531
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006532 iop_base = asc_dvc->iop_base;
6533 int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006534
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006535 halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B);
6536 halt_q_addr = ASC_QNO_TO_QADDR(halt_qp);
6537 target_ix = AscReadLramByte(iop_base,
6538 (ushort)(halt_q_addr +
6539 (ushort)ASC_SCSIQ_B_TARGET_IX));
6540 q_cntl =
6541 AscReadLramByte(iop_base,
6542 (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL));
6543 tid_no = ASC_TIX_TO_TID(target_ix);
6544 target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no);
6545 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6546 asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB;
6547 } else {
6548 asyn_sdtr = 0;
6549 }
6550 if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) {
6551 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6552 AscSetChipSDTR(iop_base, 0, tid_no);
6553 boardp->sdtr_data[tid_no] = 0;
6554 }
6555 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6556 return (0);
6557 } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) {
6558 if (asc_dvc->pci_fix_asyn_xfer & target_id) {
6559 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6560 boardp->sdtr_data[tid_no] = asyn_sdtr;
6561 }
6562 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6563 return (0);
6564 } else if (int_halt_code == ASC_HALT_EXTMSG_IN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006565
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006566 AscMemWordCopyPtrFromLram(iop_base,
6567 ASCV_MSGIN_BEG,
6568 (uchar *)&ext_msg,
6569 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006570
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006571 if (ext_msg.msg_type == EXTENDED_MESSAGE &&
6572 ext_msg.msg_req == EXTENDED_SDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006573 ext_msg.msg_len == MS_SDTR_LEN) {
6574 sdtr_accept = TRUE;
6575 if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006576
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006577 sdtr_accept = FALSE;
6578 ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET;
6579 }
6580 if ((ext_msg.xfer_period <
6581 asc_dvc->sdtr_period_tbl[asc_dvc->
6582 host_init_sdtr_index])
6583 || (ext_msg.xfer_period >
6584 asc_dvc->sdtr_period_tbl[asc_dvc->
6585 max_sdtr_index])) {
6586 sdtr_accept = FALSE;
6587 ext_msg.xfer_period =
6588 asc_dvc->sdtr_period_tbl[asc_dvc->
6589 host_init_sdtr_index];
6590 }
6591 if (sdtr_accept) {
6592 sdtr_data =
6593 AscCalSDTRData(asc_dvc, ext_msg.xfer_period,
6594 ext_msg.req_ack_offset);
6595 if ((sdtr_data == 0xFF)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006596
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006597 q_cntl |= QC_MSG_OUT;
6598 asc_dvc->init_sdtr &= ~target_id;
6599 asc_dvc->sdtr_done &= ~target_id;
6600 AscSetChipSDTR(iop_base, asyn_sdtr,
6601 tid_no);
6602 boardp->sdtr_data[tid_no] = asyn_sdtr;
6603 }
6604 }
6605 if (ext_msg.req_ack_offset == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006606
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006607 q_cntl &= ~QC_MSG_OUT;
6608 asc_dvc->init_sdtr &= ~target_id;
6609 asc_dvc->sdtr_done &= ~target_id;
6610 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6611 } else {
6612 if (sdtr_accept && (q_cntl & QC_MSG_OUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006613
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006614 q_cntl &= ~QC_MSG_OUT;
6615 asc_dvc->sdtr_done |= target_id;
6616 asc_dvc->init_sdtr |= target_id;
6617 asc_dvc->pci_fix_asyn_xfer &=
6618 ~target_id;
6619 sdtr_data =
6620 AscCalSDTRData(asc_dvc,
6621 ext_msg.xfer_period,
6622 ext_msg.
6623 req_ack_offset);
6624 AscSetChipSDTR(iop_base, sdtr_data,
6625 tid_no);
6626 boardp->sdtr_data[tid_no] = sdtr_data;
6627 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006628
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006629 q_cntl |= QC_MSG_OUT;
6630 AscMsgOutSDTR(asc_dvc,
6631 ext_msg.xfer_period,
6632 ext_msg.req_ack_offset);
6633 asc_dvc->pci_fix_asyn_xfer &=
6634 ~target_id;
6635 sdtr_data =
6636 AscCalSDTRData(asc_dvc,
6637 ext_msg.xfer_period,
6638 ext_msg.
6639 req_ack_offset);
6640 AscSetChipSDTR(iop_base, sdtr_data,
6641 tid_no);
6642 boardp->sdtr_data[tid_no] = sdtr_data;
6643 asc_dvc->sdtr_done |= target_id;
6644 asc_dvc->init_sdtr |= target_id;
6645 }
6646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006647
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006648 AscWriteLramByte(iop_base,
6649 (ushort)(halt_q_addr +
6650 (ushort)ASC_SCSIQ_B_CNTL),
6651 q_cntl);
6652 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6653 return (0);
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006654 } else if (ext_msg.msg_type == EXTENDED_MESSAGE &&
6655 ext_msg.msg_req == EXTENDED_WDTR &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006656 ext_msg.msg_len == MS_WDTR_LEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006657
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006658 ext_msg.wdtr_width = 0;
6659 AscMemWordCopyPtrToLram(iop_base,
6660 ASCV_MSGOUT_BEG,
6661 (uchar *)&ext_msg,
6662 sizeof(EXT_MSG) >> 1);
6663 q_cntl |= QC_MSG_OUT;
6664 AscWriteLramByte(iop_base,
6665 (ushort)(halt_q_addr +
6666 (ushort)ASC_SCSIQ_B_CNTL),
6667 q_cntl);
6668 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6669 return (0);
6670 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006671
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006672 ext_msg.msg_type = MESSAGE_REJECT;
6673 AscMemWordCopyPtrToLram(iop_base,
6674 ASCV_MSGOUT_BEG,
6675 (uchar *)&ext_msg,
6676 sizeof(EXT_MSG) >> 1);
6677 q_cntl |= QC_MSG_OUT;
6678 AscWriteLramByte(iop_base,
6679 (ushort)(halt_q_addr +
6680 (ushort)ASC_SCSIQ_B_CNTL),
6681 q_cntl);
6682 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6683 return (0);
6684 }
6685 } else if (int_halt_code == ASC_HALT_CHK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006686
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006687 q_cntl |= QC_REQ_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006688
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006689 if ((asc_dvc->init_sdtr & target_id) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006690
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006691 asc_dvc->sdtr_done &= ~target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006692
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006693 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
6694 q_cntl |= QC_MSG_OUT;
6695 AscMsgOutSDTR(asc_dvc,
6696 asc_dvc->
6697 sdtr_period_tbl[(sdtr_data >> 4) &
6698 (uchar)(asc_dvc->
6699 max_sdtr_index -
6700 1)],
6701 (uchar)(sdtr_data & (uchar)
6702 ASC_SYN_MAX_OFFSET));
6703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006704
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006705 AscWriteLramByte(iop_base,
6706 (ushort)(halt_q_addr +
6707 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006708
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006709 tag_code = AscReadLramByte(iop_base,
6710 (ushort)(halt_q_addr + (ushort)
6711 ASC_SCSIQ_B_TAG_CODE));
6712 tag_code &= 0xDC;
6713 if ((asc_dvc->pci_fix_asyn_xfer & target_id)
6714 && !(asc_dvc->pci_fix_asyn_xfer_always & target_id)
6715 ) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006716
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006717 tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT
6718 | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006719
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006720 }
6721 AscWriteLramByte(iop_base,
6722 (ushort)(halt_q_addr +
6723 (ushort)ASC_SCSIQ_B_TAG_CODE),
6724 tag_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006725
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006726 q_status = AscReadLramByte(iop_base,
6727 (ushort)(halt_q_addr + (ushort)
6728 ASC_SCSIQ_B_STATUS));
6729 q_status |= (QS_READY | QS_BUSY);
6730 AscWriteLramByte(iop_base,
6731 (ushort)(halt_q_addr +
6732 (ushort)ASC_SCSIQ_B_STATUS),
6733 q_status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006734
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006735 scsi_busy = AscReadLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B);
6736 scsi_busy &= ~target_id;
6737 AscWriteLramByte(iop_base, (ushort)ASCV_SCSIBUSY_B, scsi_busy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006738
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006739 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6740 return (0);
6741 } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006742
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006743 AscMemWordCopyPtrFromLram(iop_base,
6744 ASCV_MSGOUT_BEG,
6745 (uchar *)&out_msg,
6746 sizeof(EXT_MSG) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006747
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006748 if ((out_msg.msg_type == EXTENDED_MESSAGE) &&
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006749 (out_msg.msg_len == MS_SDTR_LEN) &&
Matthew Wilcox47d853c2007-07-26 11:41:33 -04006750 (out_msg.msg_req == EXTENDED_SDTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006751
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006752 asc_dvc->init_sdtr &= ~target_id;
6753 asc_dvc->sdtr_done &= ~target_id;
6754 AscSetChipSDTR(iop_base, asyn_sdtr, tid_no);
6755 boardp->sdtr_data[tid_no] = asyn_sdtr;
6756 }
6757 q_cntl &= ~QC_MSG_OUT;
6758 AscWriteLramByte(iop_base,
6759 (ushort)(halt_q_addr +
6760 (ushort)ASC_SCSIQ_B_CNTL), q_cntl);
6761 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6762 return (0);
6763 } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006764
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006765 scsi_status = AscReadLramByte(iop_base,
6766 (ushort)((ushort)halt_q_addr +
6767 (ushort)
6768 ASC_SCSIQ_SCSI_STATUS));
6769 cur_dvc_qng =
6770 AscReadLramByte(iop_base,
6771 (ushort)((ushort)ASC_QADR_BEG +
6772 (ushort)target_ix));
6773 if ((cur_dvc_qng > 0) && (asc_dvc->cur_dvc_qng[tid_no] > 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006774
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006775 scsi_busy = AscReadLramByte(iop_base,
6776 (ushort)ASCV_SCSIBUSY_B);
6777 scsi_busy |= target_id;
6778 AscWriteLramByte(iop_base,
6779 (ushort)ASCV_SCSIBUSY_B, scsi_busy);
6780 asc_dvc->queue_full_or_busy |= target_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006781
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006782 if (scsi_status == SAM_STAT_TASK_SET_FULL) {
6783 if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) {
6784 cur_dvc_qng -= 1;
6785 asc_dvc->max_dvc_qng[tid_no] =
6786 cur_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006787
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006788 AscWriteLramByte(iop_base,
6789 (ushort)((ushort)
6790 ASCV_MAX_DVC_QNG_BEG
6791 + (ushort)
6792 tid_no),
6793 cur_dvc_qng);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006794
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006795 /*
6796 * Set the device queue depth to the number of
6797 * active requests when the QUEUE FULL condition
6798 * was encountered.
6799 */
6800 boardp->queue_full |= target_id;
6801 boardp->queue_full_cnt[tid_no] =
6802 cur_dvc_qng;
6803 }
6804 }
6805 }
6806 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6807 return (0);
6808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006809#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006810 else if (int_halt_code == ASC_HALT_HOST_COPY_SG_LIST_TO_RISC) {
6811 uchar q_no;
6812 ushort q_addr;
6813 uchar sg_wk_q_no;
6814 uchar first_sg_wk_q_no;
6815 ASC_SCSI_Q *scsiq; /* Ptr to driver request. */
6816 ASC_SG_HEAD *sg_head; /* Ptr to driver SG request. */
6817 ASC_SG_LIST_Q scsi_sg_q; /* Structure written to queue. */
6818 ushort sg_list_dwords;
6819 ushort sg_entry_cnt;
6820 uchar next_qp;
6821 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006822
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006823 q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP);
6824 if (q_no == ASC_QLINK_END) {
6825 return (0);
6826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006827
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006828 q_addr = ASC_QNO_TO_QADDR(q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006829
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006830 /*
6831 * Convert the request's SRB pointer to a host ASC_SCSI_REQ
6832 * structure pointer using a macro provided by the driver.
6833 * The ASC_SCSI_REQ pointer provides a pointer to the
6834 * host ASC_SG_HEAD structure.
6835 */
6836 /* Read request's SRB pointer. */
6837 scsiq = (ASC_SCSI_Q *)
6838 ASC_SRB2SCSIQ(ASC_U32_TO_VADDR(AscReadLramDWord(iop_base,
6839 (ushort)
6840 (q_addr +
6841 ASC_SCSIQ_D_SRBPTR))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006842
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006843 /*
6844 * Get request's first and working SG queue.
6845 */
6846 sg_wk_q_no = AscReadLramByte(iop_base,
6847 (ushort)(q_addr +
6848 ASC_SCSIQ_B_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006849
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006850 first_sg_wk_q_no = AscReadLramByte(iop_base,
6851 (ushort)(q_addr +
6852 ASC_SCSIQ_B_FIRST_SG_WK_QP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006853
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006854 /*
6855 * Reset request's working SG queue back to the
6856 * first SG queue.
6857 */
6858 AscWriteLramByte(iop_base,
6859 (ushort)(q_addr +
6860 (ushort)ASC_SCSIQ_B_SG_WK_QP),
6861 first_sg_wk_q_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006862
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006863 sg_head = scsiq->sg_head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006864
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006865 /*
6866 * Set sg_entry_cnt to the number of SG elements
6867 * that will be completed on this interrupt.
6868 *
6869 * Note: The allocated SG queues contain ASC_MAX_SG_LIST - 1
6870 * SG elements. The data_cnt and data_addr fields which
6871 * add 1 to the SG element capacity are not used when
6872 * restarting SG handling after a halt.
6873 */
6874 if (scsiq->remain_sg_entry_cnt > (ASC_MAX_SG_LIST - 1)) {
6875 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006876
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006877 /*
6878 * Keep track of remaining number of SG elements that will
6879 * need to be handled on the next interrupt.
6880 */
6881 scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1);
6882 } else {
6883 sg_entry_cnt = scsiq->remain_sg_entry_cnt;
6884 scsiq->remain_sg_entry_cnt = 0;
6885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006887 /*
6888 * Copy SG elements into the list of allocated SG queues.
6889 *
6890 * Last index completed is saved in scsiq->next_sg_index.
6891 */
6892 next_qp = first_sg_wk_q_no;
6893 q_addr = ASC_QNO_TO_QADDR(next_qp);
6894 scsi_sg_q.sg_head_qp = q_no;
6895 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
6896 for (i = 0; i < sg_head->queue_cnt; i++) {
6897 scsi_sg_q.seq_no = i + 1;
6898 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
6899 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
6900 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
6901 /*
6902 * After very first SG queue RISC FW uses next
6903 * SG queue first element then checks sg_list_cnt
6904 * against zero and then decrements, so set
6905 * sg_list_cnt 1 less than number of SG elements
6906 * in each SG queue.
6907 */
6908 scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1;
6909 scsi_sg_q.sg_cur_list_cnt =
6910 ASC_SG_LIST_PER_Q - 1;
6911 } else {
6912 /*
6913 * This is the last SG queue in the list of
6914 * allocated SG queues. If there are more
6915 * SG elements than will fit in the allocated
6916 * queues, then set the QCSG_SG_XFER_MORE flag.
6917 */
6918 if (scsiq->remain_sg_entry_cnt != 0) {
6919 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
6920 } else {
6921 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
6922 }
6923 /* equals sg_entry_cnt * 2 */
6924 sg_list_dwords = sg_entry_cnt << 1;
6925 scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1;
6926 scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1;
6927 sg_entry_cnt = 0;
6928 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006929
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006930 scsi_sg_q.q_no = next_qp;
6931 AscMemWordCopyPtrToLram(iop_base,
6932 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
6933 (uchar *)&scsi_sg_q,
6934 sizeof(ASC_SG_LIST_Q) >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006935
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006936 AscMemDWordCopyPtrToLram(iop_base,
6937 q_addr + ASC_SGQ_LIST_BEG,
6938 (uchar *)&sg_head->
6939 sg_list[scsiq->next_sg_index],
6940 sg_list_dwords);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006941
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006942 scsiq->next_sg_index += ASC_SG_LIST_PER_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006943
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006944 /*
6945 * If the just completed SG queue contained the
6946 * last SG element, then no more SG queues need
6947 * to be written.
6948 */
6949 if (scsi_sg_q.cntl & QCSG_SG_XFER_END) {
6950 break;
6951 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006952
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006953 next_qp = AscReadLramByte(iop_base,
6954 (ushort)(q_addr +
6955 ASC_SCSIQ_B_FWD));
6956 q_addr = ASC_QNO_TO_QADDR(next_qp);
6957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006958
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006959 /*
6960 * Clear the halt condition so the RISC will be restarted
6961 * after the return.
6962 */
6963 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
6964 return (0);
6965 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006966#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006967 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006968}
6969
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006970static uchar
6971_AscCopyLramScsiDoneQ(PortAddr iop_base,
6972 ushort q_addr,
6973 ASC_QDONE_INFO *scsiq, ASC_DCNT max_dma_count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006974{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006975 ushort _val;
6976 uchar sg_queue_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006977
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006978 DvcGetQinfo(iop_base,
6979 q_addr + ASC_SCSIQ_DONE_INFO_BEG,
6980 (uchar *)scsiq,
6981 (sizeof(ASC_SCSIQ_2) + sizeof(ASC_SCSIQ_3)) / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006982
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006983 _val = AscReadLramWord(iop_base,
6984 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS));
6985 scsiq->q_status = (uchar)_val;
6986 scsiq->q_no = (uchar)(_val >> 8);
6987 _val = AscReadLramWord(iop_base,
6988 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_CNTL));
6989 scsiq->cntl = (uchar)_val;
6990 sg_queue_cnt = (uchar)(_val >> 8);
6991 _val = AscReadLramWord(iop_base,
6992 (ushort)(q_addr +
6993 (ushort)ASC_SCSIQ_B_SENSE_LEN));
6994 scsiq->sense_len = (uchar)_val;
6995 scsiq->extra_bytes = (uchar)(_val >> 8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006996
Matthew Wilcox27c868c2007-07-26 10:56:23 -04006997 /*
6998 * Read high word of remain bytes from alternate location.
6999 */
7000 scsiq->remain_bytes = (((ADV_DCNT)AscReadLramWord(iop_base,
7001 (ushort)(q_addr +
7002 (ushort)
7003 ASC_SCSIQ_W_ALT_DC1)))
7004 << 16);
7005 /*
7006 * Read low word of remain bytes from original location.
7007 */
7008 scsiq->remain_bytes += AscReadLramWord(iop_base,
7009 (ushort)(q_addr + (ushort)
7010 ASC_SCSIQ_DW_REMAIN_XFER_CNT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007011
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007012 scsiq->remain_bytes &= max_dma_count;
7013 return (sg_queue_cnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007014}
7015
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007016static int AscIsrQDone(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007017{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007018 uchar next_qp;
7019 uchar n_q_used;
7020 uchar sg_list_qp;
7021 uchar sg_queue_cnt;
7022 uchar q_cnt;
7023 uchar done_q_tail;
7024 uchar tid_no;
7025 ASC_SCSI_BIT_ID_TYPE scsi_busy;
7026 ASC_SCSI_BIT_ID_TYPE target_id;
7027 PortAddr iop_base;
7028 ushort q_addr;
7029 ushort sg_q_addr;
7030 uchar cur_target_qng;
7031 ASC_QDONE_INFO scsiq_buf;
7032 ASC_QDONE_INFO *scsiq;
7033 int false_overrun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007035 iop_base = asc_dvc->iop_base;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007036 n_q_used = 1;
7037 scsiq = (ASC_QDONE_INFO *)&scsiq_buf;
7038 done_q_tail = (uchar)AscGetVarDoneQTail(iop_base);
7039 q_addr = ASC_QNO_TO_QADDR(done_q_tail);
7040 next_qp = AscReadLramByte(iop_base,
7041 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_FWD));
7042 if (next_qp != ASC_QLINK_END) {
7043 AscPutVarDoneQTail(iop_base, next_qp);
7044 q_addr = ASC_QNO_TO_QADDR(next_qp);
7045 sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq,
7046 asc_dvc->max_dma_count);
7047 AscWriteLramByte(iop_base,
7048 (ushort)(q_addr +
7049 (ushort)ASC_SCSIQ_B_STATUS),
7050 (uchar)(scsiq->
7051 q_status & (uchar)~(QS_READY |
7052 QS_ABORTED)));
7053 tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix);
7054 target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix);
7055 if ((scsiq->cntl & QC_SG_HEAD) != 0) {
7056 sg_q_addr = q_addr;
7057 sg_list_qp = next_qp;
7058 for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) {
7059 sg_list_qp = AscReadLramByte(iop_base,
7060 (ushort)(sg_q_addr
7061 + (ushort)
7062 ASC_SCSIQ_B_FWD));
7063 sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp);
7064 if (sg_list_qp == ASC_QLINK_END) {
7065 AscSetLibErrorCode(asc_dvc,
7066 ASCQ_ERR_SG_Q_LINKS);
7067 scsiq->d3.done_stat = QD_WITH_ERROR;
7068 scsiq->d3.host_stat =
7069 QHSTA_D_QDONE_SG_LIST_CORRUPTED;
7070 goto FATAL_ERR_QDONE;
7071 }
7072 AscWriteLramByte(iop_base,
7073 (ushort)(sg_q_addr + (ushort)
7074 ASC_SCSIQ_B_STATUS),
7075 QS_FREE);
7076 }
7077 n_q_used = sg_queue_cnt + 1;
7078 AscPutVarDoneQTail(iop_base, sg_list_qp);
7079 }
7080 if (asc_dvc->queue_full_or_busy & target_id) {
7081 cur_target_qng = AscReadLramByte(iop_base,
7082 (ushort)((ushort)
7083 ASC_QADR_BEG
7084 + (ushort)
7085 scsiq->d2.
7086 target_ix));
7087 if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) {
7088 scsi_busy = AscReadLramByte(iop_base, (ushort)
7089 ASCV_SCSIBUSY_B);
7090 scsi_busy &= ~target_id;
7091 AscWriteLramByte(iop_base,
7092 (ushort)ASCV_SCSIBUSY_B,
7093 scsi_busy);
7094 asc_dvc->queue_full_or_busy &= ~target_id;
7095 }
7096 }
7097 if (asc_dvc->cur_total_qng >= n_q_used) {
7098 asc_dvc->cur_total_qng -= n_q_used;
7099 if (asc_dvc->cur_dvc_qng[tid_no] != 0) {
7100 asc_dvc->cur_dvc_qng[tid_no]--;
7101 }
7102 } else {
7103 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG);
7104 scsiq->d3.done_stat = QD_WITH_ERROR;
7105 goto FATAL_ERR_QDONE;
7106 }
7107 if ((scsiq->d2.srb_ptr == 0UL) ||
7108 ((scsiq->q_status & QS_ABORTED) != 0)) {
7109 return (0x11);
7110 } else if (scsiq->q_status == QS_DONE) {
7111 false_overrun = FALSE;
7112 if (scsiq->extra_bytes != 0) {
7113 scsiq->remain_bytes +=
7114 (ADV_DCNT)scsiq->extra_bytes;
7115 }
7116 if (scsiq->d3.done_stat == QD_WITH_ERROR) {
7117 if (scsiq->d3.host_stat ==
7118 QHSTA_M_DATA_OVER_RUN) {
7119 if ((scsiq->
7120 cntl & (QC_DATA_IN | QC_DATA_OUT))
7121 == 0) {
7122 scsiq->d3.done_stat =
7123 QD_NO_ERROR;
7124 scsiq->d3.host_stat =
7125 QHSTA_NO_ERROR;
7126 } else if (false_overrun) {
7127 scsiq->d3.done_stat =
7128 QD_NO_ERROR;
7129 scsiq->d3.host_stat =
7130 QHSTA_NO_ERROR;
7131 }
7132 } else if (scsiq->d3.host_stat ==
7133 QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) {
7134 AscStopChip(iop_base);
7135 AscSetChipControl(iop_base,
7136 (uchar)(CC_SCSI_RESET
7137 | CC_HALT));
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007138 udelay(60);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007139 AscSetChipControl(iop_base, CC_HALT);
7140 AscSetChipStatus(iop_base,
7141 CIW_CLR_SCSI_RESET_INT);
7142 AscSetChipStatus(iop_base, 0);
7143 AscSetChipControl(iop_base, 0);
7144 }
7145 }
7146 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007147 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007148 } else {
7149 if ((AscReadLramByte(iop_base,
7150 (ushort)(q_addr + (ushort)
7151 ASC_SCSIQ_CDB_BEG))
7152 == START_STOP)) {
7153 asc_dvc->unit_not_ready &= ~target_id;
7154 if (scsiq->d3.done_stat != QD_NO_ERROR) {
7155 asc_dvc->start_motor &=
7156 ~target_id;
7157 }
7158 }
7159 }
7160 return (1);
7161 } else {
7162 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS);
7163 FATAL_ERR_QDONE:
7164 if ((scsiq->cntl & QC_NO_CALLBACK) == 0) {
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007165 asc_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007166 }
7167 return (0x80);
7168 }
7169 }
7170 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007171}
7172
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007173static int AscISR(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007174{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007175 ASC_CS_TYPE chipstat;
7176 PortAddr iop_base;
7177 ushort saved_ram_addr;
7178 uchar ctrl_reg;
7179 uchar saved_ctrl_reg;
7180 int int_pending;
7181 int status;
7182 uchar host_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007183
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007184 iop_base = asc_dvc->iop_base;
7185 int_pending = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007186
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007187 if (AscIsIntPending(iop_base) == 0) {
7188 return int_pending;
7189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007190
Matthew Wilcox895d6b42007-07-26 11:57:06 -04007191 if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007192 return (ERR);
7193 }
7194 if (asc_dvc->in_critical_cnt != 0) {
7195 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL);
7196 return (ERR);
7197 }
7198 if (asc_dvc->is_in_int) {
7199 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY);
7200 return (ERR);
7201 }
7202 asc_dvc->is_in_int = TRUE;
7203 ctrl_reg = AscGetChipControl(iop_base);
7204 saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET |
7205 CC_SINGLE_STEP | CC_DIAG | CC_TEST));
7206 chipstat = AscGetChipStatus(iop_base);
7207 if (chipstat & CSW_SCSI_RESET_LATCH) {
7208 if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) {
7209 int i = 10;
7210 int_pending = TRUE;
7211 asc_dvc->sdtr_done = 0;
7212 saved_ctrl_reg &= (uchar)(~CC_HALT);
7213 while ((AscGetChipStatus(iop_base) &
7214 CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) {
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06007215 mdelay(100);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007216 }
7217 AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT));
7218 AscSetChipControl(iop_base, CC_HALT);
7219 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
7220 AscSetChipStatus(iop_base, 0);
7221 chipstat = AscGetChipStatus(iop_base);
7222 }
7223 }
7224 saved_ram_addr = AscGetChipLramAddr(iop_base);
7225 host_flag = AscReadLramByte(iop_base,
7226 ASCV_HOST_FLAG_B) &
7227 (uchar)(~ASC_HOST_FLAG_IN_ISR);
7228 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
7229 (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR));
7230 if ((chipstat & CSW_INT_PENDING)
7231 || (int_pending)
7232 ) {
7233 AscAckInterrupt(iop_base);
7234 int_pending = TRUE;
7235 if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) {
7236 if (AscIsrChipHalted(asc_dvc) == ERR) {
7237 goto ISR_REPORT_QDONE_FATAL_ERROR;
7238 } else {
7239 saved_ctrl_reg &= (uchar)(~CC_HALT);
7240 }
7241 } else {
7242 ISR_REPORT_QDONE_FATAL_ERROR:
7243 if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) {
7244 while (((status =
7245 AscIsrQDone(asc_dvc)) & 0x01) != 0) {
7246 }
7247 } else {
7248 do {
7249 if ((status =
7250 AscIsrQDone(asc_dvc)) == 1) {
7251 break;
7252 }
7253 } while (status == 0x11);
7254 }
7255 if ((status & 0x80) != 0)
7256 int_pending = ERR;
7257 }
7258 }
7259 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
7260 AscSetChipLramAddr(iop_base, saved_ram_addr);
7261 AscSetChipControl(iop_base, saved_ctrl_reg);
7262 asc_dvc->is_in_int = FALSE;
7263 return (int_pending);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264}
7265
7266/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007267static uchar _asc_mcode_buf[] = {
7268 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007269 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
7274 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7275 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007276 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007277 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
7278 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
7279 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007280 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007281 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
7282 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
7283 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007284 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007285 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
7286 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
7287 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007288 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007289 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
7290 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
7291 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007292 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007293 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
7294 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
7295 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007296 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007297 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
7298 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
7299 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007300 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007301 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
7302 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
7303 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007304 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007305 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
7306 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
7307 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007308 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007309 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
7310 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
7311 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007312 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007313 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
7314 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
7315 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007316 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007317 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
7318 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
7319 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007320 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007321 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
7322 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
7323 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007324 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007325 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
7326 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
7327 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007328 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007329 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
7330 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
7331 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007332 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007333 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
7334 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
7335 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007336 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007337 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
7338 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
7339 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007340 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007341 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
7342 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
7343 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007344 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007345 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
7346 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
7347 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007348 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007349 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
7350 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
7351 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007352 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007353 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
7354 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
7355 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007356 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007357 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
7358 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
7359 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007360 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007361 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
7362 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
7363 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007364 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007365 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
7366 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
7367 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007368 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007369 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
7370 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
7371 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007372 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007373 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
7374 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
7375 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007376 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007377 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
7378 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
7379 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007380 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007381 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
7382 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
7383 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007384 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007385 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
7386 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
7387 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007388 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007389 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
7390 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
7391 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007392 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007393 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
7394 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
7395 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007396 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007397 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
7398 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
7399 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007400 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007401 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
7402 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
7403 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007404 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007405 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
7406 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
7407 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007408 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007409 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
7410 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
7411 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007412 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007413 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
7414 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
7415 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007416 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007417 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
7418 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
7419 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007420 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007421 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
7422 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
7423 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007424 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007425 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
7426 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
7427 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007428 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007429 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
7430 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
7431 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007432 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007433 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
7434 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
7435 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007436 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007437 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
7438 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
7439 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007440 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007441 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
7442 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
7443 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007444 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007445 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
7446 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
7447 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007448 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007449 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
7450 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
7451 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007452 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007453 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
7454 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
7455 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007456 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06007457 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
7458 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
7459 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
Linus Torvalds1da177e2005-04-16 15:20:36 -07007460};
7461
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007462static ushort _asc_mcode_size = sizeof(_asc_mcode_buf);
7463static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007464
7465#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007466static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = {
7467 INQUIRY,
7468 REQUEST_SENSE,
7469 READ_CAPACITY,
7470 READ_TOC,
7471 MODE_SELECT,
7472 MODE_SENSE,
7473 MODE_SELECT_10,
7474 MODE_SENSE_10,
7475 0xFF,
7476 0xFF,
7477 0xFF,
7478 0xFF,
7479 0xFF,
7480 0xFF,
7481 0xFF,
7482 0xFF
Linus Torvalds1da177e2005-04-16 15:20:36 -07007483};
7484
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007485static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007486{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007487 PortAddr iop_base;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007488 int sta;
7489 int n_q_required;
7490 int disable_syn_offset_one_fix;
7491 int i;
7492 ASC_PADDR addr;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007493 ushort sg_entry_cnt = 0;
7494 ushort sg_entry_cnt_minus_one = 0;
7495 uchar target_ix;
7496 uchar tid_no;
7497 uchar sdtr_data;
7498 uchar extra_bytes;
7499 uchar scsi_cmd;
7500 uchar disable_cmd;
7501 ASC_SG_HEAD *sg_head;
7502 ASC_DCNT data_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007503
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007504 iop_base = asc_dvc->iop_base;
7505 sg_head = scsiq->sg_head;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007506 if (asc_dvc->err_code != 0)
7507 return (ERR);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007508 scsiq->q1.q_no = 0;
7509 if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) {
7510 scsiq->q1.extra_bytes = 0;
7511 }
7512 sta = 0;
7513 target_ix = scsiq->q2.target_ix;
7514 tid_no = ASC_TIX_TO_TID(target_ix);
7515 n_q_required = 1;
7516 if (scsiq->cdbptr[0] == REQUEST_SENSE) {
7517 if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) {
7518 asc_dvc->sdtr_done &= ~scsiq->q1.target_id;
7519 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7520 AscMsgOutSDTR(asc_dvc,
7521 asc_dvc->
7522 sdtr_period_tbl[(sdtr_data >> 4) &
7523 (uchar)(asc_dvc->
7524 max_sdtr_index -
7525 1)],
7526 (uchar)(sdtr_data & (uchar)
7527 ASC_SYN_MAX_OFFSET));
7528 scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT);
7529 }
7530 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007531 if (asc_dvc->in_critical_cnt != 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007532 AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY);
7533 return (ERR);
7534 }
7535 asc_dvc->in_critical_cnt++;
7536 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
7537 if ((sg_entry_cnt = sg_head->entry_cnt) == 0) {
7538 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007539 return (ERR);
7540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007541#if !CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007542 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
7543 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007544 return (ERR);
7545 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007546#endif /* !CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007547 if (sg_entry_cnt == 1) {
7548 scsiq->q1.data_addr =
7549 (ADV_PADDR)sg_head->sg_list[0].addr;
7550 scsiq->q1.data_cnt =
7551 (ADV_DCNT)sg_head->sg_list[0].bytes;
7552 scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE);
7553 }
7554 sg_entry_cnt_minus_one = sg_entry_cnt - 1;
7555 }
7556 scsi_cmd = scsiq->cdbptr[0];
7557 disable_syn_offset_one_fix = FALSE;
7558 if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) &&
7559 !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) {
7560 if (scsiq->q1.cntl & QC_SG_HEAD) {
7561 data_cnt = 0;
7562 for (i = 0; i < sg_entry_cnt; i++) {
7563 data_cnt +=
7564 (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i].
7565 bytes);
7566 }
7567 } else {
7568 data_cnt = le32_to_cpu(scsiq->q1.data_cnt);
7569 }
7570 if (data_cnt != 0UL) {
7571 if (data_cnt < 512UL) {
7572 disable_syn_offset_one_fix = TRUE;
7573 } else {
7574 for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST;
7575 i++) {
7576 disable_cmd =
7577 _syn_offset_one_disable_cmd[i];
7578 if (disable_cmd == 0xFF) {
7579 break;
7580 }
7581 if (scsi_cmd == disable_cmd) {
7582 disable_syn_offset_one_fix =
7583 TRUE;
7584 break;
7585 }
7586 }
7587 }
7588 }
7589 }
7590 if (disable_syn_offset_one_fix) {
7591 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
7592 scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX |
7593 ASC_TAG_FLAG_DISABLE_DISCONNECT);
7594 } else {
7595 scsiq->q2.tag_code &= 0x27;
7596 }
7597 if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) {
7598 if (asc_dvc->bug_fix_cntl) {
7599 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
7600 if ((scsi_cmd == READ_6) ||
7601 (scsi_cmd == READ_10)) {
7602 addr =
7603 (ADV_PADDR)le32_to_cpu(sg_head->
7604 sg_list
7605 [sg_entry_cnt_minus_one].
7606 addr) +
7607 (ADV_DCNT)le32_to_cpu(sg_head->
7608 sg_list
7609 [sg_entry_cnt_minus_one].
7610 bytes);
7611 extra_bytes =
7612 (uchar)((ushort)addr & 0x0003);
7613 if ((extra_bytes != 0)
7614 &&
7615 ((scsiq->q2.
7616 tag_code &
7617 ASC_TAG_FLAG_EXTRA_BYTES)
7618 == 0)) {
7619 scsiq->q2.tag_code |=
7620 ASC_TAG_FLAG_EXTRA_BYTES;
7621 scsiq->q1.extra_bytes =
7622 extra_bytes;
7623 data_cnt =
7624 le32_to_cpu(sg_head->
7625 sg_list
7626 [sg_entry_cnt_minus_one].
7627 bytes);
7628 data_cnt -=
7629 (ASC_DCNT) extra_bytes;
7630 sg_head->
7631 sg_list
7632 [sg_entry_cnt_minus_one].
7633 bytes =
7634 cpu_to_le32(data_cnt);
7635 }
7636 }
7637 }
7638 }
7639 sg_head->entry_to_copy = sg_head->entry_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007640#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007641 /*
7642 * Set the sg_entry_cnt to the maximum possible. The rest of
7643 * the SG elements will be copied when the RISC completes the
7644 * SG elements that fit and halts.
7645 */
7646 if (sg_entry_cnt > ASC_MAX_SG_LIST) {
7647 sg_entry_cnt = ASC_MAX_SG_LIST;
7648 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007649#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007650 n_q_required = AscSgListToQueue(sg_entry_cnt);
7651 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >=
7652 (uint) n_q_required)
7653 || ((scsiq->q1.cntl & QC_URGENT) != 0)) {
7654 if ((sta =
7655 AscSendScsiQueue(asc_dvc, scsiq,
7656 n_q_required)) == 1) {
7657 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007658 return (sta);
7659 }
7660 }
7661 } else {
7662 if (asc_dvc->bug_fix_cntl) {
7663 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) {
7664 if ((scsi_cmd == READ_6) ||
7665 (scsi_cmd == READ_10)) {
7666 addr =
7667 le32_to_cpu(scsiq->q1.data_addr) +
7668 le32_to_cpu(scsiq->q1.data_cnt);
7669 extra_bytes =
7670 (uchar)((ushort)addr & 0x0003);
7671 if ((extra_bytes != 0)
7672 &&
7673 ((scsiq->q2.
7674 tag_code &
7675 ASC_TAG_FLAG_EXTRA_BYTES)
7676 == 0)) {
7677 data_cnt =
7678 le32_to_cpu(scsiq->q1.
7679 data_cnt);
7680 if (((ushort)data_cnt & 0x01FF)
7681 == 0) {
7682 scsiq->q2.tag_code |=
7683 ASC_TAG_FLAG_EXTRA_BYTES;
7684 data_cnt -= (ASC_DCNT)
7685 extra_bytes;
7686 scsiq->q1.data_cnt =
7687 cpu_to_le32
7688 (data_cnt);
7689 scsiq->q1.extra_bytes =
7690 extra_bytes;
7691 }
7692 }
7693 }
7694 }
7695 }
7696 n_q_required = 1;
7697 if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) ||
7698 ((scsiq->q1.cntl & QC_URGENT) != 0)) {
7699 if ((sta = AscSendScsiQueue(asc_dvc, scsiq,
7700 n_q_required)) == 1) {
7701 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007702 return (sta);
7703 }
7704 }
7705 }
7706 asc_dvc->in_critical_cnt--;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007707 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007708}
7709
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007710static int
7711AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007712{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007713 PortAddr iop_base;
7714 uchar free_q_head;
7715 uchar next_qp;
7716 uchar tid_no;
7717 uchar target_ix;
7718 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007719
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007720 iop_base = asc_dvc->iop_base;
7721 target_ix = scsiq->q2.target_ix;
7722 tid_no = ASC_TIX_TO_TID(target_ix);
7723 sta = 0;
7724 free_q_head = (uchar)AscGetVarFreeQHead(iop_base);
7725 if (n_q_required > 1) {
7726 if ((next_qp = AscAllocMultipleFreeQueue(iop_base,
7727 free_q_head, (uchar)
7728 (n_q_required)))
7729 != (uchar)ASC_QLINK_END) {
7730 asc_dvc->last_q_shortage = 0;
7731 scsiq->sg_head->queue_cnt = n_q_required - 1;
7732 scsiq->q1.q_no = free_q_head;
7733 if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq,
7734 free_q_head)) == 1) {
7735 AscPutVarFreeQHead(iop_base, next_qp);
7736 asc_dvc->cur_total_qng += (uchar)(n_q_required);
7737 asc_dvc->cur_dvc_qng[tid_no]++;
7738 }
7739 return (sta);
7740 }
7741 } else if (n_q_required == 1) {
7742 if ((next_qp = AscAllocFreeQueue(iop_base,
7743 free_q_head)) !=
7744 ASC_QLINK_END) {
7745 scsiq->q1.q_no = free_q_head;
7746 if ((sta = AscPutReadyQueue(asc_dvc, scsiq,
7747 free_q_head)) == 1) {
7748 AscPutVarFreeQHead(iop_base, next_qp);
7749 asc_dvc->cur_total_qng++;
7750 asc_dvc->cur_dvc_qng[tid_no]++;
7751 }
7752 return (sta);
7753 }
7754 }
7755 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007756}
7757
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007758static int AscSgListToQueue(int sg_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007759{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007760 int n_sg_list_qs;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007761
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007762 n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q);
7763 if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0)
7764 n_sg_list_qs++;
7765 return (n_sg_list_qs + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007766}
7767
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007768static uint
7769AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007770{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007771 uint cur_used_qs;
7772 uint cur_free_qs;
7773 ASC_SCSI_BIT_ID_TYPE target_id;
7774 uchar tid_no;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007775
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007776 target_id = ASC_TIX_TO_TARGET_ID(target_ix);
7777 tid_no = ASC_TIX_TO_TID(target_ix);
7778 if ((asc_dvc->unit_not_ready & target_id) ||
7779 (asc_dvc->queue_full_or_busy & target_id)) {
7780 return (0);
7781 }
7782 if (n_qs == 1) {
7783 cur_used_qs = (uint) asc_dvc->cur_total_qng +
7784 (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q;
7785 } else {
7786 cur_used_qs = (uint) asc_dvc->cur_total_qng +
7787 (uint) ASC_MIN_FREE_Q;
7788 }
7789 if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) {
7790 cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs;
7791 if (asc_dvc->cur_dvc_qng[tid_no] >=
7792 asc_dvc->max_dvc_qng[tid_no]) {
7793 return (0);
7794 }
7795 return (cur_free_qs);
7796 }
7797 if (n_qs > 1) {
7798 if ((n_qs > asc_dvc->last_q_shortage)
7799 && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) {
7800 asc_dvc->last_q_shortage = n_qs;
7801 }
7802 }
7803 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007804}
7805
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007806static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007807{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007808 ushort q_addr;
7809 uchar tid_no;
7810 uchar sdtr_data;
7811 uchar syn_period_ix;
7812 uchar syn_offset;
7813 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007814
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007815 iop_base = asc_dvc->iop_base;
7816 if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) &&
7817 ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) {
7818 tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix);
7819 sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no);
7820 syn_period_ix =
7821 (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1);
7822 syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET;
7823 AscMsgOutSDTR(asc_dvc,
7824 asc_dvc->sdtr_period_tbl[syn_period_ix],
7825 syn_offset);
7826 scsiq->q1.cntl |= QC_MSG_OUT;
7827 }
7828 q_addr = ASC_QNO_TO_QADDR(q_no);
7829 if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) {
7830 scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG;
7831 }
7832 scsiq->q1.status = QS_FREE;
7833 AscMemWordCopyPtrToLram(iop_base,
7834 q_addr + ASC_SCSIQ_CDB_BEG,
7835 (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007836
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007837 DvcPutScsiQ(iop_base,
7838 q_addr + ASC_SCSIQ_CPY_BEG,
7839 (uchar *)&scsiq->q1.cntl,
7840 ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1);
7841 AscWriteLramWord(iop_base,
7842 (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS),
7843 (ushort)(((ushort)scsiq->q1.
7844 q_no << 8) | (ushort)QS_READY));
7845 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007846}
7847
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007848static int
7849AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007850{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007851 int sta;
7852 int i;
7853 ASC_SG_HEAD *sg_head;
7854 ASC_SG_LIST_Q scsi_sg_q;
7855 ASC_DCNT saved_data_addr;
7856 ASC_DCNT saved_data_cnt;
7857 PortAddr iop_base;
7858 ushort sg_list_dwords;
7859 ushort sg_index;
7860 ushort sg_entry_cnt;
7861 ushort q_addr;
7862 uchar next_qp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007863
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007864 iop_base = asc_dvc->iop_base;
7865 sg_head = scsiq->sg_head;
7866 saved_data_addr = scsiq->q1.data_addr;
7867 saved_data_cnt = scsiq->q1.data_cnt;
7868 scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr;
7869 scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007870#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007871 /*
7872 * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST
7873 * then not all SG elements will fit in the allocated queues.
7874 * The rest of the SG elements will be copied when the RISC
7875 * completes the SG elements that fit and halts.
7876 */
7877 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
7878 /*
7879 * Set sg_entry_cnt to be the number of SG elements that
7880 * will fit in the allocated SG queues. It is minus 1, because
7881 * the first SG element is handled above. ASC_MAX_SG_LIST is
7882 * already inflated by 1 to account for this. For example it
7883 * may be 50 which is 1 + 7 queues * 7 SG elements.
7884 */
7885 sg_entry_cnt = ASC_MAX_SG_LIST - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007886
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007887 /*
7888 * Keep track of remaining number of SG elements that will
7889 * need to be handled from a_isr.c.
7890 */
7891 scsiq->remain_sg_entry_cnt =
7892 sg_head->entry_cnt - ASC_MAX_SG_LIST;
7893 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007894#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007895 /*
7896 * Set sg_entry_cnt to be the number of SG elements that
7897 * will fit in the allocated SG queues. It is minus 1, because
7898 * the first SG element is handled above.
7899 */
7900 sg_entry_cnt = sg_head->entry_cnt - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007901#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007903#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007904 if (sg_entry_cnt != 0) {
7905 scsiq->q1.cntl |= QC_SG_HEAD;
7906 q_addr = ASC_QNO_TO_QADDR(q_no);
7907 sg_index = 1;
7908 scsiq->q1.sg_queue_cnt = sg_head->queue_cnt;
7909 scsi_sg_q.sg_head_qp = q_no;
7910 scsi_sg_q.cntl = QCSG_SG_XFER_LIST;
7911 for (i = 0; i < sg_head->queue_cnt; i++) {
7912 scsi_sg_q.seq_no = i + 1;
7913 if (sg_entry_cnt > ASC_SG_LIST_PER_Q) {
7914 sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2);
7915 sg_entry_cnt -= ASC_SG_LIST_PER_Q;
7916 if (i == 0) {
7917 scsi_sg_q.sg_list_cnt =
7918 ASC_SG_LIST_PER_Q;
7919 scsi_sg_q.sg_cur_list_cnt =
7920 ASC_SG_LIST_PER_Q;
7921 } else {
7922 scsi_sg_q.sg_list_cnt =
7923 ASC_SG_LIST_PER_Q - 1;
7924 scsi_sg_q.sg_cur_list_cnt =
7925 ASC_SG_LIST_PER_Q - 1;
7926 }
7927 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007928#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007929 /*
7930 * This is the last SG queue in the list of
7931 * allocated SG queues. If there are more
7932 * SG elements than will fit in the allocated
7933 * queues, then set the QCSG_SG_XFER_MORE flag.
7934 */
7935 if (sg_head->entry_cnt > ASC_MAX_SG_LIST) {
7936 scsi_sg_q.cntl |= QCSG_SG_XFER_MORE;
7937 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007938#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007939 scsi_sg_q.cntl |= QCSG_SG_XFER_END;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007940#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007941 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007942#endif /* CC_VERY_LONG_SG_LIST */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007943 sg_list_dwords = sg_entry_cnt << 1;
7944 if (i == 0) {
7945 scsi_sg_q.sg_list_cnt = sg_entry_cnt;
7946 scsi_sg_q.sg_cur_list_cnt =
7947 sg_entry_cnt;
7948 } else {
7949 scsi_sg_q.sg_list_cnt =
7950 sg_entry_cnt - 1;
7951 scsi_sg_q.sg_cur_list_cnt =
7952 sg_entry_cnt - 1;
7953 }
7954 sg_entry_cnt = 0;
7955 }
7956 next_qp = AscReadLramByte(iop_base,
7957 (ushort)(q_addr +
7958 ASC_SCSIQ_B_FWD));
7959 scsi_sg_q.q_no = next_qp;
7960 q_addr = ASC_QNO_TO_QADDR(next_qp);
7961 AscMemWordCopyPtrToLram(iop_base,
7962 q_addr + ASC_SCSIQ_SGHD_CPY_BEG,
7963 (uchar *)&scsi_sg_q,
7964 sizeof(ASC_SG_LIST_Q) >> 1);
7965 AscMemDWordCopyPtrToLram(iop_base,
7966 q_addr + ASC_SGQ_LIST_BEG,
7967 (uchar *)&sg_head->
7968 sg_list[sg_index],
7969 sg_list_dwords);
7970 sg_index += ASC_SG_LIST_PER_Q;
7971 scsiq->next_sg_index = sg_index;
7972 }
7973 } else {
7974 scsiq->q1.cntl &= ~QC_SG_HEAD;
7975 }
7976 sta = AscPutReadyQueue(asc_dvc, scsiq, q_no);
7977 scsiq->q1.data_addr = saved_data_addr;
7978 scsiq->q1.data_cnt = saved_data_cnt;
7979 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007980}
7981
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007982static int
7983AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007984{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007985 int sta = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007986
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007987 if (AscHostReqRiscHalt(iop_base)) {
7988 sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
7989 AscStartChip(iop_base);
7990 return (sta);
7991 }
7992 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007993}
7994
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007995static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007996{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04007997 ASC_SCSI_BIT_ID_TYPE org_id;
7998 int i;
7999 int sta = TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008000
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008001 AscSetBank(iop_base, 1);
8002 org_id = AscReadChipDvcID(iop_base);
8003 for (i = 0; i <= ASC_MAX_TID; i++) {
8004 if (org_id == (0x01 << i))
8005 break;
8006 }
8007 org_id = (ASC_SCSI_BIT_ID_TYPE) i;
8008 AscWriteChipDvcID(iop_base, id);
8009 if (AscReadChipDvcID(iop_base) == (0x01 << id)) {
8010 AscSetBank(iop_base, 0);
8011 AscSetChipSyn(iop_base, sdtr_data);
8012 if (AscGetChipSyn(iop_base) != sdtr_data) {
8013 sta = FALSE;
8014 }
8015 } else {
8016 sta = FALSE;
8017 }
8018 AscSetBank(iop_base, 1);
8019 AscWriteChipDvcID(iop_base, org_id);
8020 AscSetBank(iop_base, 0);
8021 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008022}
8023
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008024static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008025{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008026 uchar i;
8027 ushort s_addr;
8028 PortAddr iop_base;
8029 ushort warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008030
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008031 iop_base = asc_dvc->iop_base;
8032 warn_code = 0;
8033 AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0,
8034 (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) *
8035 64) >> 1)
8036 );
8037 i = ASC_MIN_ACTIVE_QNO;
8038 s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE;
8039 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8040 (uchar)(i + 1));
8041 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8042 (uchar)(asc_dvc->max_total_qng));
8043 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8044 (uchar)i);
8045 i++;
8046 s_addr += ASC_QBLK_SIZE;
8047 for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) {
8048 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8049 (uchar)(i + 1));
8050 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8051 (uchar)(i - 1));
8052 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8053 (uchar)i);
8054 }
8055 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD),
8056 (uchar)ASC_QLINK_END);
8057 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD),
8058 (uchar)(asc_dvc->max_total_qng - 1));
8059 AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO),
8060 (uchar)asc_dvc->max_total_qng);
8061 i++;
8062 s_addr += ASC_QBLK_SIZE;
8063 for (; i <= (uchar)(asc_dvc->max_total_qng + 3);
8064 i++, s_addr += ASC_QBLK_SIZE) {
8065 AscWriteLramByte(iop_base,
8066 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i);
8067 AscWriteLramByte(iop_base,
8068 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i);
8069 AscWriteLramByte(iop_base,
8070 (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i);
8071 }
8072 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008073}
8074
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008075static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008076{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008077 PortAddr iop_base;
8078 int i;
8079 ushort lram_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008080
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008081 iop_base = asc_dvc->iop_base;
8082 AscPutRiscVarFreeQHead(iop_base, 1);
8083 AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8084 AscPutVarFreeQHead(iop_base, 1);
8085 AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng);
8086 AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B,
8087 (uchar)((int)asc_dvc->max_total_qng + 1));
8088 AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B,
8089 (uchar)((int)asc_dvc->max_total_qng + 2));
8090 AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B,
8091 asc_dvc->max_total_qng);
8092 AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0);
8093 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
8094 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0);
8095 AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0);
8096 AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0);
8097 AscPutQDoneInProgress(iop_base, 0);
8098 lram_addr = ASC_QADR_BEG;
8099 for (i = 0; i < 32; i++, lram_addr += 2) {
8100 AscWriteLramWord(iop_base, lram_addr, 0);
8101 }
8102 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008103}
8104
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008105static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008106{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008107 if (asc_dvc->err_code == 0) {
8108 asc_dvc->err_code = err_code;
8109 AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W,
8110 err_code);
8111 }
8112 return (err_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008113}
8114
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008115static uchar
8116AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008117{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008118 EXT_MSG sdtr_buf;
8119 uchar sdtr_period_index;
8120 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008121
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008122 iop_base = asc_dvc->iop_base;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008123 sdtr_buf.msg_type = EXTENDED_MESSAGE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008124 sdtr_buf.msg_len = MS_SDTR_LEN;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04008125 sdtr_buf.msg_req = EXTENDED_SDTR;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008126 sdtr_buf.xfer_period = sdtr_period;
8127 sdtr_offset &= ASC_SYN_MAX_OFFSET;
8128 sdtr_buf.req_ack_offset = sdtr_offset;
8129 if ((sdtr_period_index =
8130 AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <=
8131 asc_dvc->max_sdtr_index) {
8132 AscMemWordCopyPtrToLram(iop_base,
8133 ASCV_MSGOUT_BEG,
8134 (uchar *)&sdtr_buf,
8135 sizeof(EXT_MSG) >> 1);
8136 return ((sdtr_period_index << 4) | sdtr_offset);
8137 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07008138
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008139 sdtr_buf.req_ack_offset = 0;
8140 AscMemWordCopyPtrToLram(iop_base,
8141 ASCV_MSGOUT_BEG,
8142 (uchar *)&sdtr_buf,
8143 sizeof(EXT_MSG) >> 1);
8144 return (0);
8145 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008146}
8147
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008148static uchar
8149AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008150{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008151 uchar byte;
8152 uchar sdtr_period_ix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008153
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008154 sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period);
8155 if ((sdtr_period_ix > asc_dvc->max_sdtr_index)
8156 ) {
8157 return (0xFF);
8158 }
8159 byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET);
8160 return (byte);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008161}
8162
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008163static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008164{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008165 AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data);
8166 AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data);
8167 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008168}
8169
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008170static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008171{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008172 uchar *period_table;
8173 int max_index;
8174 int min_index;
8175 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008176
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008177 period_table = asc_dvc->sdtr_period_tbl;
8178 max_index = (int)asc_dvc->max_sdtr_index;
8179 min_index = (int)asc_dvc->host_init_sdtr_index;
8180 if ((syn_time <= period_table[max_index])) {
8181 for (i = min_index; i < (max_index - 1); i++) {
8182 if (syn_time <= period_table[i]) {
8183 return ((uchar)i);
8184 }
8185 }
8186 return ((uchar)max_index);
8187 } else {
8188 return ((uchar)(max_index + 1));
8189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008190}
8191
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008192static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008193{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008194 ushort q_addr;
8195 uchar next_qp;
8196 uchar q_status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008197
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008198 q_addr = ASC_QNO_TO_QADDR(free_q_head);
8199 q_status = (uchar)AscReadLramByte(iop_base,
8200 (ushort)(q_addr +
8201 ASC_SCSIQ_B_STATUS));
8202 next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD));
8203 if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) {
8204 return (next_qp);
8205 }
8206 return (ASC_QLINK_END);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008207}
8208
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008209static uchar
8210AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008211{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008212 uchar i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008213
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008214 for (i = 0; i < n_free_q; i++) {
8215 if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head))
8216 == ASC_QLINK_END) {
8217 return (ASC_QLINK_END);
8218 }
8219 }
8220 return (free_q_head);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008221}
8222
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008223static int AscHostReqRiscHalt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008224{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008225 int count = 0;
8226 int sta = 0;
8227 uchar saved_stop_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008228
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008229 if (AscIsChipHalted(iop_base))
8230 return (1);
8231 saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B);
8232 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8233 ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP);
8234 do {
8235 if (AscIsChipHalted(iop_base)) {
8236 sta = 1;
8237 break;
8238 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06008239 mdelay(100);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008240 } while (count++ < 20);
8241 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code);
8242 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008243}
8244
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008245static int AscStopQueueExe(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008246{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008247 int count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008248
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008249 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) {
8250 AscWriteLramByte(iop_base, ASCV_STOP_CODE_B,
8251 ASC_STOP_REQ_RISC_STOP);
8252 do {
8253 if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) &
8254 ASC_STOP_ACK_RISC_STOP) {
8255 return (1);
8256 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06008257 mdelay(100);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008258 } while (count++ < 20);
8259 }
8260 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008261}
8262
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008263static int AscStartChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008264{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008265 AscSetChipControl(iop_base, 0);
8266 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8267 return (0);
8268 }
8269 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008270}
8271
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008272static int AscStopChip(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008273{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008274 uchar cc_val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008275
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008276 cc_val =
8277 AscGetChipControl(iop_base) &
8278 (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG));
8279 AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT));
8280 AscSetChipIH(iop_base, INS_HALT);
8281 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8282 if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) {
8283 return (0);
8284 }
8285 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008286}
8287
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008288static int AscIsChipHalted(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008289{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008290 if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) {
8291 if ((AscGetChipControl(iop_base) & CC_HALT) != 0) {
8292 return (1);
8293 }
8294 }
8295 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008296}
8297
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008298static void AscSetChipIH(PortAddr iop_base, ushort ins_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008299{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008300 AscSetBank(iop_base, 1);
8301 AscWriteChipIH(iop_base, ins_code);
8302 AscSetBank(iop_base, 0);
8303 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008304}
8305
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008306static void AscAckInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008307{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008308 uchar host_flag;
8309 uchar risc_flag;
8310 ushort loop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008311
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008312 loop = 0;
8313 do {
8314 risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B);
8315 if (loop++ > 0x7FFF) {
8316 break;
8317 }
8318 } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0);
8319 host_flag =
8320 AscReadLramByte(iop_base,
8321 ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT);
8322 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B,
8323 (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT));
8324 AscSetChipStatus(iop_base, CIW_INT_ACK);
8325 loop = 0;
8326 while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) {
8327 AscSetChipStatus(iop_base, CIW_INT_ACK);
8328 if (loop++ > 3) {
8329 break;
8330 }
8331 }
8332 AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag);
8333 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008334}
8335
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008336static void AscDisableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008337{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008338 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008339
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008340 cfg = AscGetChipCfgLsw(iop_base);
8341 AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON));
8342 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008343}
8344
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008345static void AscEnableInterrupt(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008346{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008347 ushort cfg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008348
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008349 cfg = AscGetChipCfgLsw(iop_base);
8350 AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON);
8351 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008352}
8353
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008354static void AscSetBank(PortAddr iop_base, uchar bank)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008355{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008356 uchar val;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008357
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008358 val = AscGetChipControl(iop_base) &
8359 (~
8360 (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET |
8361 CC_CHIP_RESET));
8362 if (bank == 1) {
8363 val |= CC_BANK_ONE;
8364 } else if (bank == 2) {
8365 val |= CC_DIAG | CC_BANK_ONE;
8366 } else {
8367 val &= ~CC_BANK_ONE;
8368 }
8369 AscSetChipControl(iop_base, val);
8370 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008371}
8372
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008373static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008374{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008375 PortAddr iop_base;
8376 int i = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008377
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008378 iop_base = asc_dvc->iop_base;
8379 while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE)
8380 && (i-- > 0)) {
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06008381 mdelay(100);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008382 }
8383 AscStopChip(iop_base);
8384 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06008385 udelay(60);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008386 AscSetChipIH(iop_base, INS_RFLAG_WTM);
8387 AscSetChipIH(iop_base, INS_HALT);
8388 AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT);
8389 AscSetChipControl(iop_base, CC_HALT);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06008390 mdelay(200);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008391 AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT);
8392 AscSetChipStatus(iop_base, 0);
8393 return (AscIsChipHalted(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008394}
8395
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008396static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008397{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008398 if (bus_type & ASC_IS_ISA)
8399 return (ASC_MAX_ISA_DMA_COUNT);
8400 else if (bus_type & (ASC_IS_EISA | ASC_IS_VL))
8401 return (ASC_MAX_VL_DMA_COUNT);
8402 return (ASC_MAX_PCI_DMA_COUNT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008403}
8404
8405#ifdef CONFIG_ISA
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008406static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008407{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008408 ushort channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008409
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008410 channel = AscGetChipCfgLsw(iop_base) & 0x0003;
8411 if (channel == 0x03)
8412 return (0);
8413 else if (channel == 0x00)
8414 return (7);
8415 return (channel + 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008416}
8417
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008418static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008419{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008420 ushort cfg_lsw;
8421 uchar value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008422
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008423 if ((dma_channel >= 5) && (dma_channel <= 7)) {
8424 if (dma_channel == 7)
8425 value = 0x00;
8426 else
8427 value = dma_channel - 4;
8428 cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC;
8429 cfg_lsw |= value;
8430 AscSetChipCfgLsw(iop_base, cfg_lsw);
8431 return (AscGetIsaDmaChannel(iop_base));
8432 }
8433 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008434}
8435
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008436static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008437{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008438 speed_value &= 0x07;
8439 AscSetBank(iop_base, 1);
8440 AscWriteChipDmaSpeed(iop_base, speed_value);
8441 AscSetBank(iop_base, 0);
8442 return (AscGetIsaDmaSpeed(iop_base));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008443}
8444
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008445static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008446{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008447 uchar speed_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008448
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008449 AscSetBank(iop_base, 1);
8450 speed_value = AscReadChipDmaSpeed(iop_base);
8451 speed_value &= 0x07;
8452 AscSetBank(iop_base, 0);
8453 return (speed_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008454}
8455#endif /* CONFIG_ISA */
8456
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008457static int __devinit AscInitGetConfig(asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008458{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008459 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -06008460 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008461
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008462 asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG;
Matthew Wilcox9649af32007-07-26 21:51:47 -06008463 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008464 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008465
Matthew Wilcox9649af32007-07-26 21:51:47 -06008466 if (AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008467 warn_code |= AscInitAscDvcVar(asc_dvc);
8468 warn_code |= AscInitFromEEP(asc_dvc);
8469 asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG;
Matthew Wilcoxecec1942007-07-30 08:08:22 -06008470 if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT)
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008471 asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008472 } else {
8473 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
8474 }
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008475
8476 switch (warn_code) {
8477 case 0: /* No error */
8478 break;
8479 case ASC_WARN_IO_PORT_ROTATE:
8480 ASC_PRINT1("AscInitGetConfig: board %d: I/O port address "
8481 "modified\n", boardp->id);
8482 break;
8483 case ASC_WARN_AUTO_CONFIG:
8484 ASC_PRINT1("AscInitGetConfig: board %d: I/O port increment "
8485 "switch enabled\n", boardp->id);
8486 break;
8487 case ASC_WARN_EEPROM_CHKSUM:
8488 ASC_PRINT1("AscInitGetConfig: board %d: EEPROM checksum "
8489 "error\n", boardp->id);
8490 break;
8491 case ASC_WARN_IRQ_MODIFIED:
8492 ASC_PRINT1("AscInitGetConfig: board %d: IRQ modified\n",
8493 boardp->id);
8494 break;
8495 case ASC_WARN_CMD_QNG_CONFLICT:
8496 ASC_PRINT1("AscInitGetConfig: board %d: tag queuing enabled "
8497 "w/o disconnects\n", boardp->id);
8498 break;
8499 default:
8500 ASC_PRINT2("AscInitGetConfig: board %d: unknown warning: "
8501 "0x%x\n", boardp->id, warn_code);
8502 break;
8503 }
8504
8505 if (asc_dvc->err_code != 0) {
8506 ASC_PRINT3("AscInitGetConfig: board %d error: init_state 0x%x, "
8507 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
8508 asc_dvc->err_code);
8509 }
8510
8511 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008512}
8513
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008514static int __devinit AscInitSetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008515{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008516 ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008517 PortAddr iop_base = asc_dvc->iop_base;
8518 unsigned short cfg_msw;
8519 unsigned short warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008520
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008521 asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG;
8522 if (asc_dvc->err_code != 0)
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008523 return asc_dvc->err_code;
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008524 if (!AscFindSignature(asc_dvc->iop_base)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008525 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008526 return asc_dvc->err_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008528
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008529 cfg_msw = AscGetChipCfgMsw(iop_base);
8530 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008531 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008532 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
8533 AscSetChipCfgMsw(iop_base, cfg_msw);
8534 }
8535 if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) !=
8536 asc_dvc->cfg->cmd_qng_enabled) {
8537 asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled;
8538 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
8539 }
8540 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
8541 warn_code |= ASC_WARN_AUTO_CONFIG;
8542 }
8543 if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) {
8544 if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type)
8545 != asc_dvc->irq_no) {
8546 asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO;
8547 }
8548 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06008549#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008550 if (asc_dvc->bus_type & ASC_IS_PCI) {
8551 cfg_msw &= 0xFFC0;
8552 AscSetChipCfgMsw(iop_base, cfg_msw);
8553 if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) {
8554 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -06008555 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
8556 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008557 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB;
8558 asc_dvc->bug_fix_cntl |=
8559 ASC_BUG_FIX_ASYN_USE_SYN;
8560 }
8561 }
Matthew Wilcox9649af32007-07-26 21:51:47 -06008562 } else
8563#endif /* CONFIG_PCI */
8564 if (asc_dvc->bus_type == ASC_IS_ISAPNP) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008565 if (AscGetChipVersion(iop_base, asc_dvc->bus_type)
8566 == ASC_CHIP_VER_ASYN_BUG) {
8567 asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN;
8568 }
8569 }
8570 if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) !=
8571 asc_dvc->cfg->chip_scsi_id) {
8572 asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID;
8573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008574#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008575 if (asc_dvc->bus_type & ASC_IS_ISA) {
8576 AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel);
8577 AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed);
8578 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008579#endif /* CONFIG_ISA */
Matthew Wilcox394dbf32007-07-26 11:56:40 -04008580
8581 asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG;
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008582
8583 switch (warn_code) {
8584 case 0: /* No error. */
8585 break;
8586 case ASC_WARN_IO_PORT_ROTATE:
8587 ASC_PRINT1("AscInitSetConfig: board %d: I/O port address "
8588 "modified\n", boardp->id);
8589 break;
8590 case ASC_WARN_AUTO_CONFIG:
8591 ASC_PRINT1("AscInitSetConfig: board %d: I/O port increment "
8592 "switch enabled\n", boardp->id);
8593 break;
8594 case ASC_WARN_EEPROM_CHKSUM:
8595 ASC_PRINT1("AscInitSetConfig: board %d: EEPROM checksum "
8596 "error\n", boardp->id);
8597 break;
8598 case ASC_WARN_IRQ_MODIFIED:
8599 ASC_PRINT1("AscInitSetConfig: board %d: IRQ modified\n",
8600 boardp->id);
8601 break;
8602 case ASC_WARN_CMD_QNG_CONFLICT:
8603 ASC_PRINT1("AscInitSetConfig: board %d: tag queuing w/o "
8604 "disconnects\n",
8605 boardp->id);
8606 break;
8607 default:
8608 ASC_PRINT2("AscInitSetConfig: board %d: unknown warning: "
8609 "0x%x\n", boardp->id, warn_code);
8610 break;
8611 }
8612
8613 if (asc_dvc->err_code != 0) {
8614 ASC_PRINT3("AscInitSetConfig: board %d error: init_state 0x%x, "
8615 "err_code 0x%x\n", boardp->id, asc_dvc->init_state,
8616 asc_dvc->err_code);
8617 }
8618
8619 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008620}
8621
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008622static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008623{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008624 ushort warn_code;
8625 PortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008626
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008627 iop_base = asc_dvc->iop_base;
8628 warn_code = 0;
8629 if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) &&
8630 !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) {
8631 AscResetChipAndScsiBus(asc_dvc);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06008632 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008633 }
8634 asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC;
8635 if (asc_dvc->err_code != 0)
8636 return (UW_ERR);
8637 if (!AscFindSignature(asc_dvc->iop_base)) {
8638 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
8639 return (warn_code);
8640 }
8641 AscDisableInterrupt(iop_base);
8642 warn_code |= AscInitLram(asc_dvc);
8643 if (asc_dvc->err_code != 0)
8644 return (UW_ERR);
8645 ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n",
8646 (ulong)_asc_mcode_chksum);
8647 if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
8648 _asc_mcode_size) != _asc_mcode_chksum) {
8649 asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
8650 return (warn_code);
8651 }
8652 warn_code |= AscInitMicroCodeVar(asc_dvc);
8653 asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
8654 AscEnableInterrupt(iop_base);
8655 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008656}
8657
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008658static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008659{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008660 int i;
8661 PortAddr iop_base;
8662 ushort warn_code;
8663 uchar chip_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008664
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008665 iop_base = asc_dvc->iop_base;
8666 warn_code = 0;
8667 asc_dvc->err_code = 0;
8668 if ((asc_dvc->bus_type &
8669 (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) {
8670 asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE;
8671 }
8672 AscSetChipControl(iop_base, CC_HALT);
8673 AscSetChipStatus(iop_base, 0);
8674 asc_dvc->bug_fix_cntl = 0;
8675 asc_dvc->pci_fix_asyn_xfer = 0;
8676 asc_dvc->pci_fix_asyn_xfer_always = 0;
8677 /* asc_dvc->init_state initalized in AscInitGetConfig(). */
8678 asc_dvc->sdtr_done = 0;
8679 asc_dvc->cur_total_qng = 0;
8680 asc_dvc->is_in_int = 0;
8681 asc_dvc->in_critical_cnt = 0;
8682 asc_dvc->last_q_shortage = 0;
8683 asc_dvc->use_tagged_qng = 0;
8684 asc_dvc->no_scam = 0;
8685 asc_dvc->unit_not_ready = 0;
8686 asc_dvc->queue_full_or_busy = 0;
8687 asc_dvc->redo_scam = 0;
8688 asc_dvc->res2 = 0;
8689 asc_dvc->host_init_sdtr_index = 0;
8690 asc_dvc->cfg->can_tagged_qng = 0;
8691 asc_dvc->cfg->cmd_qng_enabled = 0;
8692 asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
8693 asc_dvc->init_sdtr = 0;
8694 asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
8695 asc_dvc->scsi_reset_wait = 3;
8696 asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
8697 asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
8698 asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
8699 asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
8700 asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
8701 asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
8702 asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
8703 ASC_LIB_VERSION_MINOR;
8704 chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type);
8705 asc_dvc->cfg->chip_version = chip_version;
8706 asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0;
8707 asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1;
8708 asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2;
8709 asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3;
8710 asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4;
8711 asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5;
8712 asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6;
8713 asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7;
8714 asc_dvc->max_sdtr_index = 7;
8715 if ((asc_dvc->bus_type & ASC_IS_PCI) &&
8716 (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) {
8717 asc_dvc->bus_type = ASC_IS_PCI_ULTRA;
8718 asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0;
8719 asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1;
8720 asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2;
8721 asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3;
8722 asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4;
8723 asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5;
8724 asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6;
8725 asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7;
8726 asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8;
8727 asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9;
8728 asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10;
8729 asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11;
8730 asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12;
8731 asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13;
8732 asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14;
8733 asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15;
8734 asc_dvc->max_sdtr_index = 15;
8735 if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) {
8736 AscSetExtraControl(iop_base,
8737 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
8738 } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) {
8739 AscSetExtraControl(iop_base,
8740 (SEC_ACTIVE_NEGATE |
8741 SEC_ENABLE_FILTER));
8742 }
8743 }
8744 if (asc_dvc->bus_type == ASC_IS_PCI) {
8745 AscSetExtraControl(iop_base,
8746 (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE));
8747 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008748
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008749 asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008750#ifdef CONFIG_ISA
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008751 if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) {
Matthew Wilcox59fcf842007-07-26 11:54:15 -04008752 if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) {
8753 AscSetChipIFC(iop_base, IFC_INIT_DEFAULT);
8754 asc_dvc->bus_type = ASC_IS_ISAPNP;
8755 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008756 asc_dvc->cfg->isa_dma_channel =
8757 (uchar)AscGetIsaDmaChannel(iop_base);
8758 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008759#endif /* CONFIG_ISA */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008760 for (i = 0; i <= ASC_MAX_TID; i++) {
8761 asc_dvc->cur_dvc_qng[i] = 0;
8762 asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG;
8763 asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *)0L;
8764 asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L;
8765 asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG;
8766 }
8767 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008768}
8769
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008770static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008771{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008772 ASCEEP_CONFIG eep_config_buf;
8773 ASCEEP_CONFIG *eep_config;
8774 PortAddr iop_base;
8775 ushort chksum;
8776 ushort warn_code;
8777 ushort cfg_msw, cfg_lsw;
8778 int i;
8779 int write_eep = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008780
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008781 iop_base = asc_dvc->iop_base;
8782 warn_code = 0;
8783 AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE);
8784 AscStopQueueExe(iop_base);
8785 if ((AscStopChip(iop_base) == FALSE) ||
8786 (AscGetChipScsiCtrl(iop_base) != 0)) {
8787 asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE;
8788 AscResetChipAndScsiBus(asc_dvc);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06008789 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008790 }
8791 if (AscIsChipHalted(iop_base) == FALSE) {
8792 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
8793 return (warn_code);
8794 }
8795 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
8796 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
8797 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
8798 return (warn_code);
8799 }
8800 eep_config = (ASCEEP_CONFIG *)&eep_config_buf;
8801 cfg_msw = AscGetChipCfgMsw(iop_base);
8802 cfg_lsw = AscGetChipCfgLsw(iop_base);
8803 if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -06008804 cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008805 warn_code |= ASC_WARN_CFG_MSW_RECOVER;
8806 AscSetChipCfgMsw(iop_base, cfg_msw);
8807 }
8808 chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type);
8809 ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum);
8810 if (chksum == 0) {
8811 chksum = 0xaa55;
8812 }
8813 if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) {
8814 warn_code |= ASC_WARN_AUTO_CONFIG;
8815 if (asc_dvc->cfg->chip_version == 3) {
8816 if (eep_config->cfg_lsw != cfg_lsw) {
8817 warn_code |= ASC_WARN_EEPROM_RECOVER;
8818 eep_config->cfg_lsw =
8819 AscGetChipCfgLsw(iop_base);
8820 }
8821 if (eep_config->cfg_msw != cfg_msw) {
8822 warn_code |= ASC_WARN_EEPROM_RECOVER;
8823 eep_config->cfg_msw =
8824 AscGetChipCfgMsw(iop_base);
8825 }
8826 }
8827 }
8828 eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK;
8829 eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON;
8830 ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n",
8831 eep_config->chksum);
8832 if (chksum != eep_config->chksum) {
8833 if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ==
8834 ASC_CHIP_VER_PCI_ULTRA_3050) {
8835 ASC_DBG(1,
8836 "AscInitFromEEP: chksum error ignored; EEPROM-less board\n");
8837 eep_config->init_sdtr = 0xFF;
8838 eep_config->disc_enable = 0xFF;
8839 eep_config->start_motor = 0xFF;
8840 eep_config->use_cmd_qng = 0;
8841 eep_config->max_total_qng = 0xF0;
8842 eep_config->max_tag_qng = 0x20;
8843 eep_config->cntl = 0xBFFF;
8844 ASC_EEP_SET_CHIP_ID(eep_config, 7);
8845 eep_config->no_scam = 0;
8846 eep_config->adapter_info[0] = 0;
8847 eep_config->adapter_info[1] = 0;
8848 eep_config->adapter_info[2] = 0;
8849 eep_config->adapter_info[3] = 0;
8850 eep_config->adapter_info[4] = 0;
8851 /* Indicate EEPROM-less board. */
8852 eep_config->adapter_info[5] = 0xBB;
8853 } else {
8854 ASC_PRINT
8855 ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n");
8856 write_eep = 1;
8857 warn_code |= ASC_WARN_EEPROM_CHKSUM;
8858 }
8859 }
8860 asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr;
8861 asc_dvc->cfg->disc_enable = eep_config->disc_enable;
8862 asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
8863 asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config);
8864 asc_dvc->start_motor = eep_config->start_motor;
8865 asc_dvc->dvc_cntl = eep_config->cntl;
8866 asc_dvc->no_scam = eep_config->no_scam;
8867 asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0];
8868 asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1];
8869 asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2];
8870 asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3];
8871 asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4];
8872 asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5];
8873 if (!AscTestExternalLram(asc_dvc)) {
8874 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) ==
8875 ASC_IS_PCI_ULTRA)) {
8876 eep_config->max_total_qng =
8877 ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG;
8878 eep_config->max_tag_qng =
8879 ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG;
8880 } else {
8881 eep_config->cfg_msw |= 0x0800;
8882 cfg_msw |= 0x0800;
8883 AscSetChipCfgMsw(iop_base, cfg_msw);
8884 eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG;
8885 eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG;
8886 }
8887 } else {
8888 }
8889 if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) {
8890 eep_config->max_total_qng = ASC_MIN_TOTAL_QNG;
8891 }
8892 if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) {
8893 eep_config->max_total_qng = ASC_MAX_TOTAL_QNG;
8894 }
8895 if (eep_config->max_tag_qng > eep_config->max_total_qng) {
8896 eep_config->max_tag_qng = eep_config->max_total_qng;
8897 }
8898 if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) {
8899 eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC;
8900 }
8901 asc_dvc->max_total_qng = eep_config->max_total_qng;
8902 if ((eep_config->use_cmd_qng & eep_config->disc_enable) !=
8903 eep_config->use_cmd_qng) {
8904 eep_config->disc_enable = eep_config->use_cmd_qng;
8905 warn_code |= ASC_WARN_CMD_QNG_CONFLICT;
8906 }
8907 if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) {
8908 asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type);
8909 }
8910 ASC_EEP_SET_CHIP_ID(eep_config,
8911 ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID);
8912 asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config);
8913 if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) &&
8914 !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) {
8915 asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX;
8916 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008917
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008918 for (i = 0; i <= ASC_MAX_TID; i++) {
8919 asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i];
8920 asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng;
8921 asc_dvc->cfg->sdtr_period_offset[i] =
8922 (uchar)(ASC_DEF_SDTR_OFFSET |
8923 (asc_dvc->host_init_sdtr_index << 4));
8924 }
8925 eep_config->cfg_msw = AscGetChipCfgMsw(iop_base);
8926 if (write_eep) {
8927 if ((i =
8928 AscSetEEPConfig(iop_base, eep_config,
8929 asc_dvc->bus_type)) != 0) {
8930 ASC_PRINT1
8931 ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n",
8932 i);
8933 } else {
8934 ASC_PRINT
8935 ("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
8936 }
8937 }
8938 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008939}
8940
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008941static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008942{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008943 int i;
8944 ushort warn_code;
8945 PortAddr iop_base;
8946 ASC_PADDR phy_addr;
8947 ASC_DCNT phy_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008948
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008949 iop_base = asc_dvc->iop_base;
8950 warn_code = 0;
8951 for (i = 0; i <= ASC_MAX_TID; i++) {
8952 AscPutMCodeInitSDTRAtID(iop_base, i,
8953 asc_dvc->cfg->sdtr_period_offset[i]
8954 );
8955 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008956
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008957 AscInitQLinkVar(asc_dvc);
8958 AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
8959 asc_dvc->cfg->disc_enable);
8960 AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B,
8961 ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07008962
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008963 /* Align overrun buffer on an 8 byte boundary. */
8964 phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf);
8965 phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7);
8966 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D,
8967 (uchar *)&phy_addr, 1);
8968 phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8);
8969 AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D,
8970 (uchar *)&phy_size, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008971
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008972 asc_dvc->cfg->mcode_date =
8973 AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W);
8974 asc_dvc->cfg->mcode_version =
8975 AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008976
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008977 AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR);
8978 if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) {
8979 asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR;
8980 return (warn_code);
8981 }
8982 if (AscStartChip(iop_base) != 1) {
8983 asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP;
8984 return (warn_code);
8985 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07008986
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008987 return (warn_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -07008988}
8989
Matthew Wilcox78e77d82007-07-29 21:46:15 -06008990static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07008991{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008992 PortAddr iop_base;
8993 ushort q_addr;
8994 ushort saved_word;
8995 int sta;
Linus Torvalds1da177e2005-04-16 15:20:36 -07008996
Matthew Wilcox27c868c2007-07-26 10:56:23 -04008997 iop_base = asc_dvc->iop_base;
8998 sta = 0;
8999 q_addr = ASC_QNO_TO_QADDR(241);
9000 saved_word = AscReadLramWord(iop_base, q_addr);
9001 AscSetChipLramAddr(iop_base, q_addr);
9002 AscSetChipLramData(iop_base, 0x55AA);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06009003 mdelay(10);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009004 AscSetChipLramAddr(iop_base, q_addr);
9005 if (AscGetChipLramData(iop_base) == 0x55AA) {
9006 sta = 1;
9007 AscWriteLramWord(iop_base, q_addr, saved_word);
9008 }
9009 return (sta);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009010}
9011
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009012static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009013{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009014 uchar read_back;
9015 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009016
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009017 retry = 0;
9018 while (TRUE) {
9019 AscSetChipEEPCmd(iop_base, cmd_reg);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06009020 mdelay(1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009021 read_back = AscGetChipEEPCmd(iop_base);
9022 if (read_back == cmd_reg) {
9023 return (1);
9024 }
9025 if (retry++ > ASC_EEP_MAX_RETRY) {
9026 return (0);
9027 }
9028 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009029}
9030
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009031static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009032{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009033 ushort read_back;
9034 int retry;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009035
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009036 retry = 0;
9037 while (TRUE) {
9038 AscSetChipEEPData(iop_base, data_reg);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06009039 mdelay(1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009040 read_back = AscGetChipEEPData(iop_base);
9041 if (read_back == data_reg) {
9042 return (1);
9043 }
9044 if (retry++ > ASC_EEP_MAX_RETRY) {
9045 return (0);
9046 }
9047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009048}
9049
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009050static void __devinit AscWaitEEPRead(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009051{
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06009052 mdelay(1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009053 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009054}
9055
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009056static void __devinit AscWaitEEPWrite(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009057{
Matthew Wilcoxb009bef2007-09-09 08:56:38 -06009058 mdelay(20);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009059 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009060}
9061
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009062static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009063{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009064 ushort read_wval;
9065 uchar cmd_reg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009066
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009067 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9068 AscWaitEEPRead();
9069 cmd_reg = addr | ASC_EEP_CMD_READ;
9070 AscWriteEEPCmdReg(iop_base, cmd_reg);
9071 AscWaitEEPRead();
9072 read_wval = AscGetChipEEPData(iop_base);
9073 AscWaitEEPRead();
9074 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009075}
9076
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009077static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009078AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009079{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009080 ushort read_wval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009081
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009082 read_wval = AscReadEEPWord(iop_base, addr);
9083 if (read_wval != word_val) {
9084 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE);
9085 AscWaitEEPRead();
9086 AscWriteEEPDataReg(iop_base, word_val);
9087 AscWaitEEPRead();
9088 AscWriteEEPCmdReg(iop_base,
9089 (uchar)((uchar)ASC_EEP_CMD_WRITE | addr));
9090 AscWaitEEPWrite();
9091 AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE);
9092 AscWaitEEPRead();
9093 return (AscReadEEPWord(iop_base, addr));
9094 }
9095 return (read_wval);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009096}
9097
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009098static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009099AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009100{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009101 ushort wval;
9102 ushort sum;
9103 ushort *wbuf;
9104 int cfg_beg;
9105 int cfg_end;
9106 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
9107 int s_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009108
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009109 wbuf = (ushort *)cfg_buf;
9110 sum = 0;
9111 /* Read two config words; Byte-swapping done by AscReadEEPWord(). */
9112 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9113 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9114 sum += *wbuf;
9115 }
9116 if (bus_type & ASC_IS_VL) {
9117 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9118 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9119 } else {
9120 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9121 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9122 }
9123 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9124 wval = AscReadEEPWord(iop_base, (uchar)s_addr);
9125 if (s_addr <= uchar_end_in_config) {
9126 /*
9127 * Swap all char fields - must unswap bytes already swapped
9128 * by AscReadEEPWord().
9129 */
9130 *wbuf = le16_to_cpu(wval);
9131 } else {
9132 /* Don't swap word field at the end - cntl field. */
9133 *wbuf = wval;
9134 }
9135 sum += wval; /* Checksum treats all EEPROM data as words. */
9136 }
9137 /*
9138 * Read the checksum word which will be compared against 'sum'
9139 * by the caller. Word field already swapped.
9140 */
9141 *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr);
9142 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009143}
9144
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009145static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009146AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009147{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009148 int n_error;
9149 ushort *wbuf;
9150 ushort word;
9151 ushort sum;
9152 int s_addr;
9153 int cfg_beg;
9154 int cfg_end;
9155 int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009156
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009157 wbuf = (ushort *)cfg_buf;
9158 n_error = 0;
9159 sum = 0;
9160 /* Write two config words; AscWriteEEPWord() will swap bytes. */
9161 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9162 sum += *wbuf;
9163 if (*wbuf != AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9164 n_error++;
9165 }
9166 }
9167 if (bus_type & ASC_IS_VL) {
9168 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9169 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9170 } else {
9171 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9172 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9173 }
9174 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9175 if (s_addr <= uchar_end_in_config) {
9176 /*
9177 * This is a char field. Swap char fields before they are
9178 * swapped again by AscWriteEEPWord().
9179 */
9180 word = cpu_to_le16(*wbuf);
9181 if (word !=
9182 AscWriteEEPWord(iop_base, (uchar)s_addr, word)) {
9183 n_error++;
9184 }
9185 } else {
9186 /* Don't swap word field at the end - cntl field. */
9187 if (*wbuf !=
9188 AscWriteEEPWord(iop_base, (uchar)s_addr, *wbuf)) {
9189 n_error++;
9190 }
9191 }
9192 sum += *wbuf; /* Checksum calculated from word values. */
9193 }
9194 /* Write checksum word. It will be swapped by AscWriteEEPWord(). */
9195 *wbuf = sum;
9196 if (sum != AscWriteEEPWord(iop_base, (uchar)s_addr, sum)) {
9197 n_error++;
9198 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009199
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009200 /* Read EEPROM back again. */
9201 wbuf = (ushort *)cfg_buf;
9202 /*
9203 * Read two config words; Byte-swapping done by AscReadEEPWord().
9204 */
9205 for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) {
9206 if (*wbuf != AscReadEEPWord(iop_base, (uchar)s_addr)) {
9207 n_error++;
9208 }
9209 }
9210 if (bus_type & ASC_IS_VL) {
9211 cfg_beg = ASC_EEP_DVC_CFG_BEG_VL;
9212 cfg_end = ASC_EEP_MAX_DVC_ADDR_VL;
9213 } else {
9214 cfg_beg = ASC_EEP_DVC_CFG_BEG;
9215 cfg_end = ASC_EEP_MAX_DVC_ADDR;
9216 }
9217 for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) {
9218 if (s_addr <= uchar_end_in_config) {
9219 /*
9220 * Swap all char fields. Must unswap bytes already swapped
9221 * by AscReadEEPWord().
9222 */
9223 word =
9224 le16_to_cpu(AscReadEEPWord
9225 (iop_base, (uchar)s_addr));
9226 } else {
9227 /* Don't swap word field at the end - cntl field. */
9228 word = AscReadEEPWord(iop_base, (uchar)s_addr);
9229 }
9230 if (*wbuf != word) {
9231 n_error++;
9232 }
9233 }
9234 /* Read checksum; Byte swapping not needed. */
9235 if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) {
9236 n_error++;
9237 }
9238 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009239}
9240
Matthew Wilcox78e77d82007-07-29 21:46:15 -06009241static int __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009242AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009243{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009244 int retry;
9245 int n_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009246
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009247 retry = 0;
9248 while (TRUE) {
9249 if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf,
9250 bus_type)) == 0) {
9251 break;
9252 }
9253 if (++retry > ASC_EEP_MAX_RETRY) {
9254 break;
9255 }
9256 }
9257 return (n_error);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009258}
9259
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009260static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009261{
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009262 char type = sdev->type;
9263 ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009264
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009265 if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
9266 if (!(asc_dvc->init_sdtr & tid_bits)) {
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009267 if ((type == TYPE_ROM) &&
9268 (strncmp(sdev->vendor, "HP ", 3) == 0)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009269 asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
9270 }
9271 asc_dvc->pci_fix_asyn_xfer |= tid_bits;
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009272 if ((type == TYPE_PROCESSOR) ||
9273 (type == TYPE_SCANNER) || (type == TYPE_ROM) ||
9274 (type == TYPE_TAPE)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009275 asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
9276 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009277
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009278 if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
9279 AscSetRunChipSynRegAtID(asc_dvc->iop_base,
Matthew Wilcox47d853c2007-07-26 11:41:33 -04009280 sdev->id,
9281 ASYN_SDTR_DATA_FIX_PCI_REV_AB);
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009282 }
9283 }
9284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07009285}
9286
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009287static uchar AscReadLramByte(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009288{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009289 uchar byte_data;
9290 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009291
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009292 if (isodd_word(addr)) {
9293 AscSetChipLramAddr(iop_base, addr - 1);
9294 word_data = AscGetChipLramData(iop_base);
9295 byte_data = (uchar)((word_data >> 8) & 0xFF);
9296 } else {
9297 AscSetChipLramAddr(iop_base, addr);
9298 word_data = AscGetChipLramData(iop_base);
9299 byte_data = (uchar)(word_data & 0xFF);
9300 }
9301 return (byte_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009302}
Linus Torvalds1da177e2005-04-16 15:20:36 -07009303
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009304static ushort AscReadLramWord(PortAddr iop_base, ushort addr)
9305{
9306 ushort word_data;
9307
9308 AscSetChipLramAddr(iop_base, addr);
9309 word_data = AscGetChipLramData(iop_base);
9310 return (word_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009311}
9312
9313#if CC_VERY_LONG_SG_LIST
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009314static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009315{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009316 ushort val_low, val_high;
9317 ASC_DCNT dword_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009318
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009319 AscSetChipLramAddr(iop_base, addr);
9320 val_low = AscGetChipLramData(iop_base);
9321 val_high = AscGetChipLramData(iop_base);
9322 dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low;
9323 return (dword_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009324}
9325#endif /* CC_VERY_LONG_SG_LIST */
9326
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009327static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009328{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009329 AscSetChipLramAddr(iop_base, addr);
9330 AscSetChipLramData(iop_base, word_val);
9331 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009332}
9333
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009334static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009335{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009336 ushort word_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009337
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009338 if (isodd_word(addr)) {
9339 addr--;
9340 word_data = AscReadLramWord(iop_base, addr);
9341 word_data &= 0x00FF;
9342 word_data |= (((ushort)byte_val << 8) & 0xFF00);
9343 } else {
9344 word_data = AscReadLramWord(iop_base, addr);
9345 word_data &= 0xFF00;
9346 word_data |= ((ushort)byte_val & 0x00FF);
9347 }
9348 AscWriteLramWord(iop_base, addr, word_data);
9349 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009350}
9351
9352/*
9353 * Copy 2 bytes to LRAM.
9354 *
9355 * The source data is assumed to be in little-endian order in memory
9356 * and is maintained in little-endian order when written to LRAM.
9357 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009358static void
9359AscMemWordCopyPtrToLram(PortAddr iop_base,
9360 ushort s_addr, uchar *s_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009361{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009362 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009363
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009364 AscSetChipLramAddr(iop_base, s_addr);
9365 for (i = 0; i < 2 * words; i += 2) {
9366 /*
9367 * On a little-endian system the second argument below
9368 * produces a little-endian ushort which is written to
9369 * LRAM in little-endian order. On a big-endian system
9370 * the second argument produces a big-endian ushort which
9371 * is "transparently" byte-swapped by outpw() and written
9372 * in little-endian order to LRAM.
9373 */
9374 outpw(iop_base + IOP_RAM_DATA,
9375 ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]);
9376 }
9377 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009378}
9379
9380/*
9381 * Copy 4 bytes to LRAM.
9382 *
9383 * The source data is assumed to be in little-endian order in memory
9384 * and is maintained in little-endian order when writen to LRAM.
9385 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009386static void
9387AscMemDWordCopyPtrToLram(PortAddr iop_base,
9388 ushort s_addr, uchar *s_buffer, int dwords)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009389{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009390 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009391
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009392 AscSetChipLramAddr(iop_base, s_addr);
9393 for (i = 0; i < 4 * dwords; i += 4) {
9394 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */
9395 outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */
9396 }
9397 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009398}
9399
9400/*
9401 * Copy 2 bytes from LRAM.
9402 *
9403 * The source data is assumed to be in little-endian order in LRAM
9404 * and is maintained in little-endian order when written to memory.
9405 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009406static void
9407AscMemWordCopyPtrFromLram(PortAddr iop_base,
9408 ushort s_addr, uchar *d_buffer, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009409{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009410 int i;
9411 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009412
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009413 AscSetChipLramAddr(iop_base, s_addr);
9414 for (i = 0; i < 2 * words; i += 2) {
9415 word = inpw(iop_base + IOP_RAM_DATA);
9416 d_buffer[i] = word & 0xff;
9417 d_buffer[i + 1] = (word >> 8) & 0xff;
9418 }
9419 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009420}
9421
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009422static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009423{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009424 ASC_DCNT sum;
9425 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009426
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009427 sum = 0L;
9428 for (i = 0; i < words; i++, s_addr += 2) {
9429 sum += AscReadLramWord(iop_base, s_addr);
9430 }
9431 return (sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07009432}
9433
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009434static void
9435AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009436{
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009437 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009438
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009439 AscSetChipLramAddr(iop_base, s_addr);
9440 for (i = 0; i < words; i++) {
9441 AscSetChipLramData(iop_base, set_wval);
9442 }
9443 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07009444}
9445
Linus Torvalds1da177e2005-04-16 15:20:36 -07009446/*
9447 * --- Adv Library Functions
9448 */
9449
9450/* a_mcode.h */
9451
9452/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009453static unsigned char _adv_asc3550_buf[] = {
9454 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009455 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
9456 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
9457 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009458 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009459 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
9460 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
9461 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009462 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009463 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
9464 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
9465 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009466 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009467 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
9468 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
9469 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009470 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009471 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
9472 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
9473 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009474 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009475 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
9476 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
9477 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009478 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009479 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
9480 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
9481 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009482 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009483 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
9484 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
9485 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009486 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009487 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
9488 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
9489 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009490 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009491 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
9492 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
9493 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009494 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009495 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
9496 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
9497 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009498 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009499 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
9500 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
9501 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009502 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009503 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
9504 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
9505 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009506 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009507 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
9508 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
9509 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009510 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009511 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
9512 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
9513 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009514 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009515 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
9516 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
9517 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009518 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009519 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
9520 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
9521 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009522 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009523 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
9524 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
9525 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009526 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009527 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
9528 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
9529 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009530 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009531 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
9532 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
9533 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009534 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009535 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
9536 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
9537 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009538 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009539 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
9540 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
9541 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009542 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009543 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
9544 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
9545 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009546 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009547 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
9548 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
9549 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009550 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009551 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
9552 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
9553 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009554 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009555 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
9556 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
9557 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009558 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009559 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
9560 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
9561 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009562 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009563 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
9564 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
9565 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009566 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009567 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
9568 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
9569 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009570 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009571 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
9572 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
9573 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009574 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009575 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
9576 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
9577 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009578 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009579 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
9580 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
9581 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009582 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009583 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
9584 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
9585 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009586 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009587 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
9588 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
9589 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009590 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009591 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
9592 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
9593 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009594 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009595 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
9596 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
9597 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009598 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009599 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
9600 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
9601 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009602 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009603 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
9604 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
9605 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009606 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009607 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
9608 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
9609 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009610 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009611 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
9612 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
9613 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009614 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009615 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
9616 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
9617 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009618 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009619 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
9620 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
9621 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009622 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009623 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
9624 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
9625 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009626 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009627 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
9628 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
9629 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009630 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009631 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
9632 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
9633 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009634 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009635 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
9636 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
9637 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009638 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009639 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
9640 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
9641 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009642 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009643 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
9644 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
9645 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009646 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009647 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
9648 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
9649 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009650 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009651 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
9652 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
9653 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009654 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009655 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
9656 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
9657 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009658 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009659 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
9660 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
9661 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009662 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009663 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
9664 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
9665 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009666 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009667 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
9668 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
9669 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009670 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009671 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
9672 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
9673 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009674 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009675 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
9676 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
9677 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009678 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009679 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
9680 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
9681 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009682 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009683 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
9684 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
9685 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009686 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009687 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
9688 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
9689 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009690 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009691 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
9692 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
9693 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009694 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009695 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
9696 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
9697 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009698 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009699 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
9700 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
9701 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009702 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009703 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
9704 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
9705 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009706 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009707 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
9708 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
9709 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009710 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009711 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
9712 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
9713 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009714 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009715 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
9716 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
9717 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009718 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009719 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
9720 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
9721 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009722 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009723 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
9724 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
9725 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009726 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009727 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
9728 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
9729 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009730 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009731 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
9732 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
9733 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009734 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009735 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
9736 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
9737 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009738 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009739 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
9740 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
9741 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009742 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009743 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
9744 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
9745 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009746 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009747 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
9748 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
9749 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009750 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009751 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
9752 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
9753 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009754 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009755 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
9756 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
9757 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009758 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009759 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
9760 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
9761 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009762 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009763 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
9764 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
9765 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009766 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009767 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
9768 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
9769 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009770 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009771 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
9772 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
9773 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009774 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009775 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
9776 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
9777 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009778 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009779 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
9780 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
9781 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009782 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009783 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
9784 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
9785 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009786 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009787 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
9788 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
9789 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009790 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009791 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
9792 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
9793 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009794 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009795 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
9796 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
9797 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009798 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009799 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
9800 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
9801 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009802 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009803 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
9804 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
9805 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009806 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009807 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
9808 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
9809 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009810 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009811 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
9812 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
9813 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009814 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009815 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
9816 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
9817 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009818 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009819 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
9820 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
9821 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009822 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009823 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
9824 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
9825 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009826 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009827 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
9828 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
9829 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009830 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009831 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
9832 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
9833 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009834 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009835 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
9836 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
9837 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009838 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009839 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
9840 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
9841 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009842 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009843 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
9844 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
9845 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009846 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009847 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
9848 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
9849 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009850 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009851 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
9852 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
9853 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009854 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009855 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
9856 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
9857 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009858 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009859 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
9860 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
9861 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009862 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009863 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
9864 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
9865 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009866 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009867 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
9868 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
9869 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009870 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009871 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
9872 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -07009873};
9874
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009875static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
9876static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07009877
9878/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009879static unsigned char _adv_asc38C0800_buf[] = {
9880 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009881 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
9882 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
9883 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009884 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009885 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
9886 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
9887 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009888 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009889 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
9890 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
9891 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009892 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009893 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
9894 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
9895 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009896 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009897 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
9898 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
9899 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009900 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009901 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
9902 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
9903 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009904 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009905 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
9906 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
9907 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009908 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009909 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
9910 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
9911 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009912 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009913 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
9914 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
9915 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009916 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009917 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
9918 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
9919 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009920 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009921 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
9922 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
9923 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009924 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009925 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
9926 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
9927 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009928 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009929 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
9930 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
9931 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009932 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009933 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
9934 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
9935 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009936 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009937 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
9938 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
9939 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009940 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009941 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
9942 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
9943 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009944 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009945 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
9946 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
9947 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009948 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009949 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
9950 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
9951 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009952 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009953 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
9954 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
9955 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009956 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009957 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
9958 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
9959 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009960 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009961 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
9962 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
9963 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009964 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009965 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
9966 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
9967 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009968 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009969 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
9970 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
9971 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009972 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009973 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
9974 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
9975 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009976 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009977 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
9978 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
9979 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009980 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009981 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
9982 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
9983 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009984 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009985 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
9986 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
9987 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009988 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009989 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
9990 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
9991 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009992 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009993 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
9994 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
9995 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
Matthew Wilcox27c868c2007-07-26 10:56:23 -04009996 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
Matthew Wilcox629d6882007-09-09 08:56:29 -06009997 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
9998 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
9999 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010000 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010001 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
10002 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
10003 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010004 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010005 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
10006 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
10007 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010008 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010009 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
10010 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
10011 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010012 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010013 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
10014 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
10015 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010016 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010017 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
10018 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
10019 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010020 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010021 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
10022 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
10023 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010024 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010025 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
10026 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
10027 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010028 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010029 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
10030 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
10031 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010032 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010033 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
10034 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
10035 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010036 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010037 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
10038 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
10039 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010040 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010041 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
10042 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
10043 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010044 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010045 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
10046 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
10047 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010048 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010049 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
10050 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
10051 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010052 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010053 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
10054 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
10055 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010056 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010057 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
10058 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
10059 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010060 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010061 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
10062 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
10063 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010064 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010065 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
10066 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
10067 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010068 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010069 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
10070 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
10071 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010072 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010073 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
10074 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
10075 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010076 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010077 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
10078 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
10079 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010080 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010081 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
10082 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
10083 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010084 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010085 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
10086 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
10087 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010088 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010089 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
10090 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
10091 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010092 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010093 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
10094 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
10095 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010096 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010097 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
10098 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
10099 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010100 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010101 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
10102 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
10103 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010104 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010105 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
10106 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
10107 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010108 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010109 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
10110 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
10111 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010112 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010113 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
10114 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
10115 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010116 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010117 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
10118 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
10119 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010120 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010121 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
10122 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
10123 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010124 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010125 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
10126 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
10127 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010128 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010129 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
10130 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
10131 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010132 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010133 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
10134 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
10135 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010136 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010137 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
10138 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
10139 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010140 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010141 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
10142 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
10143 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010144 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010145 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
10146 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
10147 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010148 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010149 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
10150 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
10151 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010152 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010153 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
10154 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
10155 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010156 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010157 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
10158 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
10159 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010160 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010161 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
10162 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
10163 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010164 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010165 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
10166 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
10167 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010168 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010169 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
10170 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
10171 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010172 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010173 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
10174 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
10175 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010176 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010177 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
10178 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
10179 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010180 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010181 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
10182 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
10183 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010184 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010185 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
10186 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
10187 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010188 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010189 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
10190 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
10191 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010192 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010193 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
10194 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
10195 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010196 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010197 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
10198 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
10199 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010200 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010201 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
10202 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
10203 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010204 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010205 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
10206 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
10207 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010208 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010209 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
10210 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
10211 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010212 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010213 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
10214 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
10215 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010216 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010217 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
10218 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
10219 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010220 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010221 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
10222 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
10223 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010224 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010225 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
10226 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10227 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010228 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010229 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
10230 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
10231 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010232 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010233 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
10234 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
10235 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010236 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010237 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
10238 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
10239 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010240 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010241 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
10242 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
10243 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010244 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010245 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
10246 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
10247 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010248 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010249 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
10250 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
10251 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010252 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010253 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
10254 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
10255 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010256 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010257 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
10258 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
10259 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010260 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010261 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
10262 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
10263 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010264 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010265 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
10266 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
10267 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010268 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010269 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
10270 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
10271 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010272 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010273 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
10274 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
10275 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010276 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010277 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
10278 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
10279 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010280 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010281 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
10282 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
10283 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010284 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010285 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
10286 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
10287 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010288 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010289 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
10290 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
10291 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010292 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010293 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
10294 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
10295 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010296 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010297 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
10298 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
10299 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010300 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010301 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
10302 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
10303 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010304 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010305 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
10306 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
10307 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010308 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010309 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
10310 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
10311 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010312 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010313 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
10314 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
10315 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010316 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010317 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
10318 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
10319 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010320 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010321 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
10322 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
10323 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010324 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010325};
10326
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010327static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
10328static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010329
10330/* Microcode buffer is kept after initialization for error recovery. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010331static unsigned char _adv_asc38C1600_buf[] = {
10332 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010333 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
10334 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
10335 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010336 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010337 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
10338 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
10339 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010340 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010341 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
10342 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
10343 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010344 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010345 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
10346 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
10347 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010348 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010349 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
10350 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
10351 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010352 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010353 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
10354 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
10355 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010356 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010357 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
10358 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
10359 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010360 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010361 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
10362 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
10363 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010364 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010365 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
10366 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
10367 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010368 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010369 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
10370 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
10371 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010372 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010373 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
10374 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
10375 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010376 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010377 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
10378 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
10379 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010380 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010381 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
10382 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
10383 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010384 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010385 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
10386 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
10387 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010388 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010389 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
10390 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
10391 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010392 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010393 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
10394 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
10395 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010396 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010397 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
10398 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
10399 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010400 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010401 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
10402 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
10403 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010404 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010405 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
10406 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
10407 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010408 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010409 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
10410 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
10411 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010412 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010413 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
10414 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
10415 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010416 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010417 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
10418 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
10419 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010420 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010421 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
10422 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
10423 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010424 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010425 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
10426 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
10427 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010428 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010429 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
10430 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
10431 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010432 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010433 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
10434 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
10435 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010436 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010437 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
10438 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
10439 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010440 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010441 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
10442 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
10443 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010444 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010445 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
10446 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
10447 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010448 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010449 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
10450 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
10451 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010452 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010453 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
10454 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
10455 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010456 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010457 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
10458 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
10459 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010460 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010461 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
10462 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
10463 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010464 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010465 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
10466 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
10467 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010468 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010469 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
10470 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
10471 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010472 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010473 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
10474 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
10475 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010476 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010477 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
10478 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
10479 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010480 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010481 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
10482 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
10483 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010484 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010485 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
10486 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
10487 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010488 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010489 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
10490 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
10491 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010492 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010493 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
10494 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
10495 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010496 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010497 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
10498 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
10499 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010500 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010501 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
10502 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
10503 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010504 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010505 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
10506 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
10507 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010508 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010509 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
10510 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
10511 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010512 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010513 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
10514 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
10515 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010516 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010517 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
10518 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
10519 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010520 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010521 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
10522 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
10523 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010524 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010525 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
10526 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
10527 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010528 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010529 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
10530 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
10531 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010532 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010533 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
10534 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
10535 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010536 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010537 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
10538 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
10539 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010540 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010541 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
10542 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
10543 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010544 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010545 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
10546 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
10547 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010548 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010549 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
10550 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
10551 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010552 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010553 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
10554 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
10555 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010556 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010557 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
10558 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
10559 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010560 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010561 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
10562 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
10563 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010564 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010565 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
10566 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
10567 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010568 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010569 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
10570 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
10571 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010572 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010573 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
10574 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
10575 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010576 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010577 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
10578 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
10579 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010580 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010581 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
10582 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
10583 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010584 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010585 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
10586 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
10587 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010588 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010589 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
10590 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
10591 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010592 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010593 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
10594 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
10595 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010596 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010597 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
10598 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
10599 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010600 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010601 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
10602 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
10603 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010604 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010605 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
10606 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
10607 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010608 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010609 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
10610 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
10611 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010612 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010613 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
10614 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
10615 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010616 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010617 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
10618 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
10619 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010620 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010621 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
10622 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
10623 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010624 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010625 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
10626 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
10627 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010628 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010629 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
10630 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
10631 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010632 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010633 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
10634 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
10635 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010636 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010637 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
10638 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
10639 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010640 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010641 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
10642 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
10643 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010644 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010645 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
10646 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
10647 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010648 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010649 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
10650 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
10651 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010652 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010653 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
10654 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
10655 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010656 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010657 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
10658 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
10659 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010660 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010661 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
10662 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
10663 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010664 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010665 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
10666 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
10667 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010668 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010669 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
10670 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
10671 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010672 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010673 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
10674 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
10675 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010676 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010677 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
10678 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
10679 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010680 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010681 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
10682 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
10683 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010684 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010685 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
10686 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
10687 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010688 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010689 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
10690 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
10691 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010692 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010693 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
10694 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
10695 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010696 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010697 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
10698 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
10699 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010700 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010701 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
10702 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
10703 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010704 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010705 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
10706 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
10707 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010708 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010709 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
10710 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
10711 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010712 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010713 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
10714 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
10715 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010716 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010717 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
10718 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
10719 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010720 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010721 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
10722 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
10723 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010724 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010725 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
10726 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
10727 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010728 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010729 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
10730 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
10731 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010732 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010733 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
10734 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
10735 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010736 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010737 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
10738 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
10739 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010740 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010741 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
10742 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
10743 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010744 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010745 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
10746 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
10747 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010748 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010749 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
10750 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
10751 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010752 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010753 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
10754 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
10755 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010756 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010757 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
10758 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
10759 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010760 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010761 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
10762 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
10763 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010764 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010765 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
10766 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
10767 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010768 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010769 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
10770 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
10771 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010772 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010773 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
10774 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
10775 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010776 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010777 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
10778 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
10779 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010780 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010781 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
10782 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
10783 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010784 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010785 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
10786 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
10787 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010788 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010789 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
10790 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
10791 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010792 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010793 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
10794 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
10795 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010796 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010797 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
10798 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
10799 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010800 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010801 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
10802 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
10803 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010804 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010805 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
10806 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
10807 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010808 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010809 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
10810 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
10811 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010812 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010813 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
10814 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
10815 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010816 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010817 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
10818 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
10819 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010820 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010821 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
10822 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
10823 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010824 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010825 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
10826 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
10827 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010828 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010829 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
10830 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
10831 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010832 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010833 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
10834 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
10835 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010836 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010837 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
10838 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
10839 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010840 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010841 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
10842 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
10843 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010844 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010845 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
10846 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
10847 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010848 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010849 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
10850 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
10851 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010852 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010853 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
10854 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
10855 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010856 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
Matthew Wilcox629d6882007-09-09 08:56:29 -060010857 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
10858 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
10859 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
Linus Torvalds1da177e2005-04-16 15:20:36 -070010860};
10861
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010862static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
10863static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010864
Linus Torvalds1da177e2005-04-16 15:20:36 -070010865/*
10866 * EEPROM Configuration.
10867 *
10868 * All drivers should use this structure to set the default EEPROM
10869 * configuration. The BIOS now uses this structure when it is built.
10870 * Additional structure information can be found in a_condor.h where
10871 * the structure is defined.
10872 *
10873 * The *_Field_IsChar structs are needed to correct for endianness.
10874 * These values are read from the board 16 bits at a time directly
10875 * into the structs. Because some fields are char, the values will be
10876 * in the wrong order. The *_Field_IsChar tells when to flip the
10877 * bytes. Data read and written to PCI memory is automatically swapped
10878 * on big-endian platforms so char fields read as words are actually being
10879 * unswapped on big-endian platforms.
10880 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010881static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010882 ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */
10883 0x0000, /* cfg_msw */
10884 0xFFFF, /* disc_enable */
10885 0xFFFF, /* wdtr_able */
10886 0xFFFF, /* sdtr_able */
10887 0xFFFF, /* start_motor */
10888 0xFFFF, /* tagqng_able */
10889 0xFFFF, /* bios_scan */
10890 0, /* scam_tolerant */
10891 7, /* adapter_scsi_id */
10892 0, /* bios_boot_delay */
10893 3, /* scsi_reset_delay */
10894 0, /* bios_id_lun */
10895 0, /* termination */
10896 0, /* reserved1 */
10897 0xFFE7, /* bios_ctrl */
10898 0xFFFF, /* ultra_able */
10899 0, /* reserved2 */
10900 ASC_DEF_MAX_HOST_QNG, /* max_host_qng */
10901 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
10902 0, /* dvc_cntl */
10903 0, /* bug_fix */
10904 0, /* serial_number_word1 */
10905 0, /* serial_number_word2 */
10906 0, /* serial_number_word3 */
10907 0, /* check_sum */
10908 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
10909 , /* oem_name[16] */
10910 0, /* dvc_err_code */
10911 0, /* adv_err_code */
10912 0, /* adv_err_addr */
10913 0, /* saved_dvc_err_code */
10914 0, /* saved_adv_err_code */
10915 0, /* saved_adv_err_addr */
10916 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010917};
10918
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010919static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010920 0, /* cfg_lsw */
10921 0, /* cfg_msw */
10922 0, /* -disc_enable */
10923 0, /* wdtr_able */
10924 0, /* sdtr_able */
10925 0, /* start_motor */
10926 0, /* tagqng_able */
10927 0, /* bios_scan */
10928 0, /* scam_tolerant */
10929 1, /* adapter_scsi_id */
10930 1, /* bios_boot_delay */
10931 1, /* scsi_reset_delay */
10932 1, /* bios_id_lun */
10933 1, /* termination */
10934 1, /* reserved1 */
10935 0, /* bios_ctrl */
10936 0, /* ultra_able */
10937 0, /* reserved2 */
10938 1, /* max_host_qng */
10939 1, /* max_dvc_qng */
10940 0, /* dvc_cntl */
10941 0, /* bug_fix */
10942 0, /* serial_number_word1 */
10943 0, /* serial_number_word2 */
10944 0, /* serial_number_word3 */
10945 0, /* check_sum */
10946 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
10947 , /* oem_name[16] */
10948 0, /* dvc_err_code */
10949 0, /* adv_err_code */
10950 0, /* adv_err_addr */
10951 0, /* saved_dvc_err_code */
10952 0, /* saved_adv_err_code */
10953 0, /* saved_adv_err_addr */
10954 0 /* num_of_err */
Linus Torvalds1da177e2005-04-16 15:20:36 -070010955};
10956
Matthew Wilcox78e77d82007-07-29 21:46:15 -060010957static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040010958 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
10959 0x0000, /* 01 cfg_msw */
10960 0xFFFF, /* 02 disc_enable */
10961 0xFFFF, /* 03 wdtr_able */
10962 0x4444, /* 04 sdtr_speed1 */
10963 0xFFFF, /* 05 start_motor */
10964 0xFFFF, /* 06 tagqng_able */
10965 0xFFFF, /* 07 bios_scan */
10966 0, /* 08 scam_tolerant */
10967 7, /* 09 adapter_scsi_id */
10968 0, /* bios_boot_delay */
10969 3, /* 10 scsi_reset_delay */
10970 0, /* bios_id_lun */
10971 0, /* 11 termination_se */
10972 0, /* termination_lvd */
10973 0xFFE7, /* 12 bios_ctrl */
10974 0x4444, /* 13 sdtr_speed2 */
10975 0x4444, /* 14 sdtr_speed3 */
10976 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
10977 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
10978 0, /* 16 dvc_cntl */
10979 0x4444, /* 17 sdtr_speed4 */
10980 0, /* 18 serial_number_word1 */
10981 0, /* 19 serial_number_word2 */
10982 0, /* 20 serial_number_word3 */
10983 0, /* 21 check_sum */
10984 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
10985 , /* 22-29 oem_name[16] */
10986 0, /* 30 dvc_err_code */
10987 0, /* 31 adv_err_code */
10988 0, /* 32 adv_err_addr */
10989 0, /* 33 saved_dvc_err_code */
10990 0, /* 34 saved_adv_err_code */
10991 0, /* 35 saved_adv_err_addr */
10992 0, /* 36 reserved */
10993 0, /* 37 reserved */
10994 0, /* 38 reserved */
10995 0, /* 39 reserved */
10996 0, /* 40 reserved */
10997 0, /* 41 reserved */
10998 0, /* 42 reserved */
10999 0, /* 43 reserved */
11000 0, /* 44 reserved */
11001 0, /* 45 reserved */
11002 0, /* 46 reserved */
11003 0, /* 47 reserved */
11004 0, /* 48 reserved */
11005 0, /* 49 reserved */
11006 0, /* 50 reserved */
11007 0, /* 51 reserved */
11008 0, /* 52 reserved */
11009 0, /* 53 reserved */
11010 0, /* 54 reserved */
11011 0, /* 55 reserved */
11012 0, /* 56 cisptr_lsw */
11013 0, /* 57 cisprt_msw */
11014 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11015 PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */
11016 0, /* 60 reserved */
11017 0, /* 61 reserved */
11018 0, /* 62 reserved */
11019 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011020};
11021
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011022static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011023 0, /* 00 cfg_lsw */
11024 0, /* 01 cfg_msw */
11025 0, /* 02 disc_enable */
11026 0, /* 03 wdtr_able */
11027 0, /* 04 sdtr_speed1 */
11028 0, /* 05 start_motor */
11029 0, /* 06 tagqng_able */
11030 0, /* 07 bios_scan */
11031 0, /* 08 scam_tolerant */
11032 1, /* 09 adapter_scsi_id */
11033 1, /* bios_boot_delay */
11034 1, /* 10 scsi_reset_delay */
11035 1, /* bios_id_lun */
11036 1, /* 11 termination_se */
11037 1, /* termination_lvd */
11038 0, /* 12 bios_ctrl */
11039 0, /* 13 sdtr_speed2 */
11040 0, /* 14 sdtr_speed3 */
11041 1, /* 15 max_host_qng */
11042 1, /* max_dvc_qng */
11043 0, /* 16 dvc_cntl */
11044 0, /* 17 sdtr_speed4 */
11045 0, /* 18 serial_number_word1 */
11046 0, /* 19 serial_number_word2 */
11047 0, /* 20 serial_number_word3 */
11048 0, /* 21 check_sum */
11049 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11050 , /* 22-29 oem_name[16] */
11051 0, /* 30 dvc_err_code */
11052 0, /* 31 adv_err_code */
11053 0, /* 32 adv_err_addr */
11054 0, /* 33 saved_dvc_err_code */
11055 0, /* 34 saved_adv_err_code */
11056 0, /* 35 saved_adv_err_addr */
11057 0, /* 36 reserved */
11058 0, /* 37 reserved */
11059 0, /* 38 reserved */
11060 0, /* 39 reserved */
11061 0, /* 40 reserved */
11062 0, /* 41 reserved */
11063 0, /* 42 reserved */
11064 0, /* 43 reserved */
11065 0, /* 44 reserved */
11066 0, /* 45 reserved */
11067 0, /* 46 reserved */
11068 0, /* 47 reserved */
11069 0, /* 48 reserved */
11070 0, /* 49 reserved */
11071 0, /* 50 reserved */
11072 0, /* 51 reserved */
11073 0, /* 52 reserved */
11074 0, /* 53 reserved */
11075 0, /* 54 reserved */
11076 0, /* 55 reserved */
11077 0, /* 56 cisptr_lsw */
11078 0, /* 57 cisprt_msw */
11079 0, /* 58 subsysvid */
11080 0, /* 59 subsysid */
11081 0, /* 60 reserved */
11082 0, /* 61 reserved */
11083 0, /* 62 reserved */
11084 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011085};
11086
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011087static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011088 ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */
11089 0x0000, /* 01 cfg_msw */
11090 0xFFFF, /* 02 disc_enable */
11091 0xFFFF, /* 03 wdtr_able */
11092 0x5555, /* 04 sdtr_speed1 */
11093 0xFFFF, /* 05 start_motor */
11094 0xFFFF, /* 06 tagqng_able */
11095 0xFFFF, /* 07 bios_scan */
11096 0, /* 08 scam_tolerant */
11097 7, /* 09 adapter_scsi_id */
11098 0, /* bios_boot_delay */
11099 3, /* 10 scsi_reset_delay */
11100 0, /* bios_id_lun */
11101 0, /* 11 termination_se */
11102 0, /* termination_lvd */
11103 0xFFE7, /* 12 bios_ctrl */
11104 0x5555, /* 13 sdtr_speed2 */
11105 0x5555, /* 14 sdtr_speed3 */
11106 ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */
11107 ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */
11108 0, /* 16 dvc_cntl */
11109 0x5555, /* 17 sdtr_speed4 */
11110 0, /* 18 serial_number_word1 */
11111 0, /* 19 serial_number_word2 */
11112 0, /* 20 serial_number_word3 */
11113 0, /* 21 check_sum */
11114 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
11115 , /* 22-29 oem_name[16] */
11116 0, /* 30 dvc_err_code */
11117 0, /* 31 adv_err_code */
11118 0, /* 32 adv_err_addr */
11119 0, /* 33 saved_dvc_err_code */
11120 0, /* 34 saved_adv_err_code */
11121 0, /* 35 saved_adv_err_addr */
11122 0, /* 36 reserved */
11123 0, /* 37 reserved */
11124 0, /* 38 reserved */
11125 0, /* 39 reserved */
11126 0, /* 40 reserved */
11127 0, /* 41 reserved */
11128 0, /* 42 reserved */
11129 0, /* 43 reserved */
11130 0, /* 44 reserved */
11131 0, /* 45 reserved */
11132 0, /* 46 reserved */
11133 0, /* 47 reserved */
11134 0, /* 48 reserved */
11135 0, /* 49 reserved */
11136 0, /* 50 reserved */
11137 0, /* 51 reserved */
11138 0, /* 52 reserved */
11139 0, /* 53 reserved */
11140 0, /* 54 reserved */
11141 0, /* 55 reserved */
11142 0, /* 56 cisptr_lsw */
11143 0, /* 57 cisprt_msw */
11144 PCI_VENDOR_ID_ASP, /* 58 subsysvid */
11145 PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */
11146 0, /* 60 reserved */
11147 0, /* 61 reserved */
11148 0, /* 62 reserved */
11149 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011150};
11151
Matthew Wilcox78e77d82007-07-29 21:46:15 -060011152static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011153 0, /* 00 cfg_lsw */
11154 0, /* 01 cfg_msw */
11155 0, /* 02 disc_enable */
11156 0, /* 03 wdtr_able */
11157 0, /* 04 sdtr_speed1 */
11158 0, /* 05 start_motor */
11159 0, /* 06 tagqng_able */
11160 0, /* 07 bios_scan */
11161 0, /* 08 scam_tolerant */
11162 1, /* 09 adapter_scsi_id */
11163 1, /* bios_boot_delay */
11164 1, /* 10 scsi_reset_delay */
11165 1, /* bios_id_lun */
11166 1, /* 11 termination_se */
11167 1, /* termination_lvd */
11168 0, /* 12 bios_ctrl */
11169 0, /* 13 sdtr_speed2 */
11170 0, /* 14 sdtr_speed3 */
11171 1, /* 15 max_host_qng */
11172 1, /* max_dvc_qng */
11173 0, /* 16 dvc_cntl */
11174 0, /* 17 sdtr_speed4 */
11175 0, /* 18 serial_number_word1 */
11176 0, /* 19 serial_number_word2 */
11177 0, /* 20 serial_number_word3 */
11178 0, /* 21 check_sum */
11179 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
11180 , /* 22-29 oem_name[16] */
11181 0, /* 30 dvc_err_code */
11182 0, /* 31 adv_err_code */
11183 0, /* 32 adv_err_addr */
11184 0, /* 33 saved_dvc_err_code */
11185 0, /* 34 saved_adv_err_code */
11186 0, /* 35 saved_adv_err_addr */
11187 0, /* 36 reserved */
11188 0, /* 37 reserved */
11189 0, /* 38 reserved */
11190 0, /* 39 reserved */
11191 0, /* 40 reserved */
11192 0, /* 41 reserved */
11193 0, /* 42 reserved */
11194 0, /* 43 reserved */
11195 0, /* 44 reserved */
11196 0, /* 45 reserved */
11197 0, /* 46 reserved */
11198 0, /* 47 reserved */
11199 0, /* 48 reserved */
11200 0, /* 49 reserved */
11201 0, /* 50 reserved */
11202 0, /* 51 reserved */
11203 0, /* 52 reserved */
11204 0, /* 53 reserved */
11205 0, /* 54 reserved */
11206 0, /* 55 reserved */
11207 0, /* 56 cisptr_lsw */
11208 0, /* 57 cisprt_msw */
11209 0, /* 58 subsysvid */
11210 0, /* 59 subsysid */
11211 0, /* 60 reserved */
11212 0, /* 61 reserved */
11213 0, /* 62 reserved */
11214 0 /* 63 reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011215};
11216
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011217#ifdef CONFIG_PCI
Linus Torvalds1da177e2005-04-16 15:20:36 -070011218/*
11219 * Initialize the ADV_DVC_VAR structure.
11220 *
11221 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11222 *
11223 * For a non-fatal error return a warning code. If there are no warnings
11224 * then 0 is returned.
11225 */
Matthew Wilcox394dbf32007-07-26 11:56:40 -040011226static int __devinit
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011227AdvInitGetConfig(struct pci_dev *pdev, asc_board_t *boardp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011228{
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011229 ADV_DVC_VAR *asc_dvc = &boardp->dvc_var.adv_dvc_var;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011230 unsigned short warn_code = 0;
11231 AdvPortAddr iop_base = asc_dvc->iop_base;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011232 u16 cmd;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011233 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011234
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011235 asc_dvc->err_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011236
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011237 /*
11238 * Save the state of the PCI Configuration Command Register
11239 * "Parity Error Response Control" Bit. If the bit is clear (0),
11240 * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore
11241 * DMA parity errors.
11242 */
11243 asc_dvc->cfg->control_flag = 0;
Matthew Wilcox9649af32007-07-26 21:51:47 -060011244 pci_read_config_word(pdev, PCI_COMMAND, &cmd);
11245 if ((cmd & PCI_COMMAND_PARITY) == 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011246 asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011247
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011248 asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) |
11249 ADV_LIB_VERSION_MINOR;
11250 asc_dvc->cfg->chip_version =
11251 AdvGetChipVersion(iop_base, asc_dvc->bus_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011252
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011253 ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n",
11254 (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1),
11255 (ushort)ADV_CHIP_ID_BYTE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011256
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011257 ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n",
11258 (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0),
11259 (ushort)ADV_CHIP_ID_WORD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011260
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011261 /*
11262 * Reset the chip to start and allow register writes.
11263 */
11264 if (AdvFindSignature(iop_base) == 0) {
11265 asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE;
11266 return ADV_ERROR;
11267 } else {
11268 /*
11269 * The caller must set 'chip_type' to a valid setting.
11270 */
11271 if (asc_dvc->chip_type != ADV_CHIP_ASC3550 &&
11272 asc_dvc->chip_type != ADV_CHIP_ASC38C0800 &&
11273 asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
11274 asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE;
11275 return ADV_ERROR;
11276 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011277
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011278 /*
11279 * Reset Chip.
11280 */
11281 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11282 ADV_CTRL_REG_CMD_RESET);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060011283 mdelay(100);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011284 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
11285 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011286
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011287 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011288 status = AdvInitFrom38C1600EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011289 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011290 status = AdvInitFrom38C0800EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011291 } else {
Matthew Wilcox9649af32007-07-26 21:51:47 -060011292 status = AdvInitFrom3550EEP(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011293 }
11294 warn_code |= status;
11295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011296
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011297 if (warn_code != 0) {
11298 ASC_PRINT2("AdvInitGetConfig: board %d: warning: 0x%x\n",
11299 boardp->id, warn_code);
11300 }
11301
11302 if (asc_dvc->err_code) {
11303 ASC_PRINT2("AdvInitGetConfig: board %d error: err_code 0x%x\n",
11304 boardp->id, asc_dvc->err_code);
11305 }
11306
11307 return asc_dvc->err_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011308}
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060011309#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070011310
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011311static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc)
11312{
11313 ADV_CARR_T *carrp;
11314 ADV_SDCNT buf_size;
11315 ADV_PADDR carr_paddr;
11316
11317 BUG_ON(!asc_dvc->carrier_buf);
11318
11319 carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf);
11320 asc_dvc->carr_freelist = NULL;
11321 if (carrp == asc_dvc->carrier_buf) {
11322 buf_size = ADV_CARRIER_BUFSIZE;
11323 } else {
11324 buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T);
11325 }
11326
11327 do {
11328 /* Get physical address of the carrier 'carrp'. */
11329 ADV_DCNT contig_len = sizeof(ADV_CARR_T);
11330 carr_paddr = cpu_to_le32(DvcGetPhyAddr(asc_dvc, NULL,
11331 (uchar *)carrp,
11332 (ADV_SDCNT *)&contig_len,
11333 ADV_IS_CARRIER_FLAG));
11334
11335 buf_size -= sizeof(ADV_CARR_T);
11336
11337 /*
11338 * If the current carrier is not physically contiguous, then
11339 * maybe there was a page crossing. Try the next carrier
11340 * aligned start address.
11341 */
11342 if (contig_len < sizeof(ADV_CARR_T)) {
11343 carrp++;
11344 continue;
11345 }
11346
11347 carrp->carr_pa = carr_paddr;
11348 carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp));
11349
11350 /*
11351 * Insert the carrier at the beginning of the freelist.
11352 */
11353 carrp->next_vpa =
11354 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
11355 asc_dvc->carr_freelist = carrp;
11356
11357 carrp++;
11358 } while (buf_size > 0);
11359}
11360
Linus Torvalds1da177e2005-04-16 15:20:36 -070011361/*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011362 * Load the Microcode
11363 *
11364 * Write the microcode image to RISC memory starting at address 0.
11365 *
11366 * The microcode is stored compressed in the following format:
11367 *
11368 * 254 word (508 byte) table indexed by byte code followed
11369 * by the following byte codes:
11370 *
11371 * 1-Byte Code:
11372 * 00: Emit word 0 in table.
11373 * 01: Emit word 1 in table.
11374 * .
11375 * FD: Emit word 253 in table.
11376 *
11377 * Multi-Byte Code:
11378 * FE WW WW: (3 byte code) Word to emit is the next word WW WW.
11379 * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW.
11380 *
11381 * Returns 0 or an error if the checksum doesn't match
11382 */
11383static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
11384 int memsize, int chksum)
11385{
11386 int i, j, end, len = 0;
11387 ADV_DCNT sum;
11388
11389 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
11390
11391 for (i = 253 * 2; i < size; i++) {
11392 if (buf[i] == 0xff) {
11393 unsigned short word = (buf[i + 3] << 8) | buf[i + 2];
11394 for (j = 0; j < buf[i + 1]; j++) {
11395 AdvWriteWordAutoIncLram(iop_base, word);
11396 len += 2;
11397 }
11398 i += 3;
11399 } else if (buf[i] == 0xfe) {
11400 unsigned short word = (buf[i + 2] << 8) | buf[i + 1];
11401 AdvWriteWordAutoIncLram(iop_base, word);
11402 i += 2;
11403 len += 2;
11404 } else {
11405 unsigned char off = buf[i] * 2;
11406 unsigned short word = (buf[off + 1] << 8) | buf[off];
11407 AdvWriteWordAutoIncLram(iop_base, word);
11408 len += 2;
11409 }
11410 }
11411
11412 end = len;
11413
11414 while (len < memsize) {
11415 AdvWriteWordAutoIncLram(iop_base, 0);
11416 len += 2;
11417 }
11418
11419 /* Verify the microcode checksum. */
11420 sum = 0;
11421 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0);
11422
11423 for (len = 0; len < end; len += 2) {
11424 sum += AdvReadWordAutoIncLram(iop_base);
11425 }
11426
11427 if (sum != chksum)
11428 return ASC_IERR_MCODE_CHKSUM;
11429
11430 return 0;
11431}
11432
11433/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070011434 * Initialize the ASC-3550.
11435 *
11436 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11437 *
11438 * For a non-fatal error return a warning code. If there are no warnings
11439 * then 0 is returned.
11440 *
11441 * Needed after initialization for error recovery.
11442 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011443static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011444{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011445 AdvPortAddr iop_base;
11446 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011447 int begin_addr;
11448 int end_addr;
11449 ushort code_sum;
11450 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011451 int i;
11452 ushort scsi_cfg1;
11453 uchar tid;
11454 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
11455 ushort wdtr_able = 0, sdtr_able, tagqng_able;
11456 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070011457
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011458 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011459 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011460 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011461
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011462 /*
11463 * The caller must set 'chip_type' to ADV_CHIP_ASC3550.
11464 */
11465 if (asc_dvc->chip_type != ADV_CHIP_ASC3550) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011466 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011467 return ADV_ERROR;
11468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011469
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011470 warn_code = 0;
11471 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011472
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011473 /*
11474 * Save the RISC memory BIOS region before writing the microcode.
11475 * The BIOS may already be loaded and using its RISC LRAM region
11476 * so its region must be saved and restored.
11477 *
11478 * Note: This code makes the assumption, which is currently true,
11479 * that a chip reset does not clear RISC LRAM.
11480 */
11481 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11482 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11483 bios_mem[i]);
11484 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011485
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011486 /*
11487 * Save current per TID negotiated values.
11488 */
11489 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) {
11490 ushort bios_version, major, minor;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011491
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011492 bios_version =
11493 bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2];
11494 major = (bios_version >> 12) & 0xF;
11495 minor = (bios_version >> 8) & 0xF;
11496 if (major < 3 || (major == 3 && minor == 1)) {
11497 /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */
11498 AdvReadWordLram(iop_base, 0x120, wdtr_able);
11499 } else {
11500 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11501 }
11502 }
11503 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11504 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
11505 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11506 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
11507 max_cmd[tid]);
11508 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011509
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011510 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
11511 _adv_asc3550_size, ADV_3550_MEMSIZE,
11512 _adv_asc3550_chksum);
11513 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011514 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011515
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011516 /*
11517 * Restore the RISC memory BIOS region.
11518 */
11519 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11520 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11521 bios_mem[i]);
11522 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011523
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011524 /*
11525 * Calculate and write the microcode code checksum to the microcode
11526 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
11527 */
11528 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
11529 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
11530 code_sum = 0;
11531 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
11532 for (word = begin_addr; word < end_addr; word += 2) {
11533 code_sum += AdvReadWordAutoIncLram(iop_base);
11534 }
11535 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011536
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011537 /*
11538 * Read and save microcode version and date.
11539 */
11540 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
11541 asc_dvc->cfg->mcode_date);
11542 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
11543 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011544
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011545 /*
11546 * Set the chip type to indicate the ASC3550.
11547 */
11548 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011549
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011550 /*
11551 * If the PCI Configuration Command Register "Parity Error Response
11552 * Control" Bit was clear (0), then set the microcode variable
11553 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
11554 * to ignore DMA parity errors.
11555 */
11556 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
11557 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
11558 word |= CONTROL_FLAG_IGNORE_PERR;
11559 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
11560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011561
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011562 /*
11563 * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO
11564 * threshold of 128 bytes. This register is only accessible to the host.
11565 */
11566 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
11567 START_CTL_EMFU | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011568
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011569 /*
11570 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040011571 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011572 * device reports it is capable of in Inquiry byte 7.
11573 *
11574 * If SCSI Bus Resets have been disabled, then directly set
11575 * SDTR and WDTR from the EEPROM configuration. This will allow
11576 * the BIOS and warm boot to work without a SCSI bus hang on
11577 * the Inquiry caused by host and target mismatched DTR values.
11578 * Without the SCSI Bus Reset, before an Inquiry a device can't
11579 * be assumed to be in Asynchronous, Narrow mode.
11580 */
11581 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
11582 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
11583 asc_dvc->wdtr_able);
11584 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
11585 asc_dvc->sdtr_able);
11586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011587
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011588 /*
11589 * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2,
11590 * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID
11591 * bitmask. These values determine the maximum SDTR speed negotiated
11592 * with a device.
11593 *
11594 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
11595 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
11596 * without determining here whether the device supports SDTR.
11597 *
11598 * 4-bit speed SDTR speed name
11599 * =========== ===============
11600 * 0000b (0x0) SDTR disabled
11601 * 0001b (0x1) 5 Mhz
11602 * 0010b (0x2) 10 Mhz
11603 * 0011b (0x3) 20 Mhz (Ultra)
11604 * 0100b (0x4) 40 Mhz (LVD/Ultra2)
11605 * 0101b (0x5) 80 Mhz (LVD2/Ultra3)
11606 * 0110b (0x6) Undefined
11607 * .
11608 * 1111b (0xF) Undefined
11609 */
11610 word = 0;
11611 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11612 if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) {
11613 /* Set Ultra speed for TID 'tid'. */
11614 word |= (0x3 << (4 * (tid % 4)));
11615 } else {
11616 /* Set Fast speed for TID 'tid'. */
11617 word |= (0x2 << (4 * (tid % 4)));
11618 }
11619 if (tid == 3) { /* Check if done with sdtr_speed1. */
11620 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word);
11621 word = 0;
11622 } else if (tid == 7) { /* Check if done with sdtr_speed2. */
11623 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word);
11624 word = 0;
11625 } else if (tid == 11) { /* Check if done with sdtr_speed3. */
11626 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word);
11627 word = 0;
11628 } else if (tid == 15) { /* Check if done with sdtr_speed4. */
11629 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word);
11630 /* End of loop. */
11631 }
11632 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011633
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011634 /*
11635 * Set microcode operating variable for the disconnect per TID bitmask.
11636 */
11637 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
11638 asc_dvc->cfg->disc_enable);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011639
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011640 /*
11641 * Set SCSI_CFG0 Microcode Default Value.
11642 *
11643 * The microcode will set the SCSI_CFG0 register using this value
11644 * after it is started below.
11645 */
11646 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
11647 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
11648 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011649
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011650 /*
11651 * Determine SCSI_CFG1 Microcode Default Value.
11652 *
11653 * The microcode will set the SCSI_CFG1 register using this value
11654 * after it is started below.
11655 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011656
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011657 /* Read current SCSI_CFG1 Register value. */
11658 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011659
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011660 /*
11661 * If all three connectors are in use, return an error.
11662 */
11663 if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 ||
11664 (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) {
11665 asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION;
11666 return ADV_ERROR;
11667 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011668
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011669 /*
11670 * If the internal narrow cable is reversed all of the SCSI_CTRL
11671 * register signals will be set. Check for and return an error if
11672 * this condition is found.
11673 */
11674 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
11675 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
11676 return ADV_ERROR;
11677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011678
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011679 /*
11680 * If this is a differential board and a single-ended device
11681 * is attached to one of the connectors, return an error.
11682 */
11683 if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) {
11684 asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE;
11685 return ADV_ERROR;
11686 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011687
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011688 /*
11689 * If automatic termination control is enabled, then set the
11690 * termination value based on a table listed in a_condor.h.
11691 *
11692 * If manual termination was specified with an EEPROM setting
11693 * then 'termination' was set-up in AdvInitFrom3550EEPROM() and
11694 * is ready to be 'ored' into SCSI_CFG1.
11695 */
11696 if (asc_dvc->cfg->termination == 0) {
11697 /*
11698 * The software always controls termination by setting TERM_CTL_SEL.
11699 * If TERM_CTL_SEL were set to 0, the hardware would set termination.
11700 */
11701 asc_dvc->cfg->termination |= TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011702
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011703 switch (scsi_cfg1 & CABLE_DETECT) {
11704 /* TERM_CTL_H: on, TERM_CTL_L: on */
11705 case 0x3:
11706 case 0x7:
11707 case 0xB:
11708 case 0xD:
11709 case 0xE:
11710 case 0xF:
11711 asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L);
11712 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011713
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011714 /* TERM_CTL_H: on, TERM_CTL_L: off */
11715 case 0x1:
11716 case 0x5:
11717 case 0x9:
11718 case 0xA:
11719 case 0xC:
11720 asc_dvc->cfg->termination |= TERM_CTL_H;
11721 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011722
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011723 /* TERM_CTL_H: off, TERM_CTL_L: off */
11724 case 0x2:
11725 case 0x6:
11726 break;
11727 }
11728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011729
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011730 /*
11731 * Clear any set TERM_CTL_H and TERM_CTL_L bits.
11732 */
11733 scsi_cfg1 &= ~TERM_CTL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011734
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011735 /*
11736 * Invert the TERM_CTL_H and TERM_CTL_L bits and then
11737 * set 'scsi_cfg1'. The TERM_POL bit does not need to be
11738 * referenced, because the hardware internally inverts
11739 * the Termination High and Low bits if TERM_POL is set.
11740 */
11741 scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011742
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011743 /*
11744 * Set SCSI_CFG1 Microcode Default Value
11745 *
11746 * Set filter value and possibly modified termination control
11747 * bits in the Microcode SCSI_CFG1 Register Value.
11748 *
11749 * The microcode will set the SCSI_CFG1 register using this value
11750 * after it is started below.
11751 */
11752 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1,
11753 FLTR_DISABLE | scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011754
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011755 /*
11756 * Set MEM_CFG Microcode Default Value
11757 *
11758 * The microcode will set the MEM_CFG register using this value
11759 * after it is started below.
11760 *
11761 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
11762 * are defined.
11763 *
11764 * ASC-3550 has 8KB internal memory.
11765 */
11766 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
11767 BIOS_EN | RAM_SZ_8KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011768
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011769 /*
11770 * Set SEL_MASK Microcode Default Value
11771 *
11772 * The microcode will set the SEL_MASK register using this value
11773 * after it is started below.
11774 */
11775 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
11776 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011777
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060011778 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011779
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011780 /*
11781 * Set-up the Host->RISC Initiator Command Queue (ICQ).
11782 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011783
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011784 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
11785 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
11786 return ADV_ERROR;
11787 }
11788 asc_dvc->carr_freelist = (ADV_CARR_T *)
11789 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011790
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011791 /*
11792 * The first command issued will be placed in the stopper carrier.
11793 */
11794 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011795
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011796 /*
11797 * Set RISC ICQ physical address start value.
11798 */
11799 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011800
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011801 /*
11802 * Set-up the RISC->Host Initiator Response Queue (IRQ).
11803 */
11804 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
11805 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
11806 return ADV_ERROR;
11807 }
11808 asc_dvc->carr_freelist = (ADV_CARR_T *)
11809 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011810
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011811 /*
11812 * The first command completed by the RISC will be placed in
11813 * the stopper.
11814 *
11815 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
11816 * completed the RISC will set the ASC_RQ_STOPPER bit.
11817 */
11818 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011819
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011820 /*
11821 * Set RISC IRQ physical address start value.
11822 */
11823 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
11824 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011825
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011826 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
11827 (ADV_INTR_ENABLE_HOST_INTR |
11828 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070011829
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011830 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
11831 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011832
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011833 /* finally, finally, gentlemen, start your engine */
11834 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070011835
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011836 /*
11837 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
11838 * Resets should be performed. The RISC has to be running
11839 * to issue a SCSI Bus Reset.
11840 */
11841 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
11842 /*
11843 * If the BIOS Signature is present in memory, restore the
11844 * BIOS Handshake Configuration Table and do not perform
11845 * a SCSI Bus Reset.
11846 */
11847 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
11848 0x55AA) {
11849 /*
11850 * Restore per TID negotiated values.
11851 */
11852 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11853 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11854 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
11855 tagqng_able);
11856 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11857 AdvWriteByteLram(iop_base,
11858 ASC_MC_NUMBER_OF_MAX_CMD + tid,
11859 max_cmd[tid]);
11860 }
11861 } else {
11862 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
11863 warn_code = ASC_WARN_BUSRESET_ERROR;
11864 }
11865 }
11866 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011867
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011868 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011869}
11870
11871/*
11872 * Initialize the ASC-38C0800.
11873 *
11874 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
11875 *
11876 * For a non-fatal error return a warning code. If there are no warnings
11877 * then 0 is returned.
11878 *
11879 * Needed after initialization for error recovery.
11880 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011881static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070011882{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011883 AdvPortAddr iop_base;
11884 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011885 int begin_addr;
11886 int end_addr;
11887 ushort code_sum;
11888 int word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011889 int i;
11890 ushort scsi_cfg1;
11891 uchar byte;
11892 uchar tid;
11893 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
11894 ushort wdtr_able, sdtr_able, tagqng_able;
11895 uchar max_cmd[ADV_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070011896
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011897 /* If there is already an error, don't continue. */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011898 if (asc_dvc->err_code != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011899 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011900
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011901 /*
11902 * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800.
11903 */
11904 if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) {
11905 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
11906 return ADV_ERROR;
11907 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011908
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011909 warn_code = 0;
11910 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070011911
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011912 /*
11913 * Save the RISC memory BIOS region before writing the microcode.
11914 * The BIOS may already be loaded and using its RISC LRAM region
11915 * so its region must be saved and restored.
11916 *
11917 * Note: This code makes the assumption, which is currently true,
11918 * that a chip reset does not clear RISC LRAM.
11919 */
11920 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
11921 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
11922 bios_mem[i]);
11923 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011924
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011925 /*
11926 * Save current per TID negotiated values.
11927 */
11928 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
11929 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
11930 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
11931 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
11932 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
11933 max_cmd[tid]);
11934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011935
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011936 /*
11937 * RAM BIST (RAM Built-In Self Test)
11938 *
11939 * Address : I/O base + offset 0x38h register (byte).
11940 * Function: Bit 7-6(RW) : RAM mode
11941 * Normal Mode : 0x00
11942 * Pre-test Mode : 0x40
11943 * RAM Test Mode : 0x80
11944 * Bit 5 : unused
11945 * Bit 4(RO) : Done bit
11946 * Bit 3-0(RO) : Status
11947 * Host Error : 0x08
11948 * Int_RAM Error : 0x04
11949 * RISC Error : 0x02
11950 * SCSI Error : 0x01
11951 * No Error : 0x00
11952 *
11953 * Note: RAM BIST code should be put right here, before loading the
11954 * microcode and after saving the RISC memory BIOS region.
11955 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011956
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011957 /*
11958 * LRAM Pre-test
11959 *
11960 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
11961 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
11962 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
11963 * to NORMAL_MODE, return an error too.
11964 */
11965 for (i = 0; i < 2; i++) {
11966 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060011967 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011968 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
11969 if ((byte & RAM_TEST_DONE) == 0
11970 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011971 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011972 return ADV_ERROR;
11973 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011974
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011975 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060011976 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011977 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
11978 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011979 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011980 return ADV_ERROR;
11981 }
11982 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070011983
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011984 /*
11985 * LRAM Test - It takes about 1.5 ms to run through the test.
11986 *
11987 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
11988 * If Done bit not set or Status not 0, save register byte, set the
11989 * err_code, and return an error.
11990 */
11991 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060011992 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070011993
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011994 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
11995 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
11996 /* Get here if Done bit not set or Status not 0. */
11997 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060011998 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040011999 return ADV_ERROR;
12000 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012001
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012002 /* We need to reset back to normal mode after LRAM test passes. */
12003 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012004
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012005 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
12006 _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
12007 _adv_asc38C0800_chksum);
12008 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012009 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012010
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012011 /*
12012 * Restore the RISC memory BIOS region.
12013 */
12014 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12015 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12016 bios_mem[i]);
12017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012018
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012019 /*
12020 * Calculate and write the microcode code checksum to the microcode
12021 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12022 */
12023 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12024 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12025 code_sum = 0;
12026 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12027 for (word = begin_addr; word < end_addr; word += 2) {
12028 code_sum += AdvReadWordAutoIncLram(iop_base);
12029 }
12030 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012031
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012032 /*
12033 * Read microcode version and date.
12034 */
12035 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12036 asc_dvc->cfg->mcode_date);
12037 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12038 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012039
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012040 /*
12041 * Set the chip type to indicate the ASC38C0800.
12042 */
12043 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012044
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012045 /*
12046 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12047 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12048 * cable detection and then we are able to read C_DET[3:0].
12049 *
12050 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12051 * Microcode Default Value' section below.
12052 */
12053 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12054 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12055 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012056
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012057 /*
12058 * If the PCI Configuration Command Register "Parity Error Response
12059 * Control" Bit was clear (0), then set the microcode variable
12060 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12061 * to ignore DMA parity errors.
12062 */
12063 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12064 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12065 word |= CONTROL_FLAG_IGNORE_PERR;
12066 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12067 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012068
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012069 /*
12070 * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2]
12071 * bits for the default FIFO threshold.
12072 *
12073 * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes.
12074 *
12075 * For DMA Errata #4 set the BC_THRESH_ENB bit.
12076 */
12077 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12078 BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH |
12079 READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012080
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012081 /*
12082 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012083 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012084 * device reports it is capable of in Inquiry byte 7.
12085 *
12086 * If SCSI Bus Resets have been disabled, then directly set
12087 * SDTR and WDTR from the EEPROM configuration. This will allow
12088 * the BIOS and warm boot to work without a SCSI bus hang on
12089 * the Inquiry caused by host and target mismatched DTR values.
12090 * Without the SCSI Bus Reset, before an Inquiry a device can't
12091 * be assumed to be in Asynchronous, Narrow mode.
12092 */
12093 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12094 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12095 asc_dvc->wdtr_able);
12096 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12097 asc_dvc->sdtr_able);
12098 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012099
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012100 /*
12101 * Set microcode operating variables for DISC and SDTR_SPEED1,
12102 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12103 * configuration values.
12104 *
12105 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12106 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12107 * without determining here whether the device supports SDTR.
12108 */
12109 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12110 asc_dvc->cfg->disc_enable);
12111 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12112 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12113 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12114 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012115
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012116 /*
12117 * Set SCSI_CFG0 Microcode Default Value.
12118 *
12119 * The microcode will set the SCSI_CFG0 register using this value
12120 * after it is started below.
12121 */
12122 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12123 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12124 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012125
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012126 /*
12127 * Determine SCSI_CFG1 Microcode Default Value.
12128 *
12129 * The microcode will set the SCSI_CFG1 register using this value
12130 * after it is started below.
12131 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012132
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012133 /* Read current SCSI_CFG1 Register value. */
12134 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012135
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012136 /*
12137 * If the internal narrow cable is reversed all of the SCSI_CTRL
12138 * register signals will be set. Check for and return an error if
12139 * this condition is found.
12140 */
12141 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12142 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12143 return ADV_ERROR;
12144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012145
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012146 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012147 * All kind of combinations of devices attached to one of four
12148 * connectors are acceptable except HVD device attached. For example,
12149 * LVD device can be attached to SE connector while SE device attached
12150 * to LVD connector. If LVD device attached to SE connector, it only
12151 * runs up to Ultra speed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012152 *
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012153 * If an HVD device is attached to one of LVD connectors, return an
12154 * error. However, there is no way to detect HVD device attached to
12155 * SE connectors.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012156 */
12157 if (scsi_cfg1 & HVD) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012158 asc_dvc->err_code = ASC_IERR_HVD_DEVICE;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012159 return ADV_ERROR;
12160 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012161
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012162 /*
12163 * If either SE or LVD automatic termination control is enabled, then
12164 * set the termination value based on a table listed in a_condor.h.
12165 *
12166 * If manual termination was specified with an EEPROM setting then
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012167 * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready
12168 * to be 'ored' into SCSI_CFG1.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012169 */
12170 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
12171 /* SE automatic termination control is enabled. */
12172 switch (scsi_cfg1 & C_DET_SE) {
12173 /* TERM_SE_HI: on, TERM_SE_LO: on */
12174 case 0x1:
12175 case 0x2:
12176 case 0x3:
12177 asc_dvc->cfg->termination |= TERM_SE;
12178 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012179
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012180 /* TERM_SE_HI: on, TERM_SE_LO: off */
12181 case 0x0:
12182 asc_dvc->cfg->termination |= TERM_SE_HI;
12183 break;
12184 }
12185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012186
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012187 if ((asc_dvc->cfg->termination & TERM_LVD) == 0) {
12188 /* LVD automatic termination control is enabled. */
12189 switch (scsi_cfg1 & C_DET_LVD) {
12190 /* TERM_LVD_HI: on, TERM_LVD_LO: on */
12191 case 0x4:
12192 case 0x8:
12193 case 0xC:
12194 asc_dvc->cfg->termination |= TERM_LVD;
12195 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012196
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012197 /* TERM_LVD_HI: off, TERM_LVD_LO: off */
12198 case 0x0:
12199 break;
12200 }
12201 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012202
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012203 /*
12204 * Clear any set TERM_SE and TERM_LVD bits.
12205 */
12206 scsi_cfg1 &= (~TERM_SE & ~TERM_LVD);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012207
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012208 /*
12209 * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'.
12210 */
12211 scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012212
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012213 /*
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012214 * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE
12215 * bits and set possibly modified termination control bits in the
12216 * Microcode SCSI_CFG1 Register Value.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012217 */
12218 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012219
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012220 /*
12221 * Set SCSI_CFG1 Microcode Default Value
12222 *
12223 * Set possibly modified termination control and reset DIS_TERM_DRV
12224 * bits in the Microcode SCSI_CFG1 Register Value.
12225 *
12226 * The microcode will set the SCSI_CFG1 register using this value
12227 * after it is started below.
12228 */
12229 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012230
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012231 /*
12232 * Set MEM_CFG Microcode Default Value
12233 *
12234 * The microcode will set the MEM_CFG register using this value
12235 * after it is started below.
12236 *
12237 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12238 * are defined.
12239 *
12240 * ASC-38C0800 has 16KB internal memory.
12241 */
12242 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12243 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012244
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012245 /*
12246 * Set SEL_MASK Microcode Default Value
12247 *
12248 * The microcode will set the SEL_MASK register using this value
12249 * after it is started below.
12250 */
12251 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12252 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012253
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012254 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012255
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012256 /*
12257 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12258 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012259
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012260 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12261 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12262 return ADV_ERROR;
12263 }
12264 asc_dvc->carr_freelist = (ADV_CARR_T *)
12265 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012266
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012267 /*
12268 * The first command issued will be placed in the stopper carrier.
12269 */
12270 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012271
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012272 /*
12273 * Set RISC ICQ physical address start value.
12274 * carr_pa is LE, must be native before write
12275 */
12276 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012277
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012278 /*
12279 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12280 */
12281 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12282 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12283 return ADV_ERROR;
12284 }
12285 asc_dvc->carr_freelist = (ADV_CARR_T *)
12286 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012287
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012288 /*
12289 * The first command completed by the RISC will be placed in
12290 * the stopper.
12291 *
12292 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12293 * completed the RISC will set the ASC_RQ_STOPPER bit.
12294 */
12295 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012296
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012297 /*
12298 * Set RISC IRQ physical address start value.
12299 *
12300 * carr_pa is LE, must be native before write *
12301 */
12302 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12303 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012304
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012305 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12306 (ADV_INTR_ENABLE_HOST_INTR |
12307 ADV_INTR_ENABLE_GLOBAL_INTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012308
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012309 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12310 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012311
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012312 /* finally, finally, gentlemen, start your engine */
12313 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012314
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012315 /*
12316 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12317 * Resets should be performed. The RISC has to be running
12318 * to issue a SCSI Bus Reset.
12319 */
12320 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12321 /*
12322 * If the BIOS Signature is present in memory, restore the
12323 * BIOS Handshake Configuration Table and do not perform
12324 * a SCSI Bus Reset.
12325 */
12326 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12327 0x55AA) {
12328 /*
12329 * Restore per TID negotiated values.
12330 */
12331 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12332 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12333 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12334 tagqng_able);
12335 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
12336 AdvWriteByteLram(iop_base,
12337 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12338 max_cmd[tid]);
12339 }
12340 } else {
12341 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12342 warn_code = ASC_WARN_BUSRESET_ERROR;
12343 }
12344 }
12345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012346
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012347 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012348}
12349
12350/*
12351 * Initialize the ASC-38C1600.
12352 *
12353 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
12354 *
12355 * For a non-fatal error return a warning code. If there are no warnings
12356 * then 0 is returned.
12357 *
12358 * Needed after initialization for error recovery.
12359 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012360static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012361{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012362 AdvPortAddr iop_base;
12363 ushort warn_code;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012364 int begin_addr;
12365 int end_addr;
12366 ushort code_sum;
12367 long word;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012368 int i;
12369 ushort scsi_cfg1;
12370 uchar byte;
12371 uchar tid;
12372 ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
12373 ushort wdtr_able, sdtr_able, ppr_able, tagqng_able;
12374 uchar max_cmd[ASC_MAX_TID + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -070012375
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012376 /* If there is already an error, don't continue. */
12377 if (asc_dvc->err_code != 0) {
12378 return ADV_ERROR;
12379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012380
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012381 /*
12382 * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600.
12383 */
12384 if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) {
12385 asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE;
12386 return ADV_ERROR;
12387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012388
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012389 warn_code = 0;
12390 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012391
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012392 /*
12393 * Save the RISC memory BIOS region before writing the microcode.
12394 * The BIOS may already be loaded and using its RISC LRAM region
12395 * so its region must be saved and restored.
12396 *
12397 * Note: This code makes the assumption, which is currently true,
12398 * that a chip reset does not clear RISC LRAM.
12399 */
12400 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12401 AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12402 bios_mem[i]);
12403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012404
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012405 /*
12406 * Save current per TID negotiated values.
12407 */
12408 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12409 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12410 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
12411 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
12412 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12413 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
12414 max_cmd[tid]);
12415 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012416
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012417 /*
12418 * RAM BIST (Built-In Self Test)
12419 *
12420 * Address : I/O base + offset 0x38h register (byte).
12421 * Function: Bit 7-6(RW) : RAM mode
12422 * Normal Mode : 0x00
12423 * Pre-test Mode : 0x40
12424 * RAM Test Mode : 0x80
12425 * Bit 5 : unused
12426 * Bit 4(RO) : Done bit
12427 * Bit 3-0(RO) : Status
12428 * Host Error : 0x08
12429 * Int_RAM Error : 0x04
12430 * RISC Error : 0x02
12431 * SCSI Error : 0x01
12432 * No Error : 0x00
12433 *
12434 * Note: RAM BIST code should be put right here, before loading the
12435 * microcode and after saving the RISC memory BIOS region.
12436 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012437
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012438 /*
12439 * LRAM Pre-test
12440 *
12441 * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds.
12442 * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return
12443 * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset
12444 * to NORMAL_MODE, return an error too.
12445 */
12446 for (i = 0; i < 2; i++) {
12447 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060012448 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012449 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12450 if ((byte & RAM_TEST_DONE) == 0
12451 || (byte & 0x0F) != PRE_TEST_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012452 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012453 return ADV_ERROR;
12454 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012455
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012456 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060012457 mdelay(10); /* Wait for 10ms before reading back. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012458 if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST)
12459 != NORMAL_VALUE) {
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012460 asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012461 return ADV_ERROR;
12462 }
12463 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012464
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012465 /*
12466 * LRAM Test - It takes about 1.5 ms to run through the test.
12467 *
12468 * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds.
12469 * If Done bit not set or Status not 0, save register byte, set the
12470 * err_code, and return an error.
12471 */
12472 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060012473 mdelay(10); /* Wait for 10ms before checking status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070012474
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012475 byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST);
12476 if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) {
12477 /* Get here if Done bit not set or Status not 0. */
12478 asc_dvc->bist_err_code = byte; /* for BIOS display message */
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012479 asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012480 return ADV_ERROR;
12481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012482
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012483 /* We need to reset back to normal mode after LRAM test passes. */
12484 AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012485
Matthew Wilcoxb9d96612007-09-09 08:56:28 -060012486 asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
12487 _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
12488 _adv_asc38C1600_chksum);
12489 if (asc_dvc->err_code)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012490 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012491
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012492 /*
12493 * Restore the RISC memory BIOS region.
12494 */
12495 for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) {
12496 AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i),
12497 bios_mem[i]);
12498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012499
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012500 /*
12501 * Calculate and write the microcode code checksum to the microcode
12502 * code checksum location ASC_MC_CODE_CHK_SUM (0x2C).
12503 */
12504 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr);
12505 AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr);
12506 code_sum = 0;
12507 AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr);
12508 for (word = begin_addr; word < end_addr; word += 2) {
12509 code_sum += AdvReadWordAutoIncLram(iop_base);
12510 }
12511 AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012512
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012513 /*
12514 * Read microcode version and date.
12515 */
12516 AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE,
12517 asc_dvc->cfg->mcode_date);
12518 AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM,
12519 asc_dvc->cfg->mcode_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012520
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012521 /*
12522 * Set the chip type to indicate the ASC38C1600.
12523 */
12524 AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012525
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012526 /*
12527 * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register.
12528 * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current
12529 * cable detection and then we are able to read C_DET[3:0].
12530 *
12531 * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1
12532 * Microcode Default Value' section below.
12533 */
12534 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
12535 AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1,
12536 scsi_cfg1 | DIS_TERM_DRV);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012537
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012538 /*
12539 * If the PCI Configuration Command Register "Parity Error Response
12540 * Control" Bit was clear (0), then set the microcode variable
12541 * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode
12542 * to ignore DMA parity errors.
12543 */
12544 if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) {
12545 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12546 word |= CONTROL_FLAG_IGNORE_PERR;
12547 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12548 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012549
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012550 /*
12551 * If the BIOS control flag AIPP (Asynchronous Information
12552 * Phase Protection) disable bit is not set, then set the firmware
12553 * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable
12554 * AIPP checking and encoding.
12555 */
12556 if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) {
12557 AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12558 word |= CONTROL_FLAG_ENABLE_AIPP;
12559 AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word);
12560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012561
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012562 /*
12563 * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4],
12564 * and START_CTL_TH [3:2].
12565 */
12566 AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0,
12567 FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012568
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012569 /*
12570 * Microcode operating variables for WDTR, SDTR, and command tag
Matthew Wilcox47d853c2007-07-26 11:41:33 -040012571 * queuing will be set in slave_configure() based on what a
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012572 * device reports it is capable of in Inquiry byte 7.
12573 *
12574 * If SCSI Bus Resets have been disabled, then directly set
12575 * SDTR and WDTR from the EEPROM configuration. This will allow
12576 * the BIOS and warm boot to work without a SCSI bus hang on
12577 * the Inquiry caused by host and target mismatched DTR values.
12578 * Without the SCSI Bus Reset, before an Inquiry a device can't
12579 * be assumed to be in Asynchronous, Narrow mode.
12580 */
12581 if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) {
12582 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE,
12583 asc_dvc->wdtr_able);
12584 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE,
12585 asc_dvc->sdtr_able);
12586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012587
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012588 /*
12589 * Set microcode operating variables for DISC and SDTR_SPEED1,
12590 * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM
12591 * configuration values.
12592 *
12593 * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2,
12594 * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them
12595 * without determining here whether the device supports SDTR.
12596 */
12597 AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE,
12598 asc_dvc->cfg->disc_enable);
12599 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1);
12600 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2);
12601 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3);
12602 AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012603
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012604 /*
12605 * Set SCSI_CFG0 Microcode Default Value.
12606 *
12607 * The microcode will set the SCSI_CFG0 register using this value
12608 * after it is started below.
12609 */
12610 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0,
12611 PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN |
12612 asc_dvc->chip_scsi_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012613
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012614 /*
12615 * Calculate SCSI_CFG1 Microcode Default Value.
12616 *
12617 * The microcode will set the SCSI_CFG1 register using this value
12618 * after it is started below.
12619 *
12620 * Each ASC-38C1600 function has only two cable detect bits.
12621 * The bus mode override bits are in IOPB_SOFT_OVER_WR.
12622 */
12623 scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012624
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012625 /*
12626 * If the cable is reversed all of the SCSI_CTRL register signals
12627 * will be set. Check for and return an error if this condition is
12628 * found.
12629 */
12630 if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) {
12631 asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE;
12632 return ADV_ERROR;
12633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012634
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012635 /*
12636 * Each ASC-38C1600 function has two connectors. Only an HVD device
12637 * can not be connected to either connector. An LVD device or SE device
12638 * may be connected to either connecor. If an SE device is connected,
12639 * then at most Ultra speed (20 Mhz) can be used on both connectors.
12640 *
12641 * If an HVD device is attached, return an error.
12642 */
12643 if (scsi_cfg1 & HVD) {
12644 asc_dvc->err_code |= ASC_IERR_HVD_DEVICE;
12645 return ADV_ERROR;
12646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012647
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012648 /*
12649 * Each function in the ASC-38C1600 uses only the SE cable detect and
12650 * termination because there are two connectors for each function. Each
12651 * function may use either LVD or SE mode. Corresponding the SE automatic
12652 * termination control EEPROM bits are used for each function. Each
12653 * function has its own EEPROM. If SE automatic control is enabled for
12654 * the function, then set the termination value based on a table listed
12655 * in a_condor.h.
12656 *
12657 * If manual termination is specified in the EEPROM for the function,
12658 * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is
12659 * ready to be 'ored' into SCSI_CFG1.
12660 */
12661 if ((asc_dvc->cfg->termination & TERM_SE) == 0) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060012662 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012663 /* SE automatic termination control is enabled. */
12664 switch (scsi_cfg1 & C_DET_SE) {
12665 /* TERM_SE_HI: on, TERM_SE_LO: on */
12666 case 0x1:
12667 case 0x2:
12668 case 0x3:
12669 asc_dvc->cfg->termination |= TERM_SE;
12670 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012671
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012672 case 0x0:
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060012673 if (PCI_FUNC(pdev->devfn) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012674 /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */
12675 } else {
12676 /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */
12677 asc_dvc->cfg->termination |= TERM_SE_HI;
12678 }
12679 break;
12680 }
12681 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012682
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012683 /*
12684 * Clear any set TERM_SE bits.
12685 */
12686 scsi_cfg1 &= ~TERM_SE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012687
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012688 /*
12689 * Invert the TERM_SE bits and then set 'scsi_cfg1'.
12690 */
12691 scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012692
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012693 /*
12694 * Clear Big Endian and Terminator Polarity bits and set possibly
12695 * modified termination control bits in the Microcode SCSI_CFG1
12696 * Register Value.
12697 *
12698 * Big Endian bit is not used even on big endian machines.
12699 */
12700 scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012701
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012702 /*
12703 * Set SCSI_CFG1 Microcode Default Value
12704 *
12705 * Set possibly modified termination control bits in the Microcode
12706 * SCSI_CFG1 Register Value.
12707 *
12708 * The microcode will set the SCSI_CFG1 register using this value
12709 * after it is started below.
12710 */
12711 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012712
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012713 /*
12714 * Set MEM_CFG Microcode Default Value
12715 *
12716 * The microcode will set the MEM_CFG register using this value
12717 * after it is started below.
12718 *
12719 * MEM_CFG may be accessed as a word or byte, but only bits 0-7
12720 * are defined.
12721 *
12722 * ASC-38C1600 has 32KB internal memory.
12723 *
12724 * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come
12725 * out a special 16K Adv Library and Microcode version. After the issue
12726 * resolved, we should turn back to the 32K support. Both a_condor.h and
12727 * mcode.sas files also need to be updated.
12728 *
12729 * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12730 * BIOS_EN | RAM_SZ_32KB);
12731 */
12732 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG,
12733 BIOS_EN | RAM_SZ_16KB);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012734
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012735 /*
12736 * Set SEL_MASK Microcode Default Value
12737 *
12738 * The microcode will set the SEL_MASK register using this value
12739 * after it is started below.
12740 */
12741 AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK,
12742 ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012743
Matthew Wilcoxa9f4a592007-09-09 08:56:27 -060012744 AdvBuildCarrierFreelist(asc_dvc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012745
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012746 /*
12747 * Set-up the Host->RISC Initiator Command Queue (ICQ).
12748 */
12749 if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) {
12750 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12751 return ADV_ERROR;
12752 }
12753 asc_dvc->carr_freelist = (ADV_CARR_T *)
12754 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012755
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012756 /*
12757 * The first command issued will be placed in the stopper carrier.
12758 */
12759 asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012760
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012761 /*
12762 * Set RISC ICQ physical address start value. Initialize the
12763 * COMMA register to the same value otherwise the RISC will
12764 * prematurely detect a command is available.
12765 */
12766 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa);
12767 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
12768 le32_to_cpu(asc_dvc->icq_sp->carr_pa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012769
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012770 /*
12771 * Set-up the RISC->Host Initiator Response Queue (IRQ).
12772 */
12773 if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) {
12774 asc_dvc->err_code |= ASC_IERR_NO_CARRIER;
12775 return ADV_ERROR;
12776 }
12777 asc_dvc->carr_freelist = (ADV_CARR_T *)
12778 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012779
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012780 /*
12781 * The first command completed by the RISC will be placed in
12782 * the stopper.
12783 *
12784 * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is
12785 * completed the RISC will set the ASC_RQ_STOPPER bit.
12786 */
12787 asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012788
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012789 /*
12790 * Set RISC IRQ physical address start value.
12791 */
12792 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa);
12793 asc_dvc->carr_pending_cnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012794
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012795 AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES,
12796 (ADV_INTR_ENABLE_HOST_INTR |
12797 ADV_INTR_ENABLE_GLOBAL_INTR));
12798 AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word);
12799 AdvWriteWordRegister(iop_base, IOPW_PC, word);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012800
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012801 /* finally, finally, gentlemen, start your engine */
12802 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012803
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012804 /*
12805 * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus
12806 * Resets should be performed. The RISC has to be running
12807 * to issue a SCSI Bus Reset.
12808 */
12809 if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) {
12810 /*
12811 * If the BIOS Signature is present in memory, restore the
12812 * per TID microcode operating variables.
12813 */
12814 if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] ==
12815 0x55AA) {
12816 /*
12817 * Restore per TID negotiated values.
12818 */
12819 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
12820 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
12821 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
12822 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE,
12823 tagqng_able);
12824 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
12825 AdvWriteByteLram(iop_base,
12826 ASC_MC_NUMBER_OF_MAX_CMD + tid,
12827 max_cmd[tid]);
12828 }
12829 } else {
12830 if (AdvResetSB(asc_dvc) != ADV_TRUE) {
12831 warn_code = ASC_WARN_BUSRESET_ERROR;
12832 }
12833 }
12834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012835
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012836 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012837}
12838
12839/*
12840 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12841 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12842 * all of this is done.
12843 *
12844 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12845 *
12846 * For a non-fatal error return a warning code. If there are no warnings
12847 * then 0 is returned.
12848 *
12849 * Note: Chip is stopped on entry.
12850 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060012851static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070012852{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012853 AdvPortAddr iop_base;
12854 ushort warn_code;
12855 ADVEEP_3550_CONFIG eep_config;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012856
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012857 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012858
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012859 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012860
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012861 /*
12862 * Read the board's EEPROM configuration.
12863 *
12864 * Set default values if a bad checksum is found.
12865 */
12866 if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) {
12867 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012868
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012869 /*
12870 * Set EEPROM default values.
12871 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012872 memcpy(&eep_config, &Default_3550_EEPROM_Config,
12873 sizeof(ADVEEP_3550_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070012874
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012875 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040012876 * Assume the 6 byte board serial number that was read from
12877 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012878 */
12879 eep_config.serial_number_word3 =
12880 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012881
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012882 eep_config.serial_number_word2 =
12883 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012884
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012885 eep_config.serial_number_word1 =
12886 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070012887
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012888 AdvSet3550EEPConfig(iop_base, &eep_config);
12889 }
12890 /*
12891 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
12892 * EEPROM configuration that was read.
12893 *
12894 * This is the mapping of EEPROM fields to Adv Library fields.
12895 */
12896 asc_dvc->wdtr_able = eep_config.wdtr_able;
12897 asc_dvc->sdtr_able = eep_config.sdtr_able;
12898 asc_dvc->ultra_able = eep_config.ultra_able;
12899 asc_dvc->tagqng_able = eep_config.tagqng_able;
12900 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
12901 asc_dvc->max_host_qng = eep_config.max_host_qng;
12902 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
12903 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
12904 asc_dvc->start_motor = eep_config.start_motor;
12905 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
12906 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
12907 asc_dvc->no_scam = eep_config.scam_tolerant;
12908 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
12909 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
12910 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012911
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012912 /*
12913 * Set the host maximum queuing (max. 253, min. 16) and the per device
12914 * maximum queuing (max. 63, min. 4).
12915 */
12916 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
12917 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12918 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
12919 /* If the value is zero, assume it is uninitialized. */
12920 if (eep_config.max_host_qng == 0) {
12921 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
12922 } else {
12923 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
12924 }
12925 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012926
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012927 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
12928 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
12929 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
12930 /* If the value is zero, assume it is uninitialized. */
12931 if (eep_config.max_dvc_qng == 0) {
12932 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
12933 } else {
12934 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
12935 }
12936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012937
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012938 /*
12939 * If 'max_dvc_qng' is greater than 'max_host_qng', then
12940 * set 'max_dvc_qng' to 'max_host_qng'.
12941 */
12942 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
12943 eep_config.max_dvc_qng = eep_config.max_host_qng;
12944 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012945
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012946 /*
12947 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
12948 * values based on possibly adjusted EEPROM values.
12949 */
12950 asc_dvc->max_host_qng = eep_config.max_host_qng;
12951 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012952
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012953 /*
12954 * If the EEPROM 'termination' field is set to automatic (0), then set
12955 * the ADV_DVC_CFG 'termination' field to automatic also.
12956 *
12957 * If the termination is specified with a non-zero 'termination'
12958 * value check that a legal value is set and set the ADV_DVC_CFG
12959 * 'termination' field appropriately.
12960 */
12961 if (eep_config.termination == 0) {
12962 asc_dvc->cfg->termination = 0; /* auto termination */
12963 } else {
12964 /* Enable manual control with low off / high off. */
12965 if (eep_config.termination == 1) {
12966 asc_dvc->cfg->termination = TERM_CTL_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012967
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012968 /* Enable manual control with low off / high on. */
12969 } else if (eep_config.termination == 2) {
12970 asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012971
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012972 /* Enable manual control with low on / high on. */
12973 } else if (eep_config.termination == 3) {
12974 asc_dvc->cfg->termination =
12975 TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L;
12976 } else {
12977 /*
12978 * The EEPROM 'termination' field contains a bad value. Use
12979 * automatic termination instead.
12980 */
12981 asc_dvc->cfg->termination = 0;
12982 warn_code |= ASC_WARN_EEPROM_TERMINATION;
12983 }
12984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070012985
Matthew Wilcox27c868c2007-07-26 10:56:23 -040012986 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070012987}
12988
12989/*
12990 * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and
12991 * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while
12992 * all of this is done.
12993 *
12994 * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR.
12995 *
12996 * For a non-fatal error return a warning code. If there are no warnings
12997 * then 0 is returned.
12998 *
12999 * Note: Chip is stopped on entry.
13000 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013001static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013002{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013003 AdvPortAddr iop_base;
13004 ushort warn_code;
13005 ADVEEP_38C0800_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013006 uchar tid, termination;
13007 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013008
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013009 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013010
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013011 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013012
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013013 /*
13014 * Read the board's EEPROM configuration.
13015 *
13016 * Set default values if a bad checksum is found.
13017 */
13018 if (AdvGet38C0800EEPConfig(iop_base, &eep_config) !=
13019 eep_config.check_sum) {
13020 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013021
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013022 /*
13023 * Set EEPROM default values.
13024 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013025 memcpy(&eep_config, &Default_38C0800_EEPROM_Config,
13026 sizeof(ADVEEP_38C0800_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013027
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013028 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013029 * Assume the 6 byte board serial number that was read from
13030 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013031 */
13032 eep_config.serial_number_word3 =
13033 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013034
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013035 eep_config.serial_number_word2 =
13036 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013037
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013038 eep_config.serial_number_word1 =
13039 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013040
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013041 AdvSet38C0800EEPConfig(iop_base, &eep_config);
13042 }
13043 /*
13044 * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the
13045 * EEPROM configuration that was read.
13046 *
13047 * This is the mapping of EEPROM fields to Adv Library fields.
13048 */
13049 asc_dvc->wdtr_able = eep_config.wdtr_able;
13050 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13051 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13052 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13053 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13054 asc_dvc->tagqng_able = eep_config.tagqng_able;
13055 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13056 asc_dvc->max_host_qng = eep_config.max_host_qng;
13057 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13058 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID);
13059 asc_dvc->start_motor = eep_config.start_motor;
13060 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13061 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13062 asc_dvc->no_scam = eep_config.scam_tolerant;
13063 asc_dvc->cfg->serial1 = eep_config.serial_number_word1;
13064 asc_dvc->cfg->serial2 = eep_config.serial_number_word2;
13065 asc_dvc->cfg->serial3 = eep_config.serial_number_word3;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013066
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013067 /*
13068 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13069 * are set, then set an 'sdtr_able' bit for it.
13070 */
13071 asc_dvc->sdtr_able = 0;
13072 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13073 if (tid == 0) {
13074 sdtr_speed = asc_dvc->sdtr_speed1;
13075 } else if (tid == 4) {
13076 sdtr_speed = asc_dvc->sdtr_speed2;
13077 } else if (tid == 8) {
13078 sdtr_speed = asc_dvc->sdtr_speed3;
13079 } else if (tid == 12) {
13080 sdtr_speed = asc_dvc->sdtr_speed4;
13081 }
13082 if (sdtr_speed & ADV_MAX_TID) {
13083 asc_dvc->sdtr_able |= (1 << tid);
13084 }
13085 sdtr_speed >>= 4;
13086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013087
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013088 /*
13089 * Set the host maximum queuing (max. 253, min. 16) and the per device
13090 * maximum queuing (max. 63, min. 4).
13091 */
13092 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13093 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13094 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13095 /* If the value is zero, assume it is uninitialized. */
13096 if (eep_config.max_host_qng == 0) {
13097 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13098 } else {
13099 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13100 }
13101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013102
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013103 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13104 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13105 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13106 /* If the value is zero, assume it is uninitialized. */
13107 if (eep_config.max_dvc_qng == 0) {
13108 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13109 } else {
13110 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13111 }
13112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013113
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013114 /*
13115 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13116 * set 'max_dvc_qng' to 'max_host_qng'.
13117 */
13118 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13119 eep_config.max_dvc_qng = eep_config.max_host_qng;
13120 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013121
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013122 /*
13123 * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng'
13124 * values based on possibly adjusted EEPROM values.
13125 */
13126 asc_dvc->max_host_qng = eep_config.max_host_qng;
13127 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013128
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013129 /*
13130 * If the EEPROM 'termination' field is set to automatic (0), then set
13131 * the ADV_DVC_CFG 'termination' field to automatic also.
13132 *
13133 * If the termination is specified with a non-zero 'termination'
13134 * value check that a legal value is set and set the ADV_DVC_CFG
13135 * 'termination' field appropriately.
13136 */
13137 if (eep_config.termination_se == 0) {
13138 termination = 0; /* auto termination for SE */
13139 } else {
13140 /* Enable manual control with low off / high off. */
13141 if (eep_config.termination_se == 1) {
13142 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013143
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013144 /* Enable manual control with low off / high on. */
13145 } else if (eep_config.termination_se == 2) {
13146 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013147
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013148 /* Enable manual control with low on / high on. */
13149 } else if (eep_config.termination_se == 3) {
13150 termination = TERM_SE;
13151 } else {
13152 /*
13153 * The EEPROM 'termination_se' field contains a bad value.
13154 * Use automatic termination instead.
13155 */
13156 termination = 0;
13157 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13158 }
13159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013160
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013161 if (eep_config.termination_lvd == 0) {
13162 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13163 } else {
13164 /* Enable manual control with low off / high off. */
13165 if (eep_config.termination_lvd == 1) {
13166 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013167
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013168 /* Enable manual control with low off / high on. */
13169 } else if (eep_config.termination_lvd == 2) {
13170 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013171
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013172 /* Enable manual control with low on / high on. */
13173 } else if (eep_config.termination_lvd == 3) {
13174 asc_dvc->cfg->termination = termination | TERM_LVD;
13175 } else {
13176 /*
13177 * The EEPROM 'termination_lvd' field contains a bad value.
13178 * Use automatic termination instead.
13179 */
13180 asc_dvc->cfg->termination = termination;
13181 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13182 }
13183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013184
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013185 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013186}
13187
13188/*
13189 * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and
13190 * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while
13191 * all of this is done.
13192 *
13193 * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR.
13194 *
13195 * For a non-fatal error return a warning code. If there are no warnings
13196 * then 0 is returned.
13197 *
13198 * Note: Chip is stopped on entry.
13199 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013200static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013201{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013202 AdvPortAddr iop_base;
13203 ushort warn_code;
13204 ADVEEP_38C1600_CONFIG eep_config;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013205 uchar tid, termination;
13206 ushort sdtr_speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013207
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013208 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013209
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013210 warn_code = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013211
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013212 /*
13213 * Read the board's EEPROM configuration.
13214 *
13215 * Set default values if a bad checksum is found.
13216 */
13217 if (AdvGet38C1600EEPConfig(iop_base, &eep_config) !=
13218 eep_config.check_sum) {
Matthew Wilcox13ac2d92007-07-30 08:10:23 -060013219 struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013220 warn_code |= ASC_WARN_EEPROM_CHKSUM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013221
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013222 /*
13223 * Set EEPROM default values.
13224 */
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013225 memcpy(&eep_config, &Default_38C1600_EEPROM_Config,
13226 sizeof(ADVEEP_38C1600_CONFIG));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013227
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013228 if (PCI_FUNC(pdev->devfn) != 0) {
13229 u8 ints;
13230 /*
13231 * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60
13232 * and old Mac system booting problem. The Expansion
13233 * ROM must be disabled in Function 1 for these systems
13234 */
13235 eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE;
13236 /*
13237 * Clear the INTAB (bit 11) if the GPIO 0 input
13238 * indicates the Function 1 interrupt line is wired
13239 * to INTB.
13240 *
13241 * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input:
13242 * 1 - Function 1 interrupt line wired to INT A.
13243 * 0 - Function 1 interrupt line wired to INT B.
13244 *
13245 * Note: Function 0 is always wired to INTA.
13246 * Put all 5 GPIO bits in input mode and then read
13247 * their input values.
13248 */
13249 AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0);
13250 ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA);
13251 if ((ints & 0x01) == 0)
13252 eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013254
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013255 /*
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013256 * Assume the 6 byte board serial number that was read from
13257 * EEPROM is correct even if the EEPROM checksum failed.
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013258 */
13259 eep_config.serial_number_word3 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013260 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013261 eep_config.serial_number_word2 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013262 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013263 eep_config.serial_number_word1 =
Matthew Wilcoxd68f4322007-07-26 11:58:12 -040013264 AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013265
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013266 AdvSet38C1600EEPConfig(iop_base, &eep_config);
13267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013268
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013269 /*
13270 * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the
13271 * EEPROM configuration that was read.
13272 *
13273 * This is the mapping of EEPROM fields to Adv Library fields.
13274 */
13275 asc_dvc->wdtr_able = eep_config.wdtr_able;
13276 asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1;
13277 asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2;
13278 asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3;
13279 asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4;
13280 asc_dvc->ppr_able = 0;
13281 asc_dvc->tagqng_able = eep_config.tagqng_able;
13282 asc_dvc->cfg->disc_enable = eep_config.disc_enable;
13283 asc_dvc->max_host_qng = eep_config.max_host_qng;
13284 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
13285 asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID);
13286 asc_dvc->start_motor = eep_config.start_motor;
13287 asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay;
13288 asc_dvc->bios_ctrl = eep_config.bios_ctrl;
13289 asc_dvc->no_scam = eep_config.scam_tolerant;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013290
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013291 /*
13292 * For every Target ID if any of its 'sdtr_speed[1234]' bits
13293 * are set, then set an 'sdtr_able' bit for it.
13294 */
13295 asc_dvc->sdtr_able = 0;
13296 for (tid = 0; tid <= ASC_MAX_TID; tid++) {
13297 if (tid == 0) {
13298 sdtr_speed = asc_dvc->sdtr_speed1;
13299 } else if (tid == 4) {
13300 sdtr_speed = asc_dvc->sdtr_speed2;
13301 } else if (tid == 8) {
13302 sdtr_speed = asc_dvc->sdtr_speed3;
13303 } else if (tid == 12) {
13304 sdtr_speed = asc_dvc->sdtr_speed4;
13305 }
13306 if (sdtr_speed & ASC_MAX_TID) {
13307 asc_dvc->sdtr_able |= (1 << tid);
13308 }
13309 sdtr_speed >>= 4;
13310 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013311
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013312 /*
13313 * Set the host maximum queuing (max. 253, min. 16) and the per device
13314 * maximum queuing (max. 63, min. 4).
13315 */
13316 if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) {
13317 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13318 } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) {
13319 /* If the value is zero, assume it is uninitialized. */
13320 if (eep_config.max_host_qng == 0) {
13321 eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG;
13322 } else {
13323 eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG;
13324 }
13325 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013326
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013327 if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) {
13328 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13329 } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) {
13330 /* If the value is zero, assume it is uninitialized. */
13331 if (eep_config.max_dvc_qng == 0) {
13332 eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG;
13333 } else {
13334 eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG;
13335 }
13336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013337
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013338 /*
13339 * If 'max_dvc_qng' is greater than 'max_host_qng', then
13340 * set 'max_dvc_qng' to 'max_host_qng'.
13341 */
13342 if (eep_config.max_dvc_qng > eep_config.max_host_qng) {
13343 eep_config.max_dvc_qng = eep_config.max_host_qng;
13344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013345
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013346 /*
13347 * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng'
13348 * values based on possibly adjusted EEPROM values.
13349 */
13350 asc_dvc->max_host_qng = eep_config.max_host_qng;
13351 asc_dvc->max_dvc_qng = eep_config.max_dvc_qng;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013352
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013353 /*
13354 * If the EEPROM 'termination' field is set to automatic (0), then set
13355 * the ASC_DVC_CFG 'termination' field to automatic also.
13356 *
13357 * If the termination is specified with a non-zero 'termination'
13358 * value check that a legal value is set and set the ASC_DVC_CFG
13359 * 'termination' field appropriately.
13360 */
13361 if (eep_config.termination_se == 0) {
13362 termination = 0; /* auto termination for SE */
13363 } else {
13364 /* Enable manual control with low off / high off. */
13365 if (eep_config.termination_se == 1) {
13366 termination = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013367
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013368 /* Enable manual control with low off / high on. */
13369 } else if (eep_config.termination_se == 2) {
13370 termination = TERM_SE_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013371
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013372 /* Enable manual control with low on / high on. */
13373 } else if (eep_config.termination_se == 3) {
13374 termination = TERM_SE;
13375 } else {
13376 /*
13377 * The EEPROM 'termination_se' field contains a bad value.
13378 * Use automatic termination instead.
13379 */
13380 termination = 0;
13381 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13382 }
13383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013384
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013385 if (eep_config.termination_lvd == 0) {
13386 asc_dvc->cfg->termination = termination; /* auto termination for LVD */
13387 } else {
13388 /* Enable manual control with low off / high off. */
13389 if (eep_config.termination_lvd == 1) {
13390 asc_dvc->cfg->termination = termination;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013391
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013392 /* Enable manual control with low off / high on. */
13393 } else if (eep_config.termination_lvd == 2) {
13394 asc_dvc->cfg->termination = termination | TERM_LVD_HI;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013395
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013396 /* Enable manual control with low on / high on. */
13397 } else if (eep_config.termination_lvd == 3) {
13398 asc_dvc->cfg->termination = termination | TERM_LVD;
13399 } else {
13400 /*
13401 * The EEPROM 'termination_lvd' field contains a bad value.
13402 * Use automatic termination instead.
13403 */
13404 asc_dvc->cfg->termination = termination;
13405 warn_code |= ASC_WARN_EEPROM_TERMINATION;
13406 }
13407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013408
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013409 return warn_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013410}
13411
13412/*
13413 * Read EEPROM configuration into the specified buffer.
13414 *
13415 * Return a checksum based on the EEPROM configuration read.
13416 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013417static ushort __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070013418AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
13419{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013420 ushort wval, chksum;
13421 ushort *wbuf;
13422 int eep_addr;
13423 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013424
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013425 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
13426 wbuf = (ushort *)cfg_buf;
13427 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013428
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013429 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13430 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13431 wval = AdvReadEEPWord(iop_base, eep_addr);
13432 chksum += wval; /* Checksum is calculated from word values. */
13433 if (*charfields++) {
13434 *wbuf = le16_to_cpu(wval);
13435 } else {
13436 *wbuf = wval;
13437 }
13438 }
13439 /* Read checksum word. */
13440 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13441 wbuf++;
13442 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013443
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013444 /* Read rest of EEPROM not covered by the checksum. */
13445 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13446 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13447 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13448 if (*charfields++) {
13449 *wbuf = le16_to_cpu(*wbuf);
13450 }
13451 }
13452 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013453}
13454
13455/*
13456 * Read EEPROM configuration into the specified buffer.
13457 *
13458 * Return a checksum based on the EEPROM configuration read.
13459 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013460static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013461AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013462{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013463 ushort wval, chksum;
13464 ushort *wbuf;
13465 int eep_addr;
13466 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013467
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013468 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
13469 wbuf = (ushort *)cfg_buf;
13470 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013471
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013472 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13473 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13474 wval = AdvReadEEPWord(iop_base, eep_addr);
13475 chksum += wval; /* Checksum is calculated from word values. */
13476 if (*charfields++) {
13477 *wbuf = le16_to_cpu(wval);
13478 } else {
13479 *wbuf = wval;
13480 }
13481 }
13482 /* Read checksum word. */
13483 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13484 wbuf++;
13485 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013486
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013487 /* Read rest of EEPROM not covered by the checksum. */
13488 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13489 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13490 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13491 if (*charfields++) {
13492 *wbuf = le16_to_cpu(*wbuf);
13493 }
13494 }
13495 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013496}
13497
13498/*
13499 * Read EEPROM configuration into the specified buffer.
13500 *
13501 * Return a checksum based on the EEPROM configuration read.
13502 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013503static ushort __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013504AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013505{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013506 ushort wval, chksum;
13507 ushort *wbuf;
13508 int eep_addr;
13509 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013510
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013511 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13512 wbuf = (ushort *)cfg_buf;
13513 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013514
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013515 for (eep_addr = ADV_EEP_DVC_CFG_BEGIN;
13516 eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) {
13517 wval = AdvReadEEPWord(iop_base, eep_addr);
13518 chksum += wval; /* Checksum is calculated from word values. */
13519 if (*charfields++) {
13520 *wbuf = le16_to_cpu(wval);
13521 } else {
13522 *wbuf = wval;
13523 }
13524 }
13525 /* Read checksum word. */
13526 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13527 wbuf++;
13528 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013529
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013530 /* Read rest of EEPROM not covered by the checksum. */
13531 for (eep_addr = ADV_EEP_DVC_CTL_BEGIN;
13532 eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) {
13533 *wbuf = AdvReadEEPWord(iop_base, eep_addr);
13534 if (*charfields++) {
13535 *wbuf = le16_to_cpu(*wbuf);
13536 }
13537 }
13538 return chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013539}
13540
13541/*
13542 * Read the EEPROM from specified location
13543 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013544static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013545{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013546 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13547 ASC_EEP_CMD_READ | eep_word_addr);
13548 AdvWaitEEPCmd(iop_base);
13549 return AdvReadWordRegister(iop_base, IOPW_EE_DATA);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013550}
13551
13552/*
13553 * Wait for EEPROM command to complete
13554 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013555static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013556{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013557 int eep_delay_ms;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013558
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013559 for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) {
13560 if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) &
13561 ASC_EEP_CMD_DONE) {
13562 break;
13563 }
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013564 mdelay(1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013565 }
13566 if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ==
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013567 0)
13568 BUG();
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013569 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013570}
13571
13572/*
13573 * Write the EEPROM from 'cfg_buf'.
13574 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013575void __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -070013576AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
13577{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013578 ushort *wbuf;
13579 ushort addr, chksum;
13580 ushort *charfields;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013581
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013582 wbuf = (ushort *)cfg_buf;
13583 charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar;
13584 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013585
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013586 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13587 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013588
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013589 /*
13590 * Write EEPROM from word 0 to word 20.
13591 */
13592 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13593 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13594 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013595
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013596 if (*charfields++) {
13597 word = cpu_to_le16(*wbuf);
13598 } else {
13599 word = *wbuf;
13600 }
13601 chksum += *wbuf; /* Checksum is calculated from word values. */
13602 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13603 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13604 ASC_EEP_CMD_WRITE | addr);
13605 AdvWaitEEPCmd(iop_base);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013606 mdelay(ADV_EEP_DELAY_MS);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013607 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013608
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013609 /*
13610 * Write EEPROM checksum at word 21.
13611 */
13612 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13613 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13614 AdvWaitEEPCmd(iop_base);
13615 wbuf++;
13616 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013617
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013618 /*
13619 * Write EEPROM OEM name at words 22 to 29.
13620 */
13621 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13622 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13623 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013624
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013625 if (*charfields++) {
13626 word = cpu_to_le16(*wbuf);
13627 } else {
13628 word = *wbuf;
13629 }
13630 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13631 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13632 ASC_EEP_CMD_WRITE | addr);
13633 AdvWaitEEPCmd(iop_base);
13634 }
13635 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13636 AdvWaitEEPCmd(iop_base);
13637 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013638}
13639
13640/*
13641 * Write the EEPROM from 'cfg_buf'.
13642 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013643void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013644AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013645{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013646 ushort *wbuf;
13647 ushort *charfields;
13648 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013649
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013650 wbuf = (ushort *)cfg_buf;
13651 charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar;
13652 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013653
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013654 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13655 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013656
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013657 /*
13658 * Write EEPROM from word 0 to word 20.
13659 */
13660 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13661 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13662 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013663
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013664 if (*charfields++) {
13665 word = cpu_to_le16(*wbuf);
13666 } else {
13667 word = *wbuf;
13668 }
13669 chksum += *wbuf; /* Checksum is calculated from word values. */
13670 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13671 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13672 ASC_EEP_CMD_WRITE | addr);
13673 AdvWaitEEPCmd(iop_base);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013674 mdelay(ADV_EEP_DELAY_MS);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013675 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013676
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013677 /*
13678 * Write EEPROM checksum at word 21.
13679 */
13680 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13681 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13682 AdvWaitEEPCmd(iop_base);
13683 wbuf++;
13684 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013685
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013686 /*
13687 * Write EEPROM OEM name at words 22 to 29.
13688 */
13689 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13690 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13691 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013692
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013693 if (*charfields++) {
13694 word = cpu_to_le16(*wbuf);
13695 } else {
13696 word = *wbuf;
13697 }
13698 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13699 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13700 ASC_EEP_CMD_WRITE | addr);
13701 AdvWaitEEPCmd(iop_base);
13702 }
13703 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13704 AdvWaitEEPCmd(iop_base);
13705 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013706}
13707
13708/*
13709 * Write the EEPROM from 'cfg_buf'.
13710 */
Matthew Wilcox78e77d82007-07-29 21:46:15 -060013711void __devinit
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013712AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013713{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013714 ushort *wbuf;
13715 ushort *charfields;
13716 ushort addr, chksum;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013717
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013718 wbuf = (ushort *)cfg_buf;
13719 charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar;
13720 chksum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013721
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013722 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE);
13723 AdvWaitEEPCmd(iop_base);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013724
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013725 /*
13726 * Write EEPROM from word 0 to word 20.
13727 */
13728 for (addr = ADV_EEP_DVC_CFG_BEGIN;
13729 addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) {
13730 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013731
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013732 if (*charfields++) {
13733 word = cpu_to_le16(*wbuf);
13734 } else {
13735 word = *wbuf;
13736 }
13737 chksum += *wbuf; /* Checksum is calculated from word values. */
13738 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13739 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13740 ASC_EEP_CMD_WRITE | addr);
13741 AdvWaitEEPCmd(iop_base);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013742 mdelay(ADV_EEP_DELAY_MS);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013744
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013745 /*
13746 * Write EEPROM checksum at word 21.
13747 */
13748 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum);
13749 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr);
13750 AdvWaitEEPCmd(iop_base);
13751 wbuf++;
13752 charfields++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013753
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013754 /*
13755 * Write EEPROM OEM name at words 22 to 29.
13756 */
13757 for (addr = ADV_EEP_DVC_CTL_BEGIN;
13758 addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) {
13759 ushort word;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013760
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013761 if (*charfields++) {
13762 word = cpu_to_le16(*wbuf);
13763 } else {
13764 word = *wbuf;
13765 }
13766 AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word);
13767 AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
13768 ASC_EEP_CMD_WRITE | addr);
13769 AdvWaitEEPCmd(iop_base);
13770 }
13771 AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE);
13772 AdvWaitEEPCmd(iop_base);
13773 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013774}
13775
13776/* a_advlib.c */
13777/*
13778 * AdvExeScsiQueue() - Send a request to the RISC microcode program.
13779 *
13780 * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q,
13781 * add the carrier to the ICQ (Initiator Command Queue), and tickle the
13782 * RISC to notify it a new command is ready to be executed.
13783 *
13784 * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be
13785 * set to SCSI_MAX_RETRY.
13786 *
13787 * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode
13788 * for DMA addresses or math operations are byte swapped to little-endian
13789 * order.
13790 *
13791 * Return:
13792 * ADV_SUCCESS(1) - The request was successfully queued.
13793 * ADV_BUSY(0) - Resource unavailable; Retry again after pending
13794 * request completes.
13795 * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure
13796 * host IC error.
13797 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013798static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013799{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013800 AdvPortAddr iop_base;
13801 ADV_DCNT req_size;
13802 ADV_PADDR req_paddr;
13803 ADV_CARR_T *new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013804
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013805 /*
13806 * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID.
13807 */
13808 if (scsiq->target_id > ADV_MAX_TID) {
13809 scsiq->host_status = QHSTA_M_INVALID_DEVICE;
13810 scsiq->done_status = QD_WITH_ERROR;
13811 return ADV_ERROR;
13812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013813
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013814 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013815
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013816 /*
13817 * Allocate a carrier ensuring at least one carrier always
13818 * remains on the freelist and initialize fields.
13819 */
13820 if ((new_carrp = asc_dvc->carr_freelist) == NULL) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013821 return ADV_BUSY;
13822 }
13823 asc_dvc->carr_freelist = (ADV_CARR_T *)
13824 ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa));
13825 asc_dvc->carr_pending_cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013826
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013827 /*
13828 * Set the carrier to be a stopper by setting 'next_vpa'
13829 * to the stopper value. The current stopper will be changed
13830 * below to point to the new stopper.
13831 */
13832 new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013833
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013834 /*
13835 * Clear the ADV_SCSI_REQ_Q done flag.
13836 */
13837 scsiq->a_flag &= ~ADV_SCSIQ_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013838
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013839 req_size = sizeof(ADV_SCSI_REQ_Q);
13840 req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq,
13841 (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013842
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013843 BUG_ON(req_paddr & 31);
13844 BUG_ON(req_size < sizeof(ADV_SCSI_REQ_Q));
Linus Torvalds1da177e2005-04-16 15:20:36 -070013845
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013846 /* Wait for assertion before making little-endian */
13847 req_paddr = cpu_to_le32(req_paddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013848
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013849 /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */
13850 scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq));
13851 scsiq->scsiq_rptr = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013852
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013853 scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp));
13854 /*
13855 * Every ADV_CARR_T.carr_pa is byte swapped to little-endian
13856 * order during initialization.
13857 */
13858 scsiq->carr_pa = asc_dvc->icq_sp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013859
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013860 /*
13861 * Use the current stopper to send the ADV_SCSI_REQ_Q command to
13862 * the microcode. The newly allocated stopper will become the new
13863 * stopper.
13864 */
13865 asc_dvc->icq_sp->areq_vpa = req_paddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013866
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013867 /*
13868 * Set the 'next_vpa' pointer for the old stopper to be the
13869 * physical address of the new stopper. The RISC can only
13870 * follow physical addresses.
13871 */
13872 asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013873
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013874 /*
13875 * Set the host adapter stopper pointer to point to the new carrier.
13876 */
13877 asc_dvc->icq_sp = new_carrp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013878
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013879 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
13880 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
13881 /*
13882 * Tickle the RISC to tell it to read its Command Queue Head pointer.
13883 */
13884 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A);
13885 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
13886 /*
13887 * Clear the tickle value. In the ASC-3550 the RISC flag
13888 * command 'clr_tickle_a' does not work unless the host
13889 * value is cleared.
13890 */
13891 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
13892 ADV_TICKLE_NOP);
13893 }
13894 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13895 /*
13896 * Notify the RISC a carrier is ready by writing the physical
13897 * address of the new carrier stopper to the COMMA register.
13898 */
13899 AdvWriteDWordRegister(iop_base, IOPDW_COMMA,
13900 le32_to_cpu(new_carrp->carr_pa));
13901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013902
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013903 return ADV_SUCCESS;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013904}
13905
13906/*
13907 * Reset SCSI Bus and purge all outstanding requests.
13908 *
13909 * Return Value:
13910 * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset.
13911 * ADV_FALSE(0) - Microcode command failed.
13912 * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC
13913 * may be hung which requires driver recovery.
13914 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013915static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013916{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013917 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013918
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013919 /*
13920 * Send the SCSI Bus Reset idle start idle command which asserts
13921 * the SCSI Bus Reset signal.
13922 */
13923 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L);
13924 if (status != ADV_TRUE) {
13925 return status;
13926 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013927
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013928 /*
13929 * Delay for the specified SCSI Bus Reset hold time.
13930 *
13931 * The hold time delay is done on the host because the RISC has no
13932 * microsecond accurate timer.
13933 */
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013934 udelay(ASC_SCSI_RESET_HOLD_TIME_US);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013935
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013936 /*
13937 * Send the SCSI Bus Reset end idle command which de-asserts
13938 * the SCSI Bus Reset signal and purges any pending requests.
13939 */
13940 status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L);
13941 if (status != ADV_TRUE) {
13942 return status;
13943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013944
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013945 mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */
Linus Torvalds1da177e2005-04-16 15:20:36 -070013946
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013947 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013948}
13949
13950/*
13951 * Reset chip and SCSI Bus.
13952 *
13953 * Return Value:
13954 * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful.
13955 * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure.
13956 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013957static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070013958{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013959 int status;
13960 ushort wdtr_able, sdtr_able, tagqng_able;
13961 ushort ppr_able = 0;
13962 uchar tid, max_cmd[ADV_MAX_TID + 1];
13963 AdvPortAddr iop_base;
13964 ushort bios_sig;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013965
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013966 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070013967
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013968 /*
13969 * Save current per TID negotiated values.
13970 */
13971 AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
13972 AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
13973 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
13974 AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
13975 }
13976 AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
13977 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
13978 AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
13979 max_cmd[tid]);
13980 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070013981
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013982 /*
13983 * Force the AdvInitAsc3550/38C0800Driver() function to
13984 * perform a SCSI Bus Reset by clearing the BIOS signature word.
13985 * The initialization functions assumes a SCSI Bus Reset is not
13986 * needed if the BIOS signature word is present.
13987 */
13988 AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
13989 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013990
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013991 /*
13992 * Stop chip and reset it.
13993 */
13994 AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP);
13995 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060013996 mdelay(100);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040013997 AdvWriteWordRegister(iop_base, IOPW_CTRL_REG,
13998 ADV_CTRL_REG_CMD_WR_IO_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070013999
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014000 /*
14001 * Reset Adv Library error code, if any, and try
14002 * re-initializing the chip.
14003 */
14004 asc_dvc->err_code = 0;
14005 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14006 status = AdvInitAsc38C1600Driver(asc_dvc);
14007 } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14008 status = AdvInitAsc38C0800Driver(asc_dvc);
14009 } else {
14010 status = AdvInitAsc3550Driver(asc_dvc);
14011 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014012
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014013 /* Translate initialization return value to status value. */
14014 if (status == 0) {
14015 status = ADV_TRUE;
14016 } else {
14017 status = ADV_FALSE;
14018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014019
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014020 /*
14021 * Restore the BIOS signature word.
14022 */
14023 AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014024
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014025 /*
14026 * Restore per TID negotiated values.
14027 */
14028 AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able);
14029 AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able);
14030 if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) {
14031 AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able);
14032 }
14033 AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able);
14034 for (tid = 0; tid <= ADV_MAX_TID; tid++) {
14035 AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid,
14036 max_cmd[tid]);
14037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014038
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014039 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014040}
14041
14042/*
14043 * Adv Library Interrupt Service Routine
14044 *
14045 * This function is called by a driver's interrupt service routine.
14046 * The function disables and re-enables interrupts.
14047 *
14048 * When a microcode idle command is completed, the ADV_DVC_VAR
14049 * 'idle_cmd_done' field is set to ADV_TRUE.
14050 *
14051 * Note: AdvISR() can be called when interrupts are disabled or even
14052 * when there is no hardware interrupt condition present. It will
14053 * always check for completed idle commands and microcode requests.
14054 * This is an important feature that shouldn't be changed because it
14055 * allows commands to be completed from polling mode loops.
14056 *
14057 * Return:
14058 * ADV_TRUE(1) - interrupt was pending
14059 * ADV_FALSE(0) - no interrupt was pending
14060 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014061static int AdvISR(ADV_DVC_VAR *asc_dvc)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014062{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014063 AdvPortAddr iop_base;
14064 uchar int_stat;
14065 ushort target_bit;
14066 ADV_CARR_T *free_carrp;
14067 ADV_VADDR irq_next_vpa;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014068 ADV_SCSI_REQ_Q *scsiq;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014069
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014070 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014071
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014072 /* Reading the register clears the interrupt. */
14073 int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014074
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014075 if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB |
14076 ADV_INTR_STATUS_INTRC)) == 0) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014077 return ADV_FALSE;
14078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014079
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014080 /*
14081 * Notify the driver of an asynchronous microcode condition by
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014082 * calling the adv_async_callback function. The function
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014083 * is passed the microcode ASC_MC_INTRB_CODE byte value.
14084 */
14085 if (int_stat & ADV_INTR_STATUS_INTRB) {
14086 uchar intrb_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014087
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014088 AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014089
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014090 if (asc_dvc->chip_type == ADV_CHIP_ASC3550 ||
14091 asc_dvc->chip_type == ADV_CHIP_ASC38C0800) {
14092 if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE &&
14093 asc_dvc->carr_pending_cnt != 0) {
14094 AdvWriteByteRegister(iop_base, IOPB_TICKLE,
14095 ADV_TICKLE_A);
14096 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14097 AdvWriteByteRegister(iop_base,
14098 IOPB_TICKLE,
14099 ADV_TICKLE_NOP);
14100 }
14101 }
14102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014103
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014104 adv_async_callback(asc_dvc, intrb_code);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014106
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014107 /*
14108 * Check if the IRQ stopper carrier contains a completed request.
14109 */
14110 while (((irq_next_vpa =
14111 le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) {
14112 /*
14113 * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure.
14114 * The RISC will have set 'areq_vpa' to a virtual address.
14115 *
14116 * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr
14117 * field to the carrier ADV_CARR_T.areq_vpa field. The conversion
14118 * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr'
14119 * in AdvExeScsiQueue().
14120 */
14121 scsiq = (ADV_SCSI_REQ_Q *)
14122 ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014123
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014124 /*
14125 * Request finished with good status and the queue was not
14126 * DMAed to host memory by the firmware. Set all status fields
14127 * to indicate good status.
14128 */
14129 if ((irq_next_vpa & ASC_RQ_GOOD) != 0) {
14130 scsiq->done_status = QD_NO_ERROR;
14131 scsiq->host_status = scsiq->scsi_status = 0;
14132 scsiq->data_cnt = 0L;
14133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014134
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014135 /*
14136 * Advance the stopper pointer to the next carrier
14137 * ignoring the lower four bits. Free the previous
14138 * stopper carrier.
14139 */
14140 free_carrp = asc_dvc->irq_sp;
14141 asc_dvc->irq_sp = (ADV_CARR_T *)
14142 ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa));
Linus Torvalds1da177e2005-04-16 15:20:36 -070014143
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014144 free_carrp->next_vpa =
14145 cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist));
14146 asc_dvc->carr_freelist = free_carrp;
14147 asc_dvc->carr_pending_cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014148
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014149 target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014150
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014151 /*
14152 * Clear request microcode control flag.
14153 */
14154 scsiq->cntl = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014155
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014156 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014157 * Notify the driver of the completed request by passing
14158 * the ADV_SCSI_REQ_Q pointer to its callback function.
14159 */
14160 scsiq->a_flag |= ADV_SCSIQ_DONE;
Matthew Wilcox895d6b42007-07-26 11:57:06 -040014161 adv_isr_callback(asc_dvc, scsiq);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014162 /*
14163 * Note: After the driver callback function is called, 'scsiq'
14164 * can no longer be referenced.
14165 *
14166 * Fall through and continue processing other completed
14167 * requests...
14168 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014169 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014170 return ADV_TRUE;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014171}
14172
14173/*
14174 * Send an idle command to the chip and wait for completion.
14175 *
14176 * Command completion is polled for once per microsecond.
14177 *
14178 * The function can be called from anywhere including an interrupt handler.
14179 * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical()
14180 * functions to prevent reentrancy.
14181 *
14182 * Return Values:
14183 * ADV_TRUE - command completed successfully
14184 * ADV_FALSE - command failed
14185 * ADV_ERROR - command timed out
14186 */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014187static int
Linus Torvalds1da177e2005-04-16 15:20:36 -070014188AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc,
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014189 ushort idle_cmd, ADV_DCNT idle_cmd_parameter)
Linus Torvalds1da177e2005-04-16 15:20:36 -070014190{
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014191 int result;
14192 ADV_DCNT i, j;
14193 AdvPortAddr iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014194
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014195 iop_base = asc_dvc->iop_base;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014196
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014197 /*
14198 * Clear the idle command status which is set by the microcode
14199 * to a non-zero value to indicate when the command is completed.
14200 * The non-zero result is one of the IDLE_CMD_STATUS_* values
14201 * defined in a_advlib.h.
14202 */
14203 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014204
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014205 /*
14206 * Write the idle command value after the idle command parameter
14207 * has been written to avoid a race condition. If the order is not
14208 * followed, the microcode may process the idle command before the
14209 * parameters have been written to LRAM.
14210 */
14211 AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER,
14212 cpu_to_le32(idle_cmd_parameter));
14213 AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070014214
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014215 /*
14216 * Tickle the RISC to tell it to process the idle command.
14217 */
14218 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B);
14219 if (asc_dvc->chip_type == ADV_CHIP_ASC3550) {
14220 /*
14221 * Clear the tickle value. In the ASC-3550 the RISC flag
14222 * command 'clr_tickle_b' does not work unless the host
14223 * value is cleared.
14224 */
14225 AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP);
14226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014227
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014228 /* Wait for up to 100 millisecond for the idle command to timeout. */
14229 for (i = 0; i < SCSI_WAIT_100_MSEC; i++) {
14230 /* Poll once each microsecond for command completion. */
14231 for (j = 0; j < SCSI_US_PER_MSEC; j++) {
14232 AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS,
14233 result);
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060014234 if (result != 0)
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014235 return result;
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060014236 udelay(1);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014237 }
14238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070014239
Matthew Wilcoxb009bef2007-09-09 08:56:38 -060014240 BUG(); /* The idle command should never timeout. */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014241 return ADV_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -070014242}
14243
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014244static int __devinit
14245advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
14246{
14247 int req_cnt = 0;
14248 adv_req_t *reqp = NULL;
14249 int sg_cnt = 0;
14250 adv_sgblk_t *sgp;
14251 int warn_code, err_code;
14252
14253 /*
14254 * Allocate buffer carrier structures. The total size
14255 * is about 4 KB, so allocate all at once.
14256 */
14257 boardp->carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
14258 ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%p\n", boardp->carrp);
14259
14260 if (!boardp->carrp)
14261 goto kmalloc_failed;
14262
14263 /*
14264 * Allocate up to 'max_host_qng' request structures for the Wide
14265 * board. The total size is about 16 KB, so allocate all at once.
14266 * If the allocation fails decrement and try again.
14267 */
14268 for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
14269 reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
14270
14271 ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
14272 "bytes %lu\n", reqp, req_cnt,
14273 (ulong)sizeof(adv_req_t) * req_cnt);
14274
14275 if (reqp)
14276 break;
14277 }
14278
14279 if (!reqp)
14280 goto kmalloc_failed;
14281
14282 boardp->orig_reqp = reqp;
14283
14284 /*
14285 * Allocate up to ADV_TOT_SG_BLOCK request structures for
14286 * the Wide board. Each structure is about 136 bytes.
14287 */
14288 boardp->adv_sgblkp = NULL;
14289 for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
14290 sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
14291
14292 if (!sgp)
14293 break;
14294
14295 sgp->next_sgblkp = boardp->adv_sgblkp;
14296 boardp->adv_sgblkp = sgp;
14297
14298 }
14299
14300 ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
14301 sg_cnt, sizeof(adv_sgblk_t),
14302 (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
14303
14304 if (!boardp->adv_sgblkp)
14305 goto kmalloc_failed;
14306
14307 adv_dvc_varp->carrier_buf = boardp->carrp;
14308
14309 /*
14310 * Point 'adv_reqp' to the request structures and
14311 * link them together.
14312 */
14313 req_cnt--;
14314 reqp[req_cnt].next_reqp = NULL;
14315 for (; req_cnt > 0; req_cnt--) {
14316 reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
14317 }
14318 boardp->adv_reqp = &reqp[0];
14319
14320 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14321 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
14322 warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
14323 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14324 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
14325 "\n");
14326 warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
14327 } else {
14328 ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
14329 "\n");
14330 warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
14331 }
14332 err_code = adv_dvc_varp->err_code;
14333
14334 if (warn_code || err_code) {
14335 ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
14336 " error 0x%x\n", boardp->id, warn_code, err_code);
14337 }
14338
14339 goto exit;
14340
14341 kmalloc_failed:
14342 ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
14343 "failed\n", boardp->id);
14344 err_code = ADV_ERROR;
14345 exit:
14346 return err_code;
14347}
14348
14349static void advansys_wide_free_mem(asc_board_t *boardp)
14350{
14351 kfree(boardp->carrp);
14352 boardp->carrp = NULL;
14353 kfree(boardp->orig_reqp);
14354 boardp->orig_reqp = boardp->adv_reqp = NULL;
14355 while (boardp->adv_sgblkp) {
14356 adv_sgblk_t *sgp = boardp->adv_sgblkp;
14357 boardp->adv_sgblkp = sgp->next_sgblkp;
14358 kfree(sgp);
14359 }
14360}
14361
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014362static struct Scsi_Host *__devinit
14363advansys_board_found(int iop, struct device *dev, int bus_type)
14364{
14365 struct Scsi_Host *shost;
14366 struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL;
14367 asc_board_t *boardp;
14368 ASC_DVC_VAR *asc_dvc_varp = NULL;
14369 ADV_DVC_VAR *adv_dvc_varp = NULL;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014370 int share_irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014371 int warn_code, err_code;
14372 int ret;
14373
14374 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014375 * Register the adapter, get its configuration, and
14376 * initialize it.
14377 */
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014378 ASC_DBG(2, "advansys_board_found: scsi_host_alloc()\n");
14379 shost = scsi_host_alloc(&advansys_template, sizeof(asc_board_t));
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014380 if (!shost)
14381 return NULL;
14382
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014383 /* Initialize private per board data */
14384 boardp = ASC_BOARDP(shost);
14385 memset(boardp, 0, sizeof(asc_board_t));
Matthew Wilcox78e77d82007-07-29 21:46:15 -060014386 boardp->id = asc_board_count++;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014387 spin_lock_init(&boardp->lock);
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014388 boardp->dev = dev;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014389
14390 /*
14391 * Handle both narrow and wide boards.
14392 *
14393 * If a Wide board was detected, set the board structure
14394 * wide board flag. Set-up the board structure based on
14395 * the board type.
14396 */
14397#ifdef CONFIG_PCI
14398 if (bus_type == ASC_IS_PCI &&
14399 (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW ||
14400 pdev->device == PCI_DEVICE_ID_38C0800_REV1 ||
14401 pdev->device == PCI_DEVICE_ID_38C1600_REV1)) {
14402 boardp->flags |= ASC_IS_WIDE_BOARD;
14403 }
14404#endif /* CONFIG_PCI */
14405
14406 if (ASC_NARROW_BOARD(boardp)) {
14407 ASC_DBG(1, "advansys_board_found: narrow board\n");
14408 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
14409 asc_dvc_varp->bus_type = bus_type;
14410 asc_dvc_varp->drv_ptr = boardp;
14411 asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg;
14412 asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
14413 asc_dvc_varp->iop_base = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014414 } else {
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014415#ifdef CONFIG_PCI
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014416 ASC_DBG(1, "advansys_board_found: wide board\n");
14417 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
14418 adv_dvc_varp->drv_ptr = boardp;
14419 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014420 if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) {
14421 ASC_DBG(1, "advansys_board_found: ASC-3550\n");
14422 adv_dvc_varp->chip_type = ADV_CHIP_ASC3550;
14423 } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) {
14424 ASC_DBG(1, "advansys_board_found: ASC-38C0800\n");
14425 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800;
14426 } else {
14427 ASC_DBG(1, "advansys_board_found: ASC-38C1600\n");
14428 adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600;
14429 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014430
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014431 boardp->asc_n_io_port = pci_resource_len(pdev, 1);
14432 boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1),
14433 boardp->asc_n_io_port);
14434 if (!boardp->ioremap_addr) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014435 ASC_PRINT3
14436 ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n",
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014437 boardp->id, pci_resource_start(pdev, 1),
14438 boardp->asc_n_io_port);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014439 goto err_shost;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014440 }
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014441 adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr
Matthew Wilcox71f361152007-07-30 08:04:53 -060014442 ASC_DBG1(1, "advansys_board_found: iop_base: 0x%lx\n",
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014443 adv_dvc_varp->iop_base);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014444
14445 /*
14446 * Even though it isn't used to access wide boards, other
14447 * than for the debug line below, save I/O Port address so
14448 * that it can be reported.
14449 */
14450 boardp->ioport = iop;
14451
Matthew Wilcox57ba5fe2007-07-26 11:55:07 -040014452 ASC_DBG2(1, "advansys_board_found: iopb_chip_id_1 0x%x, "
14453 "iopw_chip_id_0 0x%x\n", (ushort)inp(iop + 1),
14454 (ushort)inpw(iop));
14455#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014456 }
14457
14458#ifdef CONFIG_PROC_FS
14459 /*
14460 * Allocate buffer for printing information from
14461 * /proc/scsi/advansys/[0...].
14462 */
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014463 boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
14464 if (!boardp->prtbuf) {
14465 ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
14466 "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
14467 goto err_unmap;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014468 }
14469#endif /* CONFIG_PROC_FS */
14470
14471 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014472 /*
14473 * Set the board bus type and PCI IRQ before
14474 * calling AscInitGetConfig().
14475 */
14476 switch (asc_dvc_varp->bus_type) {
14477#ifdef CONFIG_ISA
14478 case ASC_IS_ISA:
14479 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014480 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014481 break;
14482 case ASC_IS_VL:
14483 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014484 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014485 break;
14486 case ASC_IS_EISA:
14487 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014488 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014489 break;
14490#endif /* CONFIG_ISA */
14491#ifdef CONFIG_PCI
14492 case ASC_IS_PCI:
14493 shost->irq = asc_dvc_varp->irq_no = pdev->irq;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014494 shost->unchecked_isa_dma = FALSE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014495 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014496 break;
14497#endif /* CONFIG_PCI */
14498 default:
14499 ASC_PRINT2
14500 ("advansys_board_found: board %d: unknown adapter type: %d\n",
14501 boardp->id, asc_dvc_varp->bus_type);
14502 shost->unchecked_isa_dma = TRUE;
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014503 share_irq = 0;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014504 break;
14505 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014506
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014507 /*
14508 * NOTE: AscInitGetConfig() may change the board's
14509 * bus_type value. The bus_type value should no
14510 * longer be used. If the bus_type field must be
14511 * referenced only use the bit-wise AND operator "&".
14512 */
14513 ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014514 err_code = AscInitGetConfig(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014515 } else {
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014516#ifdef CONFIG_PCI
14517 /*
14518 * For Wide boards set PCI information before calling
14519 * AdvInitGetConfig().
14520 */
14521 shost->irq = adv_dvc_varp->irq_no = pdev->irq;
14522 shost->unchecked_isa_dma = FALSE;
14523 share_irq = IRQF_SHARED;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014524 ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n");
Matthew Wilcox394dbf32007-07-26 11:56:40 -040014525
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014526 err_code = AdvInitGetConfig(pdev, boardp);
14527#endif /* CONFIG_PCI */
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014528 }
14529
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014530 if (err_code != 0)
14531 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014532
14533 /*
14534 * Save the EEPROM configuration so that it can be displayed
14535 * from /proc/scsi/advansys/[0...].
14536 */
14537 if (ASC_NARROW_BOARD(boardp)) {
14538
14539 ASCEEP_CONFIG *ep;
14540
14541 /*
14542 * Set the adapter's target id bit in the 'init_tidmask' field.
14543 */
14544 boardp->init_tidmask |=
14545 ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id);
14546
14547 /*
14548 * Save EEPROM settings for the board.
14549 */
14550 ep = &boardp->eep_config.asc_eep;
14551
14552 ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
14553 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
14554 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
14555 ASC_EEP_SET_DMA_SPD(ep, asc_dvc_varp->cfg->isa_dma_speed);
14556 ep->start_motor = asc_dvc_varp->start_motor;
14557 ep->cntl = asc_dvc_varp->dvc_cntl;
14558 ep->no_scam = asc_dvc_varp->no_scam;
14559 ep->max_total_qng = asc_dvc_varp->max_total_qng;
14560 ASC_EEP_SET_CHIP_ID(ep, asc_dvc_varp->cfg->chip_scsi_id);
14561 /* 'max_tag_qng' is set to the same value for every device. */
14562 ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0];
14563 ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0];
14564 ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1];
14565 ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2];
14566 ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3];
14567 ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4];
14568 ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5];
14569
14570 /*
14571 * Modify board configuration.
14572 */
14573 ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n");
Matthew Wilcoxc2dce2f2007-09-09 08:56:30 -060014574 err_code = AscInitSetConfig(pdev, boardp);
14575 if (err_code)
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014576 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014577
14578 /*
14579 * Finish initializing the 'Scsi_Host' structure.
14580 */
14581 /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
14582 if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
14583 shost->irq = asc_dvc_varp->irq_no;
14584 }
14585 } else {
14586 ADVEEP_3550_CONFIG *ep_3550;
14587 ADVEEP_38C0800_CONFIG *ep_38C0800;
14588 ADVEEP_38C1600_CONFIG *ep_38C1600;
14589
14590 /*
14591 * Save Wide EEP Configuration Information.
14592 */
14593 if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
14594 ep_3550 = &boardp->eep_config.adv_3550_eep;
14595
14596 ep_3550->adapter_scsi_id = adv_dvc_varp->chip_scsi_id;
14597 ep_3550->max_host_qng = adv_dvc_varp->max_host_qng;
14598 ep_3550->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14599 ep_3550->termination = adv_dvc_varp->cfg->termination;
14600 ep_3550->disc_enable = adv_dvc_varp->cfg->disc_enable;
14601 ep_3550->bios_ctrl = adv_dvc_varp->bios_ctrl;
14602 ep_3550->wdtr_able = adv_dvc_varp->wdtr_able;
14603 ep_3550->sdtr_able = adv_dvc_varp->sdtr_able;
14604 ep_3550->ultra_able = adv_dvc_varp->ultra_able;
14605 ep_3550->tagqng_able = adv_dvc_varp->tagqng_able;
14606 ep_3550->start_motor = adv_dvc_varp->start_motor;
14607 ep_3550->scsi_reset_delay =
14608 adv_dvc_varp->scsi_reset_wait;
14609 ep_3550->serial_number_word1 =
14610 adv_dvc_varp->cfg->serial1;
14611 ep_3550->serial_number_word2 =
14612 adv_dvc_varp->cfg->serial2;
14613 ep_3550->serial_number_word3 =
14614 adv_dvc_varp->cfg->serial3;
14615 } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
14616 ep_38C0800 = &boardp->eep_config.adv_38C0800_eep;
14617
14618 ep_38C0800->adapter_scsi_id =
14619 adv_dvc_varp->chip_scsi_id;
14620 ep_38C0800->max_host_qng = adv_dvc_varp->max_host_qng;
14621 ep_38C0800->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14622 ep_38C0800->termination_lvd =
14623 adv_dvc_varp->cfg->termination;
14624 ep_38C0800->disc_enable =
14625 adv_dvc_varp->cfg->disc_enable;
14626 ep_38C0800->bios_ctrl = adv_dvc_varp->bios_ctrl;
14627 ep_38C0800->wdtr_able = adv_dvc_varp->wdtr_able;
14628 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14629 ep_38C0800->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14630 ep_38C0800->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14631 ep_38C0800->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14632 ep_38C0800->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14633 ep_38C0800->tagqng_able = adv_dvc_varp->tagqng_able;
14634 ep_38C0800->start_motor = adv_dvc_varp->start_motor;
14635 ep_38C0800->scsi_reset_delay =
14636 adv_dvc_varp->scsi_reset_wait;
14637 ep_38C0800->serial_number_word1 =
14638 adv_dvc_varp->cfg->serial1;
14639 ep_38C0800->serial_number_word2 =
14640 adv_dvc_varp->cfg->serial2;
14641 ep_38C0800->serial_number_word3 =
14642 adv_dvc_varp->cfg->serial3;
14643 } else {
14644 ep_38C1600 = &boardp->eep_config.adv_38C1600_eep;
14645
14646 ep_38C1600->adapter_scsi_id =
14647 adv_dvc_varp->chip_scsi_id;
14648 ep_38C1600->max_host_qng = adv_dvc_varp->max_host_qng;
14649 ep_38C1600->max_dvc_qng = adv_dvc_varp->max_dvc_qng;
14650 ep_38C1600->termination_lvd =
14651 adv_dvc_varp->cfg->termination;
14652 ep_38C1600->disc_enable =
14653 adv_dvc_varp->cfg->disc_enable;
14654 ep_38C1600->bios_ctrl = adv_dvc_varp->bios_ctrl;
14655 ep_38C1600->wdtr_able = adv_dvc_varp->wdtr_able;
14656 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14657 ep_38C1600->sdtr_speed1 = adv_dvc_varp->sdtr_speed1;
14658 ep_38C1600->sdtr_speed2 = adv_dvc_varp->sdtr_speed2;
14659 ep_38C1600->sdtr_speed3 = adv_dvc_varp->sdtr_speed3;
14660 ep_38C1600->sdtr_speed4 = adv_dvc_varp->sdtr_speed4;
14661 ep_38C1600->tagqng_able = adv_dvc_varp->tagqng_able;
14662 ep_38C1600->start_motor = adv_dvc_varp->start_motor;
14663 ep_38C1600->scsi_reset_delay =
14664 adv_dvc_varp->scsi_reset_wait;
14665 ep_38C1600->serial_number_word1 =
14666 adv_dvc_varp->cfg->serial1;
14667 ep_38C1600->serial_number_word2 =
14668 adv_dvc_varp->cfg->serial2;
14669 ep_38C1600->serial_number_word3 =
14670 adv_dvc_varp->cfg->serial3;
14671 }
14672
14673 /*
14674 * Set the adapter's target id bit in the 'init_tidmask' field.
14675 */
14676 boardp->init_tidmask |=
14677 ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014678 }
14679
14680 /*
14681 * Channels are numbered beginning with 0. For AdvanSys one host
14682 * structure supports one channel. Multi-channel boards have a
14683 * separate host structure for each channel.
14684 */
14685 shost->max_channel = 0;
14686 if (ASC_NARROW_BOARD(boardp)) {
14687 shost->max_id = ASC_MAX_TID + 1;
14688 shost->max_lun = ASC_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060014689 shost->max_cmd_len = ASC_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014690
14691 shost->io_port = asc_dvc_varp->iop_base;
14692 boardp->asc_n_io_port = ASC_IOADR_GAP;
14693 shost->this_id = asc_dvc_varp->cfg->chip_scsi_id;
14694
14695 /* Set maximum number of queues the adapter can handle. */
14696 shost->can_queue = asc_dvc_varp->max_total_qng;
14697 } else {
14698 shost->max_id = ADV_MAX_TID + 1;
14699 shost->max_lun = ADV_MAX_LUN + 1;
Matthew Wilcoxf05ec592007-09-09 08:56:36 -060014700 shost->max_cmd_len = ADV_MAX_CDB_LEN;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014701
14702 /*
14703 * Save the I/O Port address and length even though
14704 * I/O ports are not used to access Wide boards.
14705 * Instead the Wide boards are accessed with
14706 * PCI Memory Mapped I/O.
14707 */
14708 shost->io_port = iop;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014709
14710 shost->this_id = adv_dvc_varp->chip_scsi_id;
14711
14712 /* Set maximum number of queues the adapter can handle. */
14713 shost->can_queue = adv_dvc_varp->max_host_qng;
14714 }
14715
14716 /*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014717 * Following v1.3.89, 'cmd_per_lun' is no longer needed
14718 * and should be set to zero.
14719 *
14720 * But because of a bug introduced in v1.3.89 if the driver is
14721 * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level
14722 * SCSI function 'allocate_device' will panic. To allow the driver
14723 * to work as a module in these kernels set 'cmd_per_lun' to 1.
14724 *
14725 * Note: This is wrong. cmd_per_lun should be set to the depth
14726 * you want on untagged devices always.
14727 #ifdef MODULE
14728 */
14729 shost->cmd_per_lun = 1;
14730/* #else
14731 shost->cmd_per_lun = 0;
14732#endif */
14733
14734 /*
14735 * Set the maximum number of scatter-gather elements the
14736 * adapter can handle.
14737 */
14738 if (ASC_NARROW_BOARD(boardp)) {
14739 /*
14740 * Allow two commands with 'sg_tablesize' scatter-gather
14741 * elements to be executed simultaneously. This value is
14742 * the theoretical hardware limit. It may be decreased
14743 * below.
14744 */
14745 shost->sg_tablesize =
14746 (((asc_dvc_varp->max_total_qng - 2) / 2) *
14747 ASC_SG_LIST_PER_Q) + 1;
14748 } else {
14749 shost->sg_tablesize = ADV_MAX_SG_LIST;
14750 }
14751
14752 /*
14753 * The value of 'sg_tablesize' can not exceed the SCSI
14754 * mid-level driver definition of SG_ALL. SG_ALL also
14755 * must not be exceeded, because it is used to define the
14756 * size of the scatter-gather table in 'struct asc_sg_head'.
14757 */
14758 if (shost->sg_tablesize > SG_ALL) {
14759 shost->sg_tablesize = SG_ALL;
14760 }
14761
14762 ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize);
14763
14764 /* BIOS start address. */
14765 if (ASC_NARROW_BOARD(boardp)) {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014766 shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base,
14767 asc_dvc_varp->bus_type);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014768 } else {
14769 /*
14770 * Fill-in BIOS board variables. The Wide BIOS saves
14771 * information in LRAM that is used by the driver.
14772 */
14773 AdvReadWordLram(adv_dvc_varp->iop_base,
14774 BIOS_SIGNATURE, boardp->bios_signature);
14775 AdvReadWordLram(adv_dvc_varp->iop_base,
14776 BIOS_VERSION, boardp->bios_version);
14777 AdvReadWordLram(adv_dvc_varp->iop_base,
14778 BIOS_CODESEG, boardp->bios_codeseg);
14779 AdvReadWordLram(adv_dvc_varp->iop_base,
14780 BIOS_CODELEN, boardp->bios_codelen);
14781
14782 ASC_DBG2(1,
14783 "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n",
14784 boardp->bios_signature, boardp->bios_version);
14785
14786 ASC_DBG2(1,
14787 "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n",
14788 boardp->bios_codeseg, boardp->bios_codelen);
14789
14790 /*
14791 * If the BIOS saved a valid signature, then fill in
14792 * the BIOS code segment base address.
14793 */
14794 if (boardp->bios_signature == 0x55AA) {
14795 /*
14796 * Convert x86 realmode code segment to a linear
14797 * address by shifting left 4.
14798 */
14799 shost->base = ((ulong)boardp->bios_codeseg << 4);
14800 } else {
14801 shost->base = 0;
14802 }
14803 }
14804
14805 /*
14806 * Register Board Resources - I/O Port, DMA, IRQ
14807 */
14808
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014809 /* Register DMA Channel for Narrow boards. */
14810 shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */
14811#ifdef CONFIG_ISA
14812 if (ASC_NARROW_BOARD(boardp)) {
14813 /* Register DMA channel for ISA bus. */
14814 if (asc_dvc_varp->bus_type & ASC_IS_ISA) {
14815 shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014816 ret = request_dma(shost->dma_channel, "advansys");
14817 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014818 ASC_PRINT3
14819 ("advansys_board_found: board %d: request_dma() %d failed %d\n",
14820 boardp->id, shost->dma_channel, ret);
Matthew Wilcox71f361152007-07-30 08:04:53 -060014821 goto err_free_proc;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014822 }
14823 AscEnableIsaDma(shost->dma_channel);
14824 }
14825 }
14826#endif /* CONFIG_ISA */
14827
14828 /* Register IRQ Number. */
14829 ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014830
14831 ret = request_irq(shost->irq, advansys_interrupt, share_irq,
14832 "advansys", shost);
14833
14834 if (ret) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014835 if (ret == -EBUSY) {
14836 ASC_PRINT2
14837 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n",
14838 boardp->id, shost->irq);
14839 } else if (ret == -EINVAL) {
14840 ASC_PRINT2
14841 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n",
14842 boardp->id, shost->irq);
14843 } else {
14844 ASC_PRINT3
14845 ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n",
14846 boardp->id, shost->irq, ret);
14847 }
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014848 goto err_free_dma;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014849 }
14850
14851 /*
14852 * Initialize board RISC chip and enable interrupts.
14853 */
14854 if (ASC_NARROW_BOARD(boardp)) {
14855 ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n");
14856 warn_code = AscInitAsc1000Driver(asc_dvc_varp);
14857 err_code = asc_dvc_varp->err_code;
14858
14859 if (warn_code || err_code) {
14860 ASC_PRINT4
14861 ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n",
14862 boardp->id,
14863 asc_dvc_varp->init_state, warn_code, err_code);
14864 }
14865 } else {
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014866 err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014867 }
14868
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014869 if (err_code != 0)
14870 goto err_free_wide_mem;
14871
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014872 ASC_DBG_PRT_SCSI_HOST(2, shost);
14873
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014874 ret = scsi_add_host(shost, dev);
14875 if (ret)
14876 goto err_free_wide_mem;
14877
14878 scsi_scan_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014879 return shost;
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014880
14881 err_free_wide_mem:
14882 advansys_wide_free_mem(boardp);
14883 free_irq(shost->irq, shost);
14884 err_free_dma:
14885 if (shost->dma_channel != NO_ISA_DMA)
14886 free_dma(shost->dma_channel);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014887 err_free_proc:
14888 kfree(boardp->prtbuf);
14889 err_unmap:
14890 if (boardp->ioremap_addr)
14891 iounmap(boardp->ioremap_addr);
14892 err_shost:
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014893 scsi_host_put(shost);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014894 return NULL;
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014895}
14896
14897/*
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014898 * advansys_release()
14899 *
14900 * Release resources allocated for a single AdvanSys adapter.
14901 */
14902static int advansys_release(struct Scsi_Host *shost)
14903{
14904 asc_board_t *boardp;
14905
14906 ASC_DBG(1, "advansys_release: begin\n");
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014907 scsi_remove_host(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014908 boardp = ASC_BOARDP(shost);
Matthew Wilcox074c8fe2007-07-28 23:11:05 -060014909 free_irq(shost->irq, shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014910 if (shost->dma_channel != NO_ISA_DMA) {
14911 ASC_DBG(1, "advansys_release: free_dma()\n");
14912 free_dma(shost->dma_channel);
14913 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014914 if (ASC_WIDE_BOARD(boardp)) {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014915 iounmap(boardp->ioremap_addr);
Matthew Wilcoxb2c16f52007-07-29 17:30:28 -060014916 advansys_wide_free_mem(boardp);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014917 }
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014918 kfree(boardp->prtbuf);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060014919 scsi_host_put(shost);
Matthew Wilcox27c868c2007-07-26 10:56:23 -040014920 ASC_DBG(1, "advansys_release: end\n");
14921 return 0;
14922}
14923
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014924static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = {
14925 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190,
14926 0x0210, 0x0230, 0x0250, 0x0330
14927};
14928
14929static int __devinit advansys_isa_probe(struct device *dev, unsigned int id)
14930{
14931 PortAddr iop_base = _asc_def_iop_base[id];
14932 struct Scsi_Host *shost;
14933
14934 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f361152007-07-30 08:04:53 -060014935 ASC_DBG1(1, "advansys_isa_match: I/O port 0x%x busy\n",
14936 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014937 return -ENODEV;
14938 }
14939 ASC_DBG1(1, "advansys_isa_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014940 if (!AscFindSignature(iop_base))
14941 goto nodev;
14942 if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT))
14943 goto nodev;
14944
14945 shost = advansys_board_found(iop_base, dev, ASC_IS_ISA);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014946 if (!shost)
14947 goto nodev;
14948
14949 dev_set_drvdata(dev, shost);
14950 return 0;
14951
14952 nodev:
Matthew Wilcox71f361152007-07-30 08:04:53 -060014953 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014954 return -ENODEV;
14955}
14956
14957static int __devexit advansys_isa_remove(struct device *dev, unsigned int id)
14958{
Matthew Wilcox71f361152007-07-30 08:04:53 -060014959 int ioport = _asc_def_iop_base[id];
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014960 advansys_release(dev_get_drvdata(dev));
Matthew Wilcox71f361152007-07-30 08:04:53 -060014961 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014962 return 0;
14963}
14964
14965static struct isa_driver advansys_isa_driver = {
14966 .probe = advansys_isa_probe,
14967 .remove = __devexit_p(advansys_isa_remove),
14968 .driver = {
14969 .owner = THIS_MODULE,
14970 .name = "advansys",
14971 },
14972};
14973
14974static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id)
14975{
14976 PortAddr iop_base = _asc_def_iop_base[id];
14977 struct Scsi_Host *shost;
14978
14979 if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) {
Matthew Wilcox71f361152007-07-30 08:04:53 -060014980 ASC_DBG1(1, "advansys_vlb_match: I/O port 0x%x busy\n",
14981 iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014982 return -ENODEV;
14983 }
14984 ASC_DBG1(1, "advansys_vlb_match: probing I/O port 0x%x\n", iop_base);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014985 if (!AscFindSignature(iop_base))
14986 goto nodev;
14987 /*
14988 * I don't think this condition can actually happen, but the old
14989 * driver did it, and the chances of finding a VLB setup in 2007
14990 * to do testing with is slight to none.
14991 */
14992 if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL)
14993 goto nodev;
14994
14995 shost = advansys_board_found(iop_base, dev, ASC_IS_VL);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060014996 if (!shost)
14997 goto nodev;
14998
14999 dev_set_drvdata(dev, shost);
15000 return 0;
15001
15002 nodev:
Matthew Wilcox71f361152007-07-30 08:04:53 -060015003 release_region(iop_base, ASC_IOADR_GAP);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015004 return -ENODEV;
15005}
15006
15007static struct isa_driver advansys_vlb_driver = {
15008 .probe = advansys_vlb_probe,
15009 .remove = __devexit_p(advansys_isa_remove),
15010 .driver = {
15011 .owner = THIS_MODULE,
Matthew Wilcoxb8e5152b2007-09-09 08:56:26 -060015012 .name = "advansys_vlb",
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015013 },
15014};
15015
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015016static struct eisa_device_id advansys_eisa_table[] __devinitdata = {
15017 { "ABP7401" },
15018 { "ABP7501" },
15019 { "" }
15020};
15021
15022MODULE_DEVICE_TABLE(eisa, advansys_eisa_table);
15023
15024/*
15025 * EISA is a little more tricky than PCI; each EISA device may have two
15026 * channels, and this driver is written to make each channel its own Scsi_Host
15027 */
15028struct eisa_scsi_data {
15029 struct Scsi_Host *host[2];
15030};
15031
15032static int __devinit advansys_eisa_probe(struct device *dev)
15033{
15034 int i, ioport;
15035 int err;
15036 struct eisa_device *edev = to_eisa_device(dev);
15037 struct eisa_scsi_data *data;
15038
15039 err = -ENOMEM;
15040 data = kzalloc(sizeof(*data), GFP_KERNEL);
15041 if (!data)
15042 goto fail;
15043 ioport = edev->base_addr + 0xc30;
15044
15045 err = -ENODEV;
15046 for (i = 0; i < 2; i++, ioport += 0x20) {
Matthew Wilcox71f361152007-07-30 08:04:53 -060015047 if (!request_region(ioport, ASC_IOADR_GAP, "advansys")) {
15048 printk(KERN_WARNING "Region %x-%x busy\n", ioport,
15049 ioport + ASC_IOADR_GAP - 1);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015050 continue;
Matthew Wilcox71f361152007-07-30 08:04:53 -060015051 }
15052 if (!AscFindSignature(ioport)) {
15053 release_region(ioport, ASC_IOADR_GAP);
15054 continue;
15055 }
15056
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015057 /*
15058 * I don't know why we need to do this for EISA chips, but
15059 * not for any others. It looks to be equivalent to
15060 * AscGetChipCfgMsw, but I may have overlooked something,
15061 * so I'm not converting it until I get an EISA board to
15062 * test with.
15063 */
15064 inw(ioport + 4);
15065 data->host[i] = advansys_board_found(ioport, dev, ASC_IS_EISA);
Matthew Wilcox71f361152007-07-30 08:04:53 -060015066 if (data->host[i]) {
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015067 err = 0;
Matthew Wilcox71f361152007-07-30 08:04:53 -060015068 } else {
15069 release_region(ioport, ASC_IOADR_GAP);
15070 }
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015071 }
15072
15073 if (err) {
15074 kfree(data);
15075 } else {
15076 dev_set_drvdata(dev, data);
15077 }
15078
15079 fail:
15080 return err;
15081}
15082
15083static __devexit int advansys_eisa_remove(struct device *dev)
15084{
15085 int i;
15086 struct eisa_scsi_data *data = dev_get_drvdata(dev);
15087
15088 for (i = 0; i < 2; i++) {
Matthew Wilcox71f361152007-07-30 08:04:53 -060015089 int ioport;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015090 struct Scsi_Host *shost = data->host[i];
15091 if (!shost)
15092 continue;
Matthew Wilcox71f361152007-07-30 08:04:53 -060015093 ioport = shost->io_port;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015094 advansys_release(shost);
Matthew Wilcox71f361152007-07-30 08:04:53 -060015095 release_region(ioport, ASC_IOADR_GAP);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015096 }
15097
15098 kfree(data);
15099 return 0;
15100}
15101
15102static struct eisa_driver advansys_eisa_driver = {
15103 .id_table = advansys_eisa_table,
15104 .driver = {
15105 .name = "advansys",
15106 .probe = advansys_eisa_probe,
15107 .remove = __devexit_p(advansys_eisa_remove),
15108 }
15109};
15110
Dave Jones2672ea82006-08-02 17:11:49 -040015111/* PCI Devices supported by this driver */
15112static struct pci_device_id advansys_pci_tbl[] __devinitdata = {
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015113 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A,
15114 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15115 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940,
15116 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15117 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940U,
15118 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15119 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_ABP940UW,
15120 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15121 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C0800_REV1,
15122 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15123 {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_38C1600_REV1,
15124 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
15125 {}
Dave Jones2672ea82006-08-02 17:11:49 -040015126};
Matthew Wilcox27c868c2007-07-26 10:56:23 -040015127
Dave Jones2672ea82006-08-02 17:11:49 -040015128MODULE_DEVICE_TABLE(pci, advansys_pci_tbl);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015129
Matthew Wilcox9649af32007-07-26 21:51:47 -060015130static void __devinit advansys_set_latency(struct pci_dev *pdev)
15131{
15132 if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) ||
15133 (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) {
15134 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0);
15135 } else {
15136 u8 latency;
15137 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
15138 if (latency < 0x20)
15139 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
15140 }
15141}
15142
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015143static int __devinit
15144advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
15145{
15146 int err, ioport;
15147 struct Scsi_Host *shost;
15148
15149 err = pci_enable_device(pdev);
15150 if (err)
15151 goto fail;
Matthew Wilcox71f361152007-07-30 08:04:53 -060015152 err = pci_request_regions(pdev, "advansys");
15153 if (err)
15154 goto disable_device;
Matthew Wilcox9649af32007-07-26 21:51:47 -060015155 pci_set_master(pdev);
15156 advansys_set_latency(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015157
15158 if (pci_resource_len(pdev, 0) == 0)
15159 goto nodev;
15160
15161 ioport = pci_resource_start(pdev, 0);
15162 shost = advansys_board_found(ioport, &pdev->dev, ASC_IS_PCI);
15163
15164 if (!shost)
15165 goto nodev;
15166
15167 pci_set_drvdata(pdev, shost);
15168 return 0;
15169
15170 nodev:
15171 err = -ENODEV;
Matthew Wilcox71f361152007-07-30 08:04:53 -060015172 pci_release_regions(pdev);
15173 disable_device:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015174 pci_disable_device(pdev);
15175 fail:
15176 return err;
15177}
15178
15179static void __devexit advansys_pci_remove(struct pci_dev *pdev)
15180{
15181 advansys_release(pci_get_drvdata(pdev));
Matthew Wilcox71f361152007-07-30 08:04:53 -060015182 pci_release_regions(pdev);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015183 pci_disable_device(pdev);
15184}
15185
15186static struct pci_driver advansys_pci_driver = {
15187 .name = "advansys",
15188 .id_table = advansys_pci_tbl,
15189 .probe = advansys_pci_probe,
15190 .remove = __devexit_p(advansys_pci_remove),
15191};
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015192
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015193static int __init advansys_init(void)
15194{
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015195 int error;
15196
15197 error = isa_register_driver(&advansys_isa_driver,
15198 ASC_IOADR_TABLE_MAX_IX);
15199 if (error)
15200 goto fail;
15201
15202 error = isa_register_driver(&advansys_vlb_driver,
15203 ASC_IOADR_TABLE_MAX_IX);
15204 if (error)
15205 goto unregister_isa;
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015206
15207 error = eisa_driver_register(&advansys_eisa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015208 if (error)
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015209 goto unregister_vlb;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015210
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015211 error = pci_register_driver(&advansys_pci_driver);
15212 if (error)
15213 goto unregister_eisa;
15214
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015215 return 0;
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015216
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015217 unregister_eisa:
15218 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015219 unregister_vlb:
15220 isa_unregister_driver(&advansys_vlb_driver);
15221 unregister_isa:
15222 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015223 fail:
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015224 return error;
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015225}
15226
15227static void __exit advansys_exit(void)
15228{
Matthew Wilcox78e77d82007-07-29 21:46:15 -060015229 pci_unregister_driver(&advansys_pci_driver);
Matthew Wilcoxb09e05a2007-07-30 09:14:52 -060015230 eisa_driver_unregister(&advansys_eisa_driver);
Matthew Wilcoxc304ec92007-07-30 09:18:45 -060015231 isa_unregister_driver(&advansys_vlb_driver);
15232 isa_unregister_driver(&advansys_isa_driver);
Matthew Wilcox8dfb5372007-07-30 09:08:34 -060015233}
15234
15235module_init(advansys_init);
15236module_exit(advansys_exit);
15237
Matthew Wilcox8c6af9e2007-07-26 11:03:19 -040015238MODULE_LICENSE("GPL");