|
|
1.1 root 1: /*
2: * QLogic ISP1020 Intelligent SCSI Processor Driver (PCI)
3: * Written by Erik H. Moe, [email protected]
4: * Copyright 1995, Erik H. Moe
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2, or (at your option) any
9: * later version.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * General Public License for more details.
15: */
16:
17: /* Renamed and updated to 1.3.x by Michael Griffith <[email protected]> */
18:
19: /*
20: * $Date: 1999/04/26 05:54:52 $
21: * $Revision: 1.1 $
22: *
23: * $Log: qlogicisp.c,v $
24: * Revision 1.1 1999/04/26 05:54:52 tb
25: * 1998-11-30 OKUJI Yoshinori <[email protected]>
26: *
27: * Clean up linux emulation code to make it architecture-independent
28: * as much as possible.
29: *
30: * * linux: Renamed from linuxdev.
31: * * Makefile.in (objfiles): Add linux.o instead of linuxdev.o.
32: * (MAKE): New variable. Used for the linux.o target.
33: * * configure.in: Add AC_CHECK_TOOL(MAKE, make).
34: * * i386/i386/spl.h: Include <i386/ipl.h>, for compatibility with
35: * OSF Mach 3.0. Suggested by Elgin Lee <[email protected]>.
36: * * linux/src: Renamed from linux/linux.
37: * * linux/dev: Renamed from linux/mach.
38: * * linux/Drivers.in (AC_INIT): Use dev/include/linux/autoconf.h,
39: * instead of mach/include/linux/autoconf.h.
40: * * Makefile.in (all): Target ../linux.o instead of ../linuxdev.o.
41: * * linux/dev/drivers/block/genhd.c: Include <machine/spl.h> instead
42: * of <i386/ipl.h>.
43: * * linux/dev/drivers/net/auto_irq.c: Remove unneeded header files,
44: * <i386/ipl.h> and <i386/pic.h>.
45: * * linux/dev/init/main.c: Many i386-dependent codes moved to ...
46: * * linux/dev/arch/i386/irq.c: ... here.
47: * * linux/dev/arch/i386/setup.c: New file.
48: * * linux/dev/arch/i386/linux_emul.h: Likewise.
49: * * linux/dev/arch/i386/glue/timer.c: Merged into sched.c.
50: * * linux/dev/arch/i386/glue/sched.c: Include <machine/spl.h> instead
51: * of <i386/ipl.h>, and moved to ...
52: * * linux/dev/kernel/sched.c: ... here.
53: * * linux/dev/arch/i386/glue/block.c: Include <machine/spl.h> and
54: * <linux_emul.h>, instead of i386-dependent header files, and
55: * moved to ...
56: * * linux/dev/glue/blocl.c: ... here.
57: * * linux/dev/arch/i386/glue/net.c: Include <machine/spl.h> and
58: * <linux_emul.h>, instead of i386-dependent header files, and
59: * moved to ...
60: * * linux/dev/glue/net.c: ... here.
61: * * linux/dev/arch/i386/glue/misc.c: Remove `x86' and moved to ...
62: * * linux/dev/glue/misc.c: ... here.
63: * * linux/dev/arch/i386/glue/kmem.c: Moved to ...
64: * * linux/dev/glue/kmem.c: ... here.
65: *
66: * Revision 0.5 1995/09/22 02:23:15 root
67: * do auto request sense
68: *
69: * Revision 0.4 1995/08/07 04:44:33 root
70: * supply firmware with driver.
71: * numerous bug fixes/general cleanup of code.
72: *
73: * Revision 0.3 1995/07/16 16:15:39 root
74: * added reset/abort code.
75: *
76: * Revision 0.2 1995/06/29 03:14:19 root
77: * fixed biosparam.
78: * added queue protocol.
79: *
80: * Revision 0.1 1995/06/25 01:55:45 root
81: * Initial release.
82: *
83: */
84:
85: #include <linux/blk.h>
86: #include <linux/kernel.h>
87: #include <linux/string.h>
88: #include <linux/ioport.h>
89: #include <linux/sched.h>
90: #include <linux/types.h>
91: #include <linux/bios32.h>
92: #include <linux/pci.h>
93: #include <linux/delay.h>
94: #include <linux/unistd.h>
95: #include <asm/io.h>
96: #include <asm/irq.h>
97:
98: #include "sd.h"
99: #include "hosts.h"
100: #include "qlogicisp.h"
101:
102: /* Configuration section *****************************************************/
103:
104: /* Set the following macro to 1 to reload the ISP1020's firmware. This is
105: the latest firmware provided by QLogic. This may be an earlier/later
106: revision than supplied by your board. */
107:
108: #define RELOAD_FIRMWARE 1
109:
110: /* Set the following macro to 1 to reload the ISP1020's defaults from nvram.
111: If you are not sure of your settings, leave this alone, the driver will
112: use a set of 'safe' defaults */
113:
114: #define USE_NVRAM_DEFAULTS 0
115:
116: /* Macros used for debugging */
117:
118: #define DEBUG_ISP1020 0
119: #define DEBUG_ISP1020_INT 0
120: #define DEBUG_ISP1020_SETUP 0
121: #define TRACE_ISP 0
122:
123: #define DEFAULT_LOOP_COUNT 1000000
124:
125: /* End Configuration section *************************************************/
126:
127: #include <linux/module.h>
128:
129: #if TRACE_ISP
130:
131: # define TRACE_BUF_LEN (32*1024)
132:
133: struct {
134: u_long next;
135: struct {
136: u_long time;
137: u_int index;
138: u_int addr;
139: u_char * name;
140: } buf[TRACE_BUF_LEN];
141: } trace;
142:
143: #define TRACE(w, i, a) \
144: { \
145: unsigned long flags; \
146: \
147: save_flags(flags); \
148: cli(); \
149: trace.buf[trace.next].name = (w); \
150: trace.buf[trace.next].time = jiffies; \
151: trace.buf[trace.next].index = (i); \
152: trace.buf[trace.next].addr = (long) (a); \
153: trace.next = (trace.next + 1) & (TRACE_BUF_LEN - 1); \
154: restore_flags(flags); \
155: }
156:
157: #else
158: # define TRACE(w, i, a)
159: #endif
160:
161: #if DEBUG_ISP1020
162: #define ENTER(x) printk("isp1020 : entering %s()\n", x);
163: #define LEAVE(x) printk("isp1020 : leaving %s()\n", x);
164: #define DEBUG(x) x
165: #else
166: #define ENTER(x)
167: #define LEAVE(x)
168: #define DEBUG(x)
169: #endif /* DEBUG_ISP1020 */
170:
171: #if DEBUG_ISP1020_INTR
172: #define ENTER_INTR(x) printk("isp1020 : entering %s()\n", x);
173: #define LEAVE_INTR(x) printk("isp1020 : leaving %s()\n", x);
174: #define DEBUG_INTR(x) x
175: #else
176: #define ENTER_INTR(x)
177: #define LEAVE_INTR(x)
178: #define DEBUG_INTR(x)
179: #endif /* DEBUG ISP1020_INTR */
180:
181: #define ISP1020_REV_ID 1
182:
183: #define MAX_TARGETS 16
184: #define MAX_LUNS 8
185:
186: /* host configuration and control registers */
187: #define HOST_HCCR 0xc0 /* host command and control */
188:
189: /* pci bus interface registers */
190: #define PCI_ID_LOW 0x00 /* vendor id */
191: #define PCI_ID_HIGH 0x02 /* device id */
192: #define ISP_CFG0 0x04 /* configuration register #0 */
193: #define ISP_CFG1 0x06 /* configuration register #1 */
194: #define PCI_INTF_CTL 0x08 /* pci interface control */
195: #define PCI_INTF_STS 0x0a /* pci interface status */
196: #define PCI_SEMAPHORE 0x0c /* pci semaphore */
197: #define PCI_NVRAM 0x0e /* pci nvram interface */
198:
199: /* mailbox registers */
200: #define MBOX0 0x70 /* mailbox 0 */
201: #define MBOX1 0x72 /* mailbox 1 */
202: #define MBOX2 0x74 /* mailbox 2 */
203: #define MBOX3 0x76 /* mailbox 3 */
204: #define MBOX4 0x78 /* mailbox 4 */
205: #define MBOX5 0x7a /* mailbox 5 */
206:
207: /* mailbox command complete status codes */
208: #define MBOX_COMMAND_COMPLETE 0x4000
209: #define INVALID_COMMAND 0x4001
210: #define HOST_INTERFACE_ERROR 0x4002
211: #define TEST_FAILED 0x4003
212: #define COMMAND_ERROR 0x4005
213: #define COMMAND_PARAM_ERROR 0x4006
214:
215: /* async event status codes */
216: #define ASYNC_SCSI_BUS_RESET 0x8001
217: #define SYSTEM_ERROR 0x8002
218: #define REQUEST_TRANSFER_ERROR 0x8003
219: #define RESPONSE_TRANSFER_ERROR 0x8004
220: #define REQUEST_QUEUE_WAKEUP 0x8005
221: #define EXECUTION_TIMEOUT_RESET 0x8006
222:
223: struct Entry_header {
224: u_char entry_type;
225: u_char entry_cnt;
226: u_char sys_def_1;
227: u_char flags;
228: };
229:
230: /* entry header type commands */
231: #define ENTRY_COMMAND 1
232: #define ENTRY_CONTINUATION 2
233: #define ENTRY_STATUS 3
234: #define ENTRY_MARKER 4
235: #define ENTRY_EXTENDED_COMMAND 5
236:
237: /* entry header flag definitions */
238: #define EFLAG_CONTINUATION 1
239: #define EFLAG_BUSY 2
240: #define EFLAG_BAD_HEADER 4
241: #define EFLAG_BAD_PAYLOAD 8
242:
243: struct dataseg {
244: u_int d_base;
245: u_int d_count;
246: };
247:
248: struct Command_Entry {
249: struct Entry_header hdr;
250: u_int handle;
251: u_char target_lun;
252: u_char target_id;
253: u_short cdb_length;
254: u_short control_flags;
255: u_short rsvd;
256: u_short time_out;
257: u_short segment_cnt;
258: u_char cdb[12];
259: struct dataseg dataseg[4];
260: };
261:
262: /* command entry control flag definitions */
263: #define CFLAG_NODISC 0x01
264: #define CFLAG_HEAD_TAG 0x02
265: #define CFLAG_ORDERED_TAG 0x04
266: #define CFLAG_SIMPLE_TAG 0x08
267: #define CFLAG_TAR_RTN 0x10
268: #define CFLAG_READ 0x20
269: #define CFLAG_WRITE 0x40
270:
271: struct Ext_Command_Entry {
272: struct Entry_header hdr;
273: u_int handle;
274: u_char target_lun;
275: u_char target_id;
276: u_short cdb_length;
277: u_short control_flags;
278: u_short rsvd;
279: u_short time_out;
280: u_short segment_cnt;
281: u_char cdb[44];
282: };
283:
284: struct Continuation_Entry {
285: struct Entry_header hdr;
286: u_int reserved;
287: struct dataseg dataseg[7];
288: };
289:
290: struct Marker_Entry {
291: struct Entry_header hdr;
292: u_int reserved;
293: u_char target_lun;
294: u_char target_id;
295: u_char modifier;
296: u_char rsvd;
297: u_char rsvds[52];
298: };
299:
300: /* marker entry modifier definitions */
301: #define SYNC_DEVICE 0
302: #define SYNC_TARGET 1
303: #define SYNC_ALL 2
304:
305: struct Status_Entry {
306: struct Entry_header hdr;
307: u_int handle;
308: u_short scsi_status;
309: u_short completion_status;
310: u_short state_flags;
311: u_short status_flags;
312: u_short time;
313: u_short req_sense_len;
314: u_int residual;
315: u_char rsvd[8];
316: u_char req_sense_data[32];
317: };
318:
319: /* status entry completion status definitions */
320: #define CS_COMPLETE 0x0000
321: #define CS_INCOMPLETE 0x0001
322: #define CS_DMA_ERROR 0x0002
323: #define CS_TRANSPORT_ERROR 0x0003
324: #define CS_RESET_OCCURRED 0x0004
325: #define CS_ABORTED 0x0005
326: #define CS_TIMEOUT 0x0006
327: #define CS_DATA_OVERRUN 0x0007
328: #define CS_COMMAND_OVERRUN 0x0008
329: #define CS_STATUS_OVERRUN 0x0009
330: #define CS_BAD_MESSAGE 0x000a
331: #define CS_NO_MESSAGE_OUT 0x000b
332: #define CS_EXT_ID_FAILED 0x000c
333: #define CS_IDE_MSG_FAILED 0x000d
334: #define CS_ABORT_MSG_FAILED 0x000e
335: #define CS_REJECT_MSG_FAILED 0x000f
336: #define CS_NOP_MSG_FAILED 0x0010
337: #define CS_PARITY_ERROR_MSG_FAILED 0x0011
338: #define CS_DEVICE_RESET_MSG_FAILED 0x0012
339: #define CS_ID_MSG_FAILED 0x0013
340: #define CS_UNEXP_BUS_FREE 0x0014
341: /* as per app note #83120-514-06a: */
342: #define CS_DATA_UNDERRUN 0x0015
343: #define CS_INVALID_ENTRY_TYPE 0x001b
344: #define CS_DEVICE_QUEUE_FULL 0x001c
345: #define CS_SCSI_PHASE_SKIPPED 0x001d
346: #define CS_ARS_FAILED 0x001e /* auto Req. Sense failed */
347:
348: /* status entry state flag definitions */
349: #define SF_GOT_BUS 0x0100
350: #define SF_GOT_TARGET 0x0200
351: #define SF_SENT_CDB 0x0400
352: #define SF_TRANSFERRED_DATA 0x0800
353: #define SF_GOT_STATUS 0x1000
354: #define SF_GOT_SENSE 0x2000
355:
356: /* status entry status flag definitions */
357: #define STF_DISCONNECT 0x0001
358: #define STF_SYNCHRONOUS 0x0002
359: #define STF_PARITY_ERROR 0x0004
360: #define STF_BUS_RESET 0x0008
361: #define STF_DEVICE_RESET 0x0010
362: #define STF_ABORTED 0x0020
363: #define STF_TIMEOUT 0x0040
364: #define STF_NEGOTIATION 0x0080
365:
366: /* interface control commands */
367: #define ISP_RESET 0x0001
368: #define ISP_EN_INT 0x0002
369: #define ISP_EN_RISC 0x0004
370:
371: /* host control commands */
372: #define HCCR_NOP 0x0000
373: #define HCCR_RESET 0x1000
374: #define HCCR_PAUSE 0x2000
375: #define HCCR_RELEASE 0x3000
376: #define HCCR_SINGLE_STEP 0x4000
377: #define HCCR_SET_HOST_INTR 0x5000
378: #define HCCR_CLEAR_HOST_INTR 0x6000
379: #define HCCR_CLEAR_RISC_INTR 0x7000
380: #define HCCR_BP_ENABLE 0x8000
381: #define HCCR_BIOS_DISABLE 0x9000
382: #define HCCR_TEST_MODE 0xf000
383:
384: #define RISC_BUSY 0x0004
385:
386: /* mailbox commands */
387: #define MBOX_NO_OP 0x0000
388: #define MBOX_LOAD_RAM 0x0001
389: #define MBOX_EXEC_FIRMWARE 0x0002
390: #define MBOX_DUMP_RAM 0x0003
391: #define MBOX_WRITE_RAM_WORD 0x0004
392: #define MBOX_READ_RAM_WORD 0x0005
393: #define MBOX_MAILBOX_REG_TEST 0x0006
394: #define MBOX_VERIFY_CHECKSUM 0x0007
395: #define MBOX_ABOUT_FIRMWARE 0x0008
396: #define MBOX_CHECK_FIRMWARE 0x000e
397: #define MBOX_INIT_REQ_QUEUE 0x0010
398: #define MBOX_INIT_RES_QUEUE 0x0011
399: #define MBOX_EXECUTE_IOCB 0x0012
400: #define MBOX_WAKE_UP 0x0013
401: #define MBOX_STOP_FIRMWARE 0x0014
402: #define MBOX_ABORT 0x0015
403: #define MBOX_ABORT_DEVICE 0x0016
404: #define MBOX_ABORT_TARGET 0x0017
405: #define MBOX_BUS_RESET 0x0018
406: #define MBOX_STOP_QUEUE 0x0019
407: #define MBOX_START_QUEUE 0x001a
408: #define MBOX_SINGLE_STEP_QUEUE 0x001b
409: #define MBOX_ABORT_QUEUE 0x001c
410: #define MBOX_GET_DEV_QUEUE_STATUS 0x001d
411: #define MBOX_GET_FIRMWARE_STATUS 0x001f
412: #define MBOX_GET_INIT_SCSI_ID 0x0020
413: #define MBOX_GET_SELECT_TIMEOUT 0x0021
414: #define MBOX_GET_RETRY_COUNT 0x0022
415: #define MBOX_GET_TAG_AGE_LIMIT 0x0023
416: #define MBOX_GET_CLOCK_RATE 0x0024
417: #define MBOX_GET_ACT_NEG_STATE 0x0025
418: #define MBOX_GET_ASYNC_DATA_SETUP_TIME 0x0026
419: #define MBOX_GET_PCI_PARAMS 0x0027
420: #define MBOX_GET_TARGET_PARAMS 0x0028
421: #define MBOX_GET_DEV_QUEUE_PARAMS 0x0029
422: #define MBOX_SET_INIT_SCSI_ID 0x0030
423: #define MBOX_SET_SELECT_TIMEOUT 0x0031
424: #define MBOX_SET_RETRY_COUNT 0x0032
425: #define MBOX_SET_TAG_AGE_LIMIT 0x0033
426: #define MBOX_SET_CLOCK_RATE 0x0034
427: #define MBOX_SET_ACTIVE_NEG_STATE 0x0035
428: #define MBOX_SET_ASYNC_DATA_SETUP_TIME 0x0036
429: #define MBOX_SET_PCI_CONTROL_PARAMS 0x0037
430: #define MBOX_SET_TARGET_PARAMS 0x0038
431: #define MBOX_SET_DEV_QUEUE_PARAMS 0x0039
432: #define MBOX_RETURN_BIOS_BLOCK_ADDR 0x0040
433: #define MBOX_WRITE_FOUR_RAM_WORDS 0x0041
434: #define MBOX_EXEC_BIOS_IOCB 0x0042
435:
436: #include "qlogicisp_asm.c"
437:
438: #define PACKB(a, b) (((a)<<4)|(b))
439:
440: const u_char mbox_param[] = {
441: PACKB(1, 1), /* MBOX_NO_OP */
442: PACKB(5, 5), /* MBOX_LOAD_RAM */
443: PACKB(2, 0), /* MBOX_EXEC_FIRMWARE */
444: PACKB(5, 5), /* MBOX_DUMP_RAM */
445: PACKB(3, 3), /* MBOX_WRITE_RAM_WORD */
446: PACKB(2, 3), /* MBOX_READ_RAM_WORD */
447: PACKB(6, 6), /* MBOX_MAILBOX_REG_TEST */
448: PACKB(2, 3), /* MBOX_VERIFY_CHECKSUM */
449: PACKB(1, 3), /* MBOX_ABOUT_FIRMWARE */
450: PACKB(0, 0), /* 0x0009 */
451: PACKB(0, 0), /* 0x000a */
452: PACKB(0, 0), /* 0x000b */
453: PACKB(0, 0), /* 0x000c */
454: PACKB(0, 0), /* 0x000d */
455: PACKB(1, 2), /* MBOX_CHECK_FIRMWARE */
456: PACKB(0, 0), /* 0x000f */
457: PACKB(5, 5), /* MBOX_INIT_REQ_QUEUE */
458: PACKB(6, 6), /* MBOX_INIT_RES_QUEUE */
459: PACKB(4, 4), /* MBOX_EXECUTE_IOCB */
460: PACKB(2, 2), /* MBOX_WAKE_UP */
461: PACKB(1, 6), /* MBOX_STOP_FIRMWARE */
462: PACKB(4, 4), /* MBOX_ABORT */
463: PACKB(2, 2), /* MBOX_ABORT_DEVICE */
464: PACKB(3, 3), /* MBOX_ABORT_TARGET */
465: PACKB(2, 2), /* MBOX_BUS_RESET */
466: PACKB(2, 3), /* MBOX_STOP_QUEUE */
467: PACKB(2, 3), /* MBOX_START_QUEUE */
468: PACKB(2, 3), /* MBOX_SINGLE_STEP_QUEUE */
469: PACKB(2, 3), /* MBOX_ABORT_QUEUE */
470: PACKB(2, 4), /* MBOX_GET_DEV_QUEUE_STATUS */
471: PACKB(0, 0), /* 0x001e */
472: PACKB(1, 3), /* MBOX_GET_FIRMWARE_STATUS */
473: PACKB(1, 2), /* MBOX_GET_INIT_SCSI_ID */
474: PACKB(1, 2), /* MBOX_GET_SELECT_TIMEOUT */
475: PACKB(1, 3), /* MBOX_GET_RETRY_COUNT */
476: PACKB(1, 2), /* MBOX_GET_TAG_AGE_LIMIT */
477: PACKB(1, 2), /* MBOX_GET_CLOCK_RATE */
478: PACKB(1, 2), /* MBOX_GET_ACT_NEG_STATE */
479: PACKB(1, 2), /* MBOX_GET_ASYNC_DATA_SETUP_TIME */
480: PACKB(1, 3), /* MBOX_GET_PCI_PARAMS */
481: PACKB(2, 4), /* MBOX_GET_TARGET_PARAMS */
482: PACKB(2, 4), /* MBOX_GET_DEV_QUEUE_PARAMS */
483: PACKB(0, 0), /* 0x002a */
484: PACKB(0, 0), /* 0x002b */
485: PACKB(0, 0), /* 0x002c */
486: PACKB(0, 0), /* 0x002d */
487: PACKB(0, 0), /* 0x002e */
488: PACKB(0, 0), /* 0x002f */
489: PACKB(2, 2), /* MBOX_SET_INIT_SCSI_ID */
490: PACKB(2, 2), /* MBOX_SET_SELECT_TIMEOUT */
491: PACKB(3, 3), /* MBOX_SET_RETRY_COUNT */
492: PACKB(2, 2), /* MBOX_SET_TAG_AGE_LIMIT */
493: PACKB(2, 2), /* MBOX_SET_CLOCK_RATE */
494: PACKB(2, 2), /* MBOX_SET_ACTIVE_NEG_STATE */
495: PACKB(2, 2), /* MBOX_SET_ASYNC_DATA_SETUP_TIME */
496: PACKB(3, 3), /* MBOX_SET_PCI_CONTROL_PARAMS */
497: PACKB(4, 4), /* MBOX_SET_TARGET_PARAMS */
498: PACKB(4, 4), /* MBOX_SET_DEV_QUEUE_PARAMS */
499: PACKB(0, 0), /* 0x003a */
500: PACKB(0, 0), /* 0x003b */
501: PACKB(0, 0), /* 0x003c */
502: PACKB(0, 0), /* 0x003d */
503: PACKB(0, 0), /* 0x003e */
504: PACKB(0, 0), /* 0x003f */
505: PACKB(1, 2), /* MBOX_RETURN_BIOS_BLOCK_ADDR */
506: PACKB(6, 1), /* MBOX_WRITE_FOUR_RAM_WORDS */
507: PACKB(2, 3) /* MBOX_EXEC_BIOS_IOCB */
508: };
509:
510: #define MAX_MBOX_COMMAND (sizeof(mbox_param)/sizeof(u_short))
511:
512: struct host_param {
513: u_short fifo_threshold;
514: u_short host_adapter_enable;
515: u_short initiator_scsi_id;
516: u_short bus_reset_delay;
517: u_short retry_count;
518: u_short retry_delay;
519: u_short async_data_setup_time;
520: u_short req_ack_active_negation;
521: u_short data_line_active_negation;
522: u_short data_dma_burst_enable;
523: u_short command_dma_burst_enable;
524: u_short tag_aging;
525: u_short selection_timeout;
526: u_short max_queue_depth;
527: };
528:
529: /*
530: * Device Flags:
531: *
532: * Bit Name
533: * ---------
534: * 7 Disconnect Privilege
535: * 6 Parity Checking
536: * 5 Wide Data Transfers
537: * 4 Synchronous Data Transfers
538: * 3 Tagged Queuing
539: * 2 Automatic Request Sense
540: * 1 Stop Queue on Check Condition
541: * 0 Renegotiate on Error
542: */
543:
544: struct dev_param {
545: u_short device_flags;
546: u_short execution_throttle;
547: u_short synchronous_period;
548: u_short synchronous_offset;
549: u_short device_enable;
550: u_short reserved; /* pad */
551: };
552:
553: /*
554: * The result queue can be quite a bit smaller since continuation entries
555: * do not show up there:
556: */
557: #define RES_QUEUE_LEN ((QLOGICISP_REQ_QUEUE_LEN + 1) / 8 - 1)
558: #define QUEUE_ENTRY_LEN 64
559:
560: struct isp1020_hostdata {
561: u_char bus;
562: u_char revision;
563: u_char device_fn;
564: struct host_param host_param;
565: struct dev_param dev_param[MAX_TARGETS];
566:
567: /* result and request queues (shared with isp1020): */
568: u_int req_in_ptr; /* index of next request slot */
569: u_int res_out_ptr; /* index of next result slot */
570:
571: /* this is here so the queues are nicely aligned */
572: long send_marker; /* do we need to send a marker? */
573:
574: char res[RES_QUEUE_LEN+1][QUEUE_ENTRY_LEN];
575: char req[QLOGICISP_REQ_QUEUE_LEN+1][QUEUE_ENTRY_LEN];
576: };
577:
578: /* queue length's _must_ be power of two: */
579: #define QUEUE_DEPTH(in, out, ql) ((in - out) & (ql))
580: #define REQ_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, \
581: QLOGICISP_REQ_QUEUE_LEN)
582: #define RES_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
583:
584: struct Scsi_Host *irq2host[NR_IRQS];
585:
586: static void isp1020_enable_irqs(struct Scsi_Host *);
587: static void isp1020_disable_irqs(struct Scsi_Host *);
588: static int isp1020_init(struct Scsi_Host *);
589: static int isp1020_reset_hardware(struct Scsi_Host *);
590: static int isp1020_set_defaults(struct Scsi_Host *);
591: static int isp1020_load_parameters(struct Scsi_Host *);
592: static int isp1020_mbox_command(struct Scsi_Host *, u_short []);
593: static int isp1020_return_status(struct Status_Entry *);
594: static void isp1020_intr_handler(int, void *, struct pt_regs *);
595:
596: #if USE_NVRAM_DEFAULTS
597: static int isp1020_get_defaults(struct Scsi_Host *);
598: static int isp1020_verify_nvram(struct Scsi_Host *);
599: static u_short isp1020_read_nvram_word(struct Scsi_Host *, u_short);
600: #endif
601:
602: #if DEBUG_ISP1020
603: static void isp1020_print_scsi_cmd(Scsi_Cmnd *);
604: #endif
605: #if DEBUG_ISP1020_INTR
606: static void isp1020_print_status_entry(struct Status_Entry *);
607: #endif
608:
609: static struct proc_dir_entry proc_scsi_isp1020 = {
610: PROC_SCSI_QLOGICISP, 7, "isp1020",
611: S_IFDIR | S_IRUGO | S_IXUGO, 2
612: };
613:
614:
615: static inline void isp1020_enable_irqs(struct Scsi_Host *host)
616: {
617: outw(ISP_EN_INT|ISP_EN_RISC, host->io_port + PCI_INTF_CTL);
618: }
619:
620:
621: static inline void isp1020_disable_irqs(struct Scsi_Host *host)
622: {
623: outw(0x0, host->io_port + PCI_INTF_CTL);
624: }
625:
626:
627: int isp1020_detect(Scsi_Host_Template *tmpt)
628: {
629: int hosts = 0;
630: u_short index;
631: u_char bus, device_fn;
632: struct Scsi_Host *host;
633: struct isp1020_hostdata *hostdata;
634:
635: ENTER("isp1020_detect");
636:
637: tmpt->proc_dir = &proc_scsi_isp1020;
638:
639: if (pcibios_present() == 0) {
640: printk("qlogicisp : PCI bios not present\n");
641: return 0;
642: }
643:
644: memset(irq2host, 0, sizeof(irq2host));
645:
646: for (index = 0; pcibios_find_device(PCI_VENDOR_ID_QLOGIC,
647: PCI_DEVICE_ID_QLOGIC_ISP1020,
648: index, &bus, &device_fn) == 0;
649: index++)
650: {
651: host = scsi_register(tmpt, sizeof(struct isp1020_hostdata));
652: hostdata = (struct isp1020_hostdata *) host->hostdata;
653:
654: memset(hostdata, 0, sizeof(struct isp1020_hostdata));
655: hostdata->bus = bus;
656: hostdata->device_fn = device_fn;
657:
658: if (isp1020_init(host) || isp1020_reset_hardware(host)
659: #if USE_NVRAM_DEFAULTS
660: || isp1020_get_defaults(host)
661: #else
662: || isp1020_set_defaults(host)
663: #endif /* USE_NVRAM_DEFAULTS */
664: || isp1020_load_parameters(host)) {
665: scsi_unregister(host);
666: continue;
667: }
668:
669: host->this_id = hostdata->host_param.initiator_scsi_id;
670:
671: if (request_irq(host->irq, isp1020_intr_handler, SA_INTERRUPT,
672: "qlogicisp", NULL))
673: {
674: printk("qlogicisp : interrupt %d already in use\n",
675: host->irq);
676: scsi_unregister(host);
677: continue;
678: }
679:
680: if (check_region(host->io_port, 0xff)) {
681: printk("qlogicisp : i/o region 0x%04x-0x%04x already "
682: "in use\n",
683: host->io_port, host->io_port + 0xff);
684: free_irq(host->irq, NULL);
685: scsi_unregister(host);
686: continue;
687: }
688:
689: request_region(host->io_port, 0xff, "qlogicisp");
690: irq2host[host->irq] = host;
691:
692: outw(0x0, host->io_port + PCI_SEMAPHORE);
693: outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
694: isp1020_enable_irqs(host);
695:
696: hosts++;
697: }
698:
699: LEAVE("isp1020_detect");
700:
701: return hosts;
702: }
703:
704:
705: int isp1020_release(struct Scsi_Host *host)
706: {
707: struct isp1020_hostdata *hostdata;
708:
709: ENTER("isp1020_release");
710:
711: hostdata = (struct isp1020_hostdata *) host->hostdata;
712:
713: outw(0x0, host->io_port + PCI_INTF_CTL);
714: free_irq(host->irq, NULL);
715:
716: release_region(host->io_port, 0xff);
717:
718: LEAVE("isp1020_release");
719:
720: return 0;
721: }
722:
723:
724: const char *isp1020_info(struct Scsi_Host *host)
725: {
726: static char buf[80];
727: struct isp1020_hostdata *hostdata;
728:
729: ENTER("isp1020_info");
730:
731: hostdata = (struct isp1020_hostdata *) host->hostdata;
732: sprintf(buf,
733: "QLogic ISP1020 SCSI on PCI bus %d device %d irq %d base 0x%x",
734: hostdata->bus, (hostdata->device_fn & 0xf8) >> 3, host->irq,
735: host->io_port);
736:
737: LEAVE("isp1020_info");
738:
739: return buf;
740: }
741:
742:
743: /*
744: * The middle SCSI layer ensures that queuecommand never gets invoked
745: * concurrently with itself or the interrupt handler (though the
746: * interrupt handler may call this routine as part of
747: * request-completion handling).
748: */
749: int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
750: {
751: int i, sg_count, n, num_free;
752: u_int in_ptr, out_ptr;
753: struct dataseg * ds;
754: struct scatterlist *sg;
755: struct Command_Entry *cmd;
756: struct Continuation_Entry *cont;
757: struct Scsi_Host *host;
758: struct isp1020_hostdata *hostdata;
759:
760: ENTER("isp1020_queuecommand");
761:
762: host = Cmnd->host;
763: hostdata = (struct isp1020_hostdata *) host->hostdata;
764: Cmnd->scsi_done = done;
765:
766: DEBUG(isp1020_print_scsi_cmd(Cmnd));
767:
768: out_ptr = inw(host->io_port + MBOX4);
769: in_ptr = hostdata->req_in_ptr;
770:
771: DEBUG(printk("qlogicisp : request queue depth %d\n",
772: REQ_QUEUE_DEPTH(in_ptr, out_ptr)));
773:
774: cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
775: in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN;
776: if (in_ptr == out_ptr) {
777: printk("qlogicisp : request queue overflow\n");
778: return 1;
779: }
780:
781: if (hostdata->send_marker) {
782: struct Marker_Entry *marker;
783:
784: TRACE("queue marker", in_ptr, 0);
785:
786: DEBUG(printk("qlogicisp : adding marker entry\n"));
787: marker = (struct Marker_Entry *) cmd;
788: memset(marker, 0, sizeof(struct Marker_Entry));
789:
790: marker->hdr.entry_type = ENTRY_MARKER;
791: marker->hdr.entry_cnt = 1;
792: marker->modifier = SYNC_ALL;
793:
794: hostdata->send_marker = 0;
795:
796: if (((in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN) == out_ptr) {
797: outw(in_ptr, host->io_port + MBOX4);
798: hostdata->req_in_ptr = in_ptr;
799: printk("qlogicisp : request queue overflow\n");
800: return 1;
801: }
802: cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
803: in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN;
804: }
805:
806: TRACE("queue command", in_ptr, Cmnd);
807:
808: memset(cmd, 0, sizeof(struct Command_Entry));
809:
810: cmd->hdr.entry_type = ENTRY_COMMAND;
811: cmd->hdr.entry_cnt = 1;
812:
813: cmd->handle = (u_int) virt_to_bus(Cmnd);
814: cmd->target_lun = Cmnd->lun;
815: cmd->target_id = Cmnd->target;
816: cmd->cdb_length = Cmnd->cmd_len;
817: cmd->control_flags = CFLAG_READ | CFLAG_WRITE;
818: cmd->time_out = 30;
819:
820: memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
821:
822: if (Cmnd->use_sg) {
823: cmd->segment_cnt = sg_count = Cmnd->use_sg;
824: sg = (struct scatterlist *) Cmnd->request_buffer;
825: ds = cmd->dataseg;
826:
827: /* fill in first four sg entries: */
828: n = sg_count;
829: if (n > 4)
830: n = 4;
831: for (i = 0; i < n; i++) {
832: ds[i].d_base = (u_int) virt_to_bus(sg->address);
833: ds[i].d_count = sg->length;
834: ++sg;
835: }
836: sg_count -= 4;
837:
838: while (sg_count > 0) {
839: ++cmd->hdr.entry_cnt;
840: cont = (struct Continuation_Entry *)
841: &hostdata->req[in_ptr][0];
842: in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN;
843: if (in_ptr == out_ptr) {
844: printk("isp1020: unexpected request queue "
845: "overflow\n");
846: return 1;
847: }
848: TRACE("queue continuation", in_ptr, 0);
849: cont->hdr.entry_type = ENTRY_CONTINUATION;
850: cont->hdr.entry_cnt = 0;
851: cont->hdr.sys_def_1 = 0;
852: cont->hdr.flags = 0;
853: cont->reserved = 0;
854: ds = cont->dataseg;
855: n = sg_count;
856: if (n > 7)
857: n = 7;
858: for (i = 0; i < n; ++i) {
859: ds[i].d_base = (u_int)virt_to_bus(sg->address);
860: ds[i].d_count = sg->length;
861: ++sg;
862: }
863: sg_count -= n;
864: }
865: } else {
866: cmd->dataseg[0].d_base =
867: (u_int) virt_to_bus(Cmnd->request_buffer);
868: cmd->dataseg[0].d_count =
869: (u_int) Cmnd->request_bufflen;
870: cmd->segment_cnt = 1;
871: }
872:
873: outw(in_ptr, host->io_port + MBOX4);
874: hostdata->req_in_ptr = in_ptr;
875:
876: num_free = QLOGICISP_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
877: host->can_queue = host->host_busy + num_free;
878: host->sg_tablesize = QLOGICISP_MAX_SG(num_free);
879:
880: LEAVE("isp1020_queuecommand");
881:
882: return 0;
883: }
884:
885:
886: #define ASYNC_EVENT_INTERRUPT 0x01
887:
888: void isp1020_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
889: {
890: Scsi_Cmnd *Cmnd;
891: struct Status_Entry *sts;
892: struct Scsi_Host *host;
893: struct isp1020_hostdata *hostdata;
894: u_int in_ptr, out_ptr;
895: u_short status;
896:
897: ENTER_INTR("isp1020_intr_handler");
898:
899: host = irq2host[irq];
900: if (!host) {
901: printk("qlogicisp : unexpected interrupt on line %d\n", irq);
902: return;
903: }
904: hostdata = (struct isp1020_hostdata *) host->hostdata;
905:
906: DEBUG_INTR(printk("qlogicisp : interrupt on line %d\n", irq));
907:
908: if (!(inw(host->io_port + PCI_INTF_STS) & 0x04)) {
909: /* spurious interrupts can happen legally */
910: DEBUG_INTR(printk("qlogicisp: got spurious interrupt\n"));
911: return;
912: }
913: in_ptr = inw(host->io_port + MBOX5);
914: outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
915:
916: if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {
917: status = inw(host->io_port + MBOX0);
918:
919: DEBUG_INTR(printk("qlogicisp : mbox completion status: %x\n",
920: status));
921:
922: switch (status) {
923: case ASYNC_SCSI_BUS_RESET:
924: case EXECUTION_TIMEOUT_RESET:
925: hostdata->send_marker = 1;
926: break;
927: case INVALID_COMMAND:
928: case HOST_INTERFACE_ERROR:
929: case COMMAND_ERROR:
930: case COMMAND_PARAM_ERROR:
931: printk("qlogicisp : bad mailbox return status\n");
932: break;
933: }
934: outw(0x0, host->io_port + PCI_SEMAPHORE);
935: }
936: out_ptr = hostdata->res_out_ptr;
937:
938: DEBUG_INTR(printk("qlogicisp : response queue update\n"));
939: DEBUG_INTR(printk("qlogicisp : response queue depth %d\n",
940: QUEUE_DEPTH(in_ptr, out_ptr)));
941:
942: while (out_ptr != in_ptr) {
943: sts = (struct Status_Entry *) &hostdata->res[out_ptr][0];
944: out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
945:
946: Cmnd = (Scsi_Cmnd *) bus_to_virt(sts->handle);
947:
948: TRACE("done", out_ptr, Cmnd);
949:
950: if (sts->completion_status == CS_RESET_OCCURRED
951: || sts->completion_status == CS_ABORTED
952: || (sts->status_flags & STF_BUS_RESET))
953: hostdata->send_marker = 1;
954:
955: if (sts->state_flags & SF_GOT_SENSE)
956: memcpy(Cmnd->sense_buffer, sts->req_sense_data,
957: sizeof(Cmnd->sense_buffer));
958:
959: DEBUG_INTR(isp1020_print_status_entry(sts));
960:
961: if (sts->hdr.entry_type == ENTRY_STATUS)
962: Cmnd->result = isp1020_return_status(sts);
963: else
964: Cmnd->result = DID_ERROR << 16;
965:
966: outw(out_ptr, host->io_port + MBOX5);
967: (*Cmnd->scsi_done)(Cmnd);
968: }
969: hostdata->res_out_ptr = out_ptr;
970:
971: LEAVE_INTR("isp1020_intr_handler");
972: }
973:
974:
975: static int isp1020_return_status(struct Status_Entry *sts)
976: {
977: int host_status = DID_ERROR;
978: #if DEBUG_ISP1020_INTR
979: static char *reason[] = {
980: "DID_OK",
981: "DID_NO_CONNECT",
982: "DID_BUS_BUSY",
983: "DID_TIME_OUT",
984: "DID_BAD_TARGET",
985: "DID_ABORT",
986: "DID_PARITY",
987: "DID_ERROR",
988: "DID_RESET",
989: "DID_BAD_INTR"
990: };
991: #endif /* DEBUG_ISP1020_INTR */
992:
993: ENTER("isp1020_return_status");
994:
995: DEBUG(printk("qlogicisp : completion status = 0x%04x\n",
996: sts->completion_status));
997:
998: switch(sts->completion_status) {
999: case CS_COMPLETE:
1000: host_status = DID_OK;
1001: break;
1002: case CS_INCOMPLETE:
1003: if (!(sts->state_flags & SF_GOT_BUS))
1004: host_status = DID_NO_CONNECT;
1005: else if (!(sts->state_flags & SF_GOT_TARGET))
1006: host_status = DID_BAD_TARGET;
1007: else if (!(sts->state_flags & SF_SENT_CDB))
1008: host_status = DID_ERROR;
1009: else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
1010: host_status = DID_ERROR;
1011: else if (!(sts->state_flags & SF_GOT_STATUS))
1012: host_status = DID_ERROR;
1013: else if (!(sts->state_flags & SF_GOT_SENSE))
1014: host_status = DID_ERROR;
1015: break;
1016: case CS_DMA_ERROR:
1017: case CS_TRANSPORT_ERROR:
1018: host_status = DID_ERROR;
1019: break;
1020: case CS_RESET_OCCURRED:
1021: host_status = DID_RESET;
1022: break;
1023: case CS_ABORTED:
1024: host_status = DID_ABORT;
1025: break;
1026: case CS_TIMEOUT:
1027: host_status = DID_TIME_OUT;
1028: break;
1029: case CS_DATA_OVERRUN:
1030: case CS_COMMAND_OVERRUN:
1031: case CS_STATUS_OVERRUN:
1032: case CS_BAD_MESSAGE:
1033: case CS_NO_MESSAGE_OUT:
1034: case CS_EXT_ID_FAILED:
1035: case CS_IDE_MSG_FAILED:
1036: case CS_ABORT_MSG_FAILED:
1037: case CS_NOP_MSG_FAILED:
1038: case CS_PARITY_ERROR_MSG_FAILED:
1039: case CS_DEVICE_RESET_MSG_FAILED:
1040: case CS_ID_MSG_FAILED:
1041: case CS_UNEXP_BUS_FREE:
1042: case CS_INVALID_ENTRY_TYPE:
1043: case CS_DEVICE_QUEUE_FULL:
1044: case CS_SCSI_PHASE_SKIPPED:
1045: case CS_ARS_FAILED:
1046: host_status = DID_ERROR;
1047: break;
1048: case CS_DATA_UNDERRUN:
1049: host_status = DID_OK;
1050: break;
1051: default:
1052: printk("qlogicisp : unknown completion status 0x%04x\n",
1053: sts->completion_status);
1054: host_status = DID_ERROR;
1055: break;
1056: }
1057:
1058: DEBUG_INTR(printk("qlogicisp : host status (%s) scsi status %x\n",
1059: reason[host_status], sts->scsi_status));
1060:
1061: LEAVE("isp1020_return_status");
1062:
1063: return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
1064: }
1065:
1066:
1067: int isp1020_abort(Scsi_Cmnd *Cmnd)
1068: {
1069: u_short param[6];
1070: struct Scsi_Host *host;
1071: struct isp1020_hostdata *hostdata;
1072: int return_status = SCSI_ABORT_SUCCESS;
1073: u_int cmdaddr = virt_to_bus(Cmnd);
1074:
1075: ENTER("isp1020_abort");
1076:
1077: host = Cmnd->host;
1078: hostdata = (struct isp1020_hostdata *) host->hostdata;
1079:
1080: isp1020_disable_irqs(host);
1081:
1082: param[0] = MBOX_ABORT;
1083: param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;
1084: param[2] = cmdaddr >> 16;
1085: param[3] = cmdaddr & 0xffff;
1086:
1087: isp1020_mbox_command(host, param);
1088:
1089: if (param[0] != MBOX_COMMAND_COMPLETE) {
1090: printk("qlogicisp : scsi abort failure: %x\n", param[0]);
1091: return_status = SCSI_ABORT_ERROR;
1092: }
1093:
1094: isp1020_enable_irqs(host);
1095:
1096: LEAVE("isp1020_abort");
1097:
1098: return return_status;
1099: }
1100:
1101:
1102: int isp1020_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
1103: {
1104: u_short param[6];
1105: struct Scsi_Host *host;
1106: struct isp1020_hostdata *hostdata;
1107: int return_status = SCSI_RESET_SUCCESS;
1108:
1109: ENTER("isp1020_reset");
1110:
1111: host = Cmnd->host;
1112: hostdata = (struct isp1020_hostdata *) host->hostdata;
1113:
1114: param[0] = MBOX_BUS_RESET;
1115: param[1] = hostdata->host_param.bus_reset_delay;
1116:
1117: isp1020_disable_irqs(host);
1118:
1119: isp1020_mbox_command(host, param);
1120:
1121: if (param[0] != MBOX_COMMAND_COMPLETE) {
1122: printk("qlogicisp : scsi bus reset failure: %x\n", param[0]);
1123: return_status = SCSI_RESET_ERROR;
1124: }
1125:
1126: isp1020_enable_irqs(host);
1127:
1128: LEAVE("isp1020_reset");
1129:
1130: return return_status;;
1131: }
1132:
1133:
1134: int isp1020_biosparam(Disk *disk, kdev_t n, int ip[])
1135: {
1136: int size = disk->capacity;
1137:
1138: ENTER("isp1020_biosparam");
1139:
1140: ip[0] = 64;
1141: ip[1] = 32;
1142: ip[2] = size >> 11;
1143: if (ip[2] > 1024) {
1144: ip[0] = 255;
1145: ip[1] = 63;
1146: ip[2] = size / (ip[0] * ip[1]);
1147: if (ip[2] > 1023)
1148: ip[2] = 1023;
1149: }
1150:
1151: LEAVE("isp1020_biosparam");
1152:
1153: return 0;
1154: }
1155:
1156:
1157: static int isp1020_reset_hardware(struct Scsi_Host *host)
1158: {
1159: u_short param[6];
1160: int loop_count;
1161:
1162: ENTER("isp1020_reset_hardware");
1163:
1164: outw(ISP_RESET, host->io_port + PCI_INTF_CTL);
1165: outw(HCCR_RESET, host->io_port + HOST_HCCR);
1166: outw(HCCR_RELEASE, host->io_port + HOST_HCCR);
1167: outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR);
1168:
1169: loop_count = DEFAULT_LOOP_COUNT;
1170: while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY)
1171: barrier();
1172: if (!loop_count)
1173: printk("qlogicisp: reset_hardware loop timeout\n");
1174:
1175: outw(0, host->io_port + ISP_CFG1);
1176:
1177: #if DEBUG_ISP1020
1178: printk("qlogicisp : mbox 0 0x%04x \n", inw(host->io_port + MBOX0));
1179: printk("qlogicisp : mbox 1 0x%04x \n", inw(host->io_port + MBOX1));
1180: printk("qlogicisp : mbox 2 0x%04x \n", inw(host->io_port + MBOX2));
1181: printk("qlogicisp : mbox 3 0x%04x \n", inw(host->io_port + MBOX3));
1182: printk("qlogicisp : mbox 4 0x%04x \n", inw(host->io_port + MBOX4));
1183: printk("qlogicisp : mbox 5 0x%04x \n", inw(host->io_port + MBOX5));
1184: #endif /* DEBUG_ISP1020 */
1185:
1186: DEBUG(printk("qlogicisp : loading risc ram\n"));
1187:
1188: #if RELOAD_FIRMWARE
1189: {
1190: int i;
1191: for (i = 0; i < risc_code_length01; i++) {
1192: param[0] = MBOX_WRITE_RAM_WORD;
1193: param[1] = risc_code_addr01 + i;
1194: param[2] = risc_code01[i];
1195:
1196: isp1020_mbox_command(host, param);
1197:
1198: if (param[0] != MBOX_COMMAND_COMPLETE) {
1199: printk("qlogicisp : firmware load failure\n");
1200: return 1;
1201: }
1202: }
1203: }
1204: #endif /* RELOAD_FIRMWARE */
1205:
1206: DEBUG(printk("qlogicisp : verifying checksum\n"));
1207:
1208: param[0] = MBOX_VERIFY_CHECKSUM;
1209: param[1] = risc_code_addr01;
1210:
1211: isp1020_mbox_command(host, param);
1212:
1213: if (param[0] != MBOX_COMMAND_COMPLETE) {
1214: printk("qlogicisp : ram checksum failure\n");
1215: return 1;
1216: }
1217:
1218: DEBUG(printk("qlogicisp : executing firmware\n"));
1219:
1220: param[0] = MBOX_EXEC_FIRMWARE;
1221: param[1] = risc_code_addr01;
1222:
1223: isp1020_mbox_command(host, param);
1224:
1225: param[0] = MBOX_ABOUT_FIRMWARE;
1226:
1227: isp1020_mbox_command(host, param);
1228:
1229: if (param[0] != MBOX_COMMAND_COMPLETE) {
1230: printk("qlogicisp : about firmware failure\n");
1231: return 1;
1232: }
1233:
1234: DEBUG(printk("qlogicisp : firmware major revision %d\n", param[1]));
1235: DEBUG(printk("qlogicisp : firmware minor revision %d\n", param[2]));
1236:
1237: LEAVE("isp1020_reset_hardware");
1238:
1239: return 0;
1240: }
1241:
1242:
1243: static int isp1020_init(struct Scsi_Host *sh)
1244: {
1245: u_int io_base;
1246: struct isp1020_hostdata *hostdata;
1247: u_char bus, device_fn, revision, irq;
1248: u_short vendor_id, device_id, command;
1249:
1250: ENTER("isp1020_init");
1251:
1252: hostdata = (struct isp1020_hostdata *) sh->hostdata;
1253: bus = hostdata->bus;
1254: device_fn = hostdata->device_fn;
1255:
1256: if (pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id)
1257: || pcibios_read_config_word(bus, device_fn,
1258: PCI_DEVICE_ID, &device_id)
1259: || pcibios_read_config_word(bus, device_fn,
1260: PCI_COMMAND, &command)
1261: || pcibios_read_config_dword(bus, device_fn,
1262: PCI_BASE_ADDRESS_0, &io_base)
1263: || pcibios_read_config_byte(bus, device_fn,
1264: PCI_CLASS_REVISION, &revision)
1265: || pcibios_read_config_byte(bus, device_fn,
1266: PCI_INTERRUPT_LINE, &irq))
1267: {
1268: printk("qlogicisp : error reading PCI configuration\n");
1269: return 1;
1270: }
1271:
1272: if (vendor_id != PCI_VENDOR_ID_QLOGIC) {
1273: printk("qlogicisp : 0x%04x is not QLogic vendor ID\n",
1274: vendor_id);
1275: return 1;
1276: }
1277:
1278: if (device_id != PCI_DEVICE_ID_QLOGIC_ISP1020) {
1279: printk("qlogicisp : 0x%04x does not match ISP1020 device id\n",
1280: device_id);
1281: return 1;
1282: }
1283:
1284: if (command & PCI_COMMAND_IO && (io_base & 3) == 1)
1285: io_base &= PCI_BASE_ADDRESS_IO_MASK;
1286: else {
1287: printk("qlogicisp : i/o mapping is disabled\n");
1288: return 1;
1289: }
1290:
1291: if (!(command & PCI_COMMAND_MASTER)) {
1292: printk("qlogicisp : bus mastering is disabled\n");
1293: return 1;
1294: }
1295:
1296: if (revision != ISP1020_REV_ID)
1297: printk("qlogicisp : new isp1020 revision ID (%d)\n", revision);
1298:
1299: if (inw(io_base + PCI_ID_LOW) != PCI_VENDOR_ID_QLOGIC
1300: || inw(io_base + PCI_ID_HIGH) != PCI_DEVICE_ID_QLOGIC_ISP1020)
1301: {
1302: printk("qlogicisp : can't decode i/o address space at 0x%x\n",
1303: io_base);
1304: return 1;
1305: }
1306:
1307: hostdata->revision = revision;
1308:
1309: sh->irq = irq;
1310: sh->io_port = io_base;
1311:
1312: LEAVE("isp1020_init");
1313:
1314: return 0;
1315: }
1316:
1317:
1318: #if USE_NVRAM_DEFAULTS
1319:
1320: static int isp1020_get_defaults(struct Scsi_Host *host)
1321: {
1322: int i;
1323: u_short value;
1324: struct isp1020_hostdata *hostdata =
1325: (struct isp1020_hostdata *) host->hostdata;
1326:
1327: ENTER("isp1020_get_defaults");
1328:
1329: if (!isp1020_verify_nvram(host)) {
1330: printk("qlogicisp : nvram checksum failure\n");
1331: printk("qlogicisp : attempting to use default parameters\n");
1332: return isp1020_set_defaults(host);
1333: }
1334:
1335: value = isp1020_read_nvram_word(host, 2);
1336: hostdata->host_param.fifo_threshold = (value >> 8) & 0x03;
1337: hostdata->host_param.host_adapter_enable = (value >> 11) & 0x01;
1338: hostdata->host_param.initiator_scsi_id = (value >> 12) & 0x0f;
1339:
1340: value = isp1020_read_nvram_word(host, 3);
1341: hostdata->host_param.bus_reset_delay = value & 0xff;
1342: hostdata->host_param.retry_count = value >> 8;
1343:
1344: value = isp1020_read_nvram_word(host, 4);
1345: hostdata->host_param.retry_delay = value & 0xff;
1346: hostdata->host_param.async_data_setup_time = (value >> 8) & 0x0f;
1347: hostdata->host_param.req_ack_active_negation = (value >> 12) & 0x01;
1348: hostdata->host_param.data_line_active_negation = (value >> 13) & 0x01;
1349: hostdata->host_param.data_dma_burst_enable = (value >> 14) & 0x01;
1350: hostdata->host_param.command_dma_burst_enable = (value >> 15);
1351:
1352: value = isp1020_read_nvram_word(host, 5);
1353: hostdata->host_param.tag_aging = value & 0xff;
1354:
1355: value = isp1020_read_nvram_word(host, 6);
1356: hostdata->host_param.selection_timeout = value & 0xffff;
1357:
1358: value = isp1020_read_nvram_word(host, 7);
1359: hostdata->host_param.max_queue_depth = value & 0xffff;
1360:
1361: #if DEBUG_ISP1020_SETUP
1362: printk("qlogicisp : fifo threshold=%d\n",
1363: hostdata->host_param.fifo_threshold);
1364: printk("qlogicisp : initiator scsi id=%d\n",
1365: hostdata->host_param.initiator_scsi_id);
1366: printk("qlogicisp : bus reset delay=%d\n",
1367: hostdata->host_param.bus_reset_delay);
1368: printk("qlogicisp : retry count=%d\n",
1369: hostdata->host_param.retry_count);
1370: printk("qlogicisp : retry delay=%d\n",
1371: hostdata->host_param.retry_delay);
1372: printk("qlogicisp : async data setup time=%d\n",
1373: hostdata->host_param.async_data_setup_time);
1374: printk("qlogicisp : req/ack active negation=%d\n",
1375: hostdata->host_param.req_ack_active_negation);
1376: printk("qlogicisp : data line active negation=%d\n",
1377: hostdata->host_param.data_line_active_negation);
1378: printk("qlogicisp : data DMA burst enable=%d\n",
1379: hostdata->host_param.data_dma_burst_enable);
1380: printk("qlogicisp : command DMA burst enable=%d\n",
1381: hostdata->host_param.command_dma_burst_enable);
1382: printk("qlogicisp : tag age limit=%d\n",
1383: hostdata->host_param.tag_aging);
1384: printk("qlogicisp : selection timeout limit=%d\n",
1385: hostdata->host_param.selection_timeout);
1386: printk("qlogicisp : max queue depth=%d\n",
1387: hostdata->host_param.max_queue_depth);
1388: #endif /* DEBUG_ISP1020_SETUP */
1389:
1390: for (i = 0; i < MAX_TARGETS; i++) {
1391:
1392: value = isp1020_read_nvram_word(host, 14 + i * 3);
1393: hostdata->dev_param[i].device_flags = value & 0xff;
1394: hostdata->dev_param[i].execution_throttle = value >> 8;
1395:
1396: value = isp1020_read_nvram_word(host, 15 + i * 3);
1397: hostdata->dev_param[i].synchronous_period = value & 0xff;
1398: hostdata->dev_param[i].synchronous_offset = (value >> 8) & 0x0f;
1399: hostdata->dev_param[i].device_enable = (value >> 12) & 0x01;
1400:
1401: #if DEBUG_ISP1020_SETUP
1402: printk("qlogicisp : target 0x%02x\n", i);
1403: printk("qlogicisp : device flags=0x%02x\n",
1404: hostdata->dev_param[i].device_flags);
1405: printk("qlogicisp : execution throttle=%d\n",
1406: hostdata->dev_param[i].execution_throttle);
1407: printk("qlogicisp : synchronous period=%d\n",
1408: hostdata->dev_param[i].synchronous_period);
1409: printk("qlogicisp : synchronous offset=%d\n",
1410: hostdata->dev_param[i].synchronous_offset);
1411: printk("qlogicisp : device enable=%d\n",
1412: hostdata->dev_param[i].device_enable);
1413: #endif /* DEBUG_ISP1020_SETUP */
1414: }
1415:
1416: LEAVE("isp1020_get_defaults");
1417:
1418: return 0;
1419: }
1420:
1421:
1422: #define ISP1020_NVRAM_LEN 0x40
1423: #define ISP1020_NVRAM_SIG1 0x5349
1424: #define ISP1020_NVRAM_SIG2 0x2050
1425:
1426: static int isp1020_verify_nvram(struct Scsi_Host *host)
1427: {
1428: int i;
1429: u_short value;
1430: u_char checksum = 0;
1431:
1432: for (i = 0; i < ISP1020_NVRAM_LEN; i++) {
1433: value = isp1020_read_nvram_word(host, i);
1434:
1435: switch (i) {
1436: case 0:
1437: if (value != ISP1020_NVRAM_SIG1) return 0;
1438: break;
1439: case 1:
1440: if (value != ISP1020_NVRAM_SIG2) return 0;
1441: break;
1442: case 2:
1443: if ((value & 0xff) != 0x02) return 0;
1444: break;
1445: }
1446: checksum += value & 0xff;
1447: checksum += value >> 8;
1448: }
1449:
1450: return (checksum == 0);
1451: }
1452:
1453: #define NVRAM_DELAY() udelay(2) /* 2 microsecond delay */
1454:
1455:
1456: u_short isp1020_read_nvram_word(struct Scsi_Host *host, u_short byte)
1457: {
1458: int i;
1459: u_short value, output, input;
1460:
1461: byte &= 0x3f; byte |= 0x0180;
1462:
1463: for (i = 8; i >= 0; i--) {
1464: output = ((byte >> i) & 0x1) ? 0x4 : 0x0;
1465: outw(output | 0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY();
1466: outw(output | 0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY();
1467: outw(output | 0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY();
1468: }
1469:
1470: for (i = 0xf, value = 0; i >= 0; i--) {
1471: value <<= 1;
1472: outw(0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY();
1473: input = inw(host->io_port + PCI_NVRAM); NVRAM_DELAY();
1474: outw(0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY();
1475: if (input & 0x8) value |= 1;
1476: }
1477:
1478: outw(0x0, host->io_port + PCI_NVRAM); NVRAM_DELAY();
1479:
1480: return value;
1481: }
1482:
1483: #endif /* USE_NVRAM_DEFAULTS */
1484:
1485:
1486: static int isp1020_set_defaults(struct Scsi_Host *host)
1487: {
1488: struct isp1020_hostdata *hostdata =
1489: (struct isp1020_hostdata *) host->hostdata;
1490: int i;
1491:
1492: ENTER("isp1020_set_defaults");
1493:
1494: hostdata->host_param.fifo_threshold = 2;
1495: hostdata->host_param.host_adapter_enable = 1;
1496: hostdata->host_param.initiator_scsi_id = 7;
1497: hostdata->host_param.bus_reset_delay = 3;
1498: hostdata->host_param.retry_count = 0;
1499: hostdata->host_param.retry_delay = 1;
1500: hostdata->host_param.async_data_setup_time = 6;
1501: hostdata->host_param.req_ack_active_negation = 1;
1502: hostdata->host_param.data_line_active_negation = 1;
1503: hostdata->host_param.data_dma_burst_enable = 1;
1504: hostdata->host_param.command_dma_burst_enable = 1;
1505: hostdata->host_param.tag_aging = 8;
1506: hostdata->host_param.selection_timeout = 250;
1507: hostdata->host_param.max_queue_depth = 256;
1508:
1509: for (i = 0; i < MAX_TARGETS; i++) {
1510: hostdata->dev_param[i].device_flags = 0xfd;
1511: hostdata->dev_param[i].execution_throttle = 16;
1512: hostdata->dev_param[i].synchronous_period = 25;
1513: hostdata->dev_param[i].synchronous_offset = 12;
1514: hostdata->dev_param[i].device_enable = 1;
1515: }
1516:
1517: LEAVE("isp1020_set_defaults");
1518:
1519: return 0;
1520: }
1521:
1522:
1523: static int isp1020_load_parameters(struct Scsi_Host *host)
1524: {
1525: int i, k;
1526: u_int queue_addr;
1527: u_short param[6];
1528: u_short isp_cfg1;
1529: unsigned long flags;
1530: struct isp1020_hostdata *hostdata =
1531: (struct isp1020_hostdata *) host->hostdata;
1532:
1533: ENTER("isp1020_load_parameters");
1534:
1535: save_flags(flags);
1536: cli();
1537:
1538: outw(hostdata->host_param.fifo_threshold, host->io_port + ISP_CFG1);
1539:
1540: param[0] = MBOX_SET_INIT_SCSI_ID;
1541: param[1] = hostdata->host_param.initiator_scsi_id;
1542:
1543: isp1020_mbox_command(host, param);
1544:
1545: if (param[0] != MBOX_COMMAND_COMPLETE) {
1546: restore_flags(flags);
1547: printk("qlogicisp : set initiator id failure\n");
1548: return 1;
1549: }
1550:
1551: param[0] = MBOX_SET_RETRY_COUNT;
1552: param[1] = hostdata->host_param.retry_count;
1553: param[2] = hostdata->host_param.retry_delay;
1554:
1555: isp1020_mbox_command(host, param);
1556:
1557: if (param[0] != MBOX_COMMAND_COMPLETE) {
1558: restore_flags(flags);
1559: printk("qlogicisp : set retry count failure\n");
1560: return 1;
1561: }
1562:
1563: param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME;
1564: param[1] = hostdata->host_param.async_data_setup_time;
1565:
1566: isp1020_mbox_command(host, param);
1567:
1568: if (param[0] != MBOX_COMMAND_COMPLETE) {
1569: restore_flags(flags);
1570: printk("qlogicisp : async data setup time failure\n");
1571: return 1;
1572: }
1573:
1574: param[0] = MBOX_SET_ACTIVE_NEG_STATE;
1575: param[1] = (hostdata->host_param.req_ack_active_negation << 4)
1576: | (hostdata->host_param.data_line_active_negation << 5);
1577:
1578: isp1020_mbox_command(host, param);
1579:
1580: if (param[0] != MBOX_COMMAND_COMPLETE) {
1581: restore_flags(flags);
1582: printk("qlogicisp : set active negation state failure\n");
1583: return 1;
1584: }
1585:
1586: param[0] = MBOX_SET_PCI_CONTROL_PARAMS;
1587: param[1] = hostdata->host_param.data_dma_burst_enable << 1;
1588: param[2] = hostdata->host_param.command_dma_burst_enable << 1;
1589:
1590: isp1020_mbox_command(host, param);
1591:
1592: if (param[0] != MBOX_COMMAND_COMPLETE) {
1593: restore_flags(flags);
1594: printk("qlogicisp : set pci control parameter failure\n");
1595: return 1;
1596: }
1597:
1598: isp_cfg1 = inw(host->io_port + ISP_CFG1);
1599:
1600: if (hostdata->host_param.data_dma_burst_enable
1601: || hostdata->host_param.command_dma_burst_enable)
1602: isp_cfg1 |= 0x0004;
1603: else
1604: isp_cfg1 &= 0xfffb;
1605:
1606: outw(isp_cfg1, host->io_port + ISP_CFG1);
1607:
1608: param[0] = MBOX_SET_TAG_AGE_LIMIT;
1609: param[1] = hostdata->host_param.tag_aging;
1610:
1611: isp1020_mbox_command(host, param);
1612:
1613: if (param[0] != MBOX_COMMAND_COMPLETE) {
1614: restore_flags(flags);
1615: printk("qlogicisp : set tag age limit failure\n");
1616: return 1;
1617: }
1618:
1619: param[0] = MBOX_SET_SELECT_TIMEOUT;
1620: param[1] = hostdata->host_param.selection_timeout;
1621:
1622: isp1020_mbox_command(host, param);
1623:
1624: if (param[0] != MBOX_COMMAND_COMPLETE) {
1625: restore_flags(flags);
1626: printk("qlogicisp : set selection timeout failure\n");
1627: return 1;
1628: }
1629:
1630: for (i = 0; i < MAX_TARGETS; i++) {
1631:
1632: if (!hostdata->dev_param[i].device_enable)
1633: continue;
1634:
1635: param[0] = MBOX_SET_TARGET_PARAMS;
1636: param[1] = i << 8;
1637: param[2] = hostdata->dev_param[i].device_flags << 8;
1638: param[3] = (hostdata->dev_param[i].synchronous_offset << 8)
1639: | hostdata->dev_param[i].synchronous_period;
1640:
1641: isp1020_mbox_command(host, param);
1642:
1643: if (param[0] != MBOX_COMMAND_COMPLETE) {
1644: restore_flags(flags);
1645: printk("qlogicisp : set target parameter failure\n");
1646: return 1;
1647: }
1648:
1649: for (k = 0; k < MAX_LUNS; k++) {
1650:
1651: param[0] = MBOX_SET_DEV_QUEUE_PARAMS;
1652: param[1] = (i << 8) | k;
1653: param[2] = hostdata->host_param.max_queue_depth;
1654: param[3] = hostdata->dev_param[i].execution_throttle;
1655:
1656: isp1020_mbox_command(host, param);
1657:
1658: if (param[0] != MBOX_COMMAND_COMPLETE) {
1659: restore_flags(flags);
1660: printk("qlogicisp : set device queue "
1661: "parameter failure\n");
1662: return 1;
1663: }
1664: }
1665: }
1666:
1667: queue_addr = (u_int) virt_to_bus(&hostdata->res[0][0]);
1668:
1669: param[0] = MBOX_INIT_RES_QUEUE;
1670: param[1] = RES_QUEUE_LEN + 1;
1671: param[2] = (u_short) (queue_addr >> 16);
1672: param[3] = (u_short) (queue_addr & 0xffff);
1673: param[4] = 0;
1674: param[5] = 0;
1675:
1676: isp1020_mbox_command(host, param);
1677:
1678: if (param[0] != MBOX_COMMAND_COMPLETE) {
1679: restore_flags(flags);
1680: printk("qlogicisp : set response queue failure\n");
1681: return 1;
1682: }
1683:
1684: queue_addr = (u_int) virt_to_bus(&hostdata->req[0][0]);
1685:
1686: param[0] = MBOX_INIT_REQ_QUEUE;
1687: param[1] = QLOGICISP_REQ_QUEUE_LEN + 1;
1688: param[2] = (u_short) (queue_addr >> 16);
1689: param[3] = (u_short) (queue_addr & 0xffff);
1690: param[4] = 0;
1691:
1692: isp1020_mbox_command(host, param);
1693:
1694: if (param[0] != MBOX_COMMAND_COMPLETE) {
1695: restore_flags(flags);
1696: printk("qlogicisp : set request queue failure\n");
1697: return 1;
1698: }
1699:
1700: restore_flags(flags);
1701:
1702: LEAVE("isp1020_load_parameters");
1703:
1704: return 0;
1705: }
1706:
1707:
1708: /*
1709: * currently, this is only called during initialization or abort/reset,
1710: * at which times interrupts are disabled, so polling is OK, I guess...
1711: */
1712: static int isp1020_mbox_command(struct Scsi_Host *host, u_short param[])
1713: {
1714: int loop_count;
1715:
1716: if (mbox_param[param[0]] == 0)
1717: return 1;
1718:
1719: loop_count = DEFAULT_LOOP_COUNT;
1720: while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080)
1721: barrier();
1722: if (!loop_count)
1723: printk("qlogicisp: mbox_command loop timeout #1\n");
1724:
1725: switch(mbox_param[param[0]] >> 4) {
1726: case 6: outw(param[5], host->io_port + MBOX5);
1727: case 5: outw(param[4], host->io_port + MBOX4);
1728: case 4: outw(param[3], host->io_port + MBOX3);
1729: case 3: outw(param[2], host->io_port + MBOX2);
1730: case 2: outw(param[1], host->io_port + MBOX1);
1731: case 1: outw(param[0], host->io_port + MBOX0);
1732: }
1733:
1734: outw(0x0, host->io_port + PCI_SEMAPHORE);
1735: outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
1736: outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR);
1737:
1738: loop_count = DEFAULT_LOOP_COUNT;
1739: while (--loop_count && !(inw(host->io_port + PCI_INTF_STS) & 0x04))
1740: barrier();
1741: if (!loop_count)
1742: printk("qlogicisp: mbox_command loop timeout #2\n");
1743:
1744: loop_count = DEFAULT_LOOP_COUNT;
1745: while (--loop_count && inw(host->io_port + MBOX0) == 0x04)
1746: barrier();
1747: if (!loop_count)
1748: printk("qlogicisp: mbox_command loop timeout #3\n");
1749:
1750: switch(mbox_param[param[0]] & 0xf) {
1751: case 6: param[5] = inw(host->io_port + MBOX5);
1752: case 5: param[4] = inw(host->io_port + MBOX4);
1753: case 4: param[3] = inw(host->io_port + MBOX3);
1754: case 3: param[2] = inw(host->io_port + MBOX2);
1755: case 2: param[1] = inw(host->io_port + MBOX1);
1756: case 1: param[0] = inw(host->io_port + MBOX0);
1757: }
1758:
1759: outw(0x0, host->io_port + PCI_SEMAPHORE);
1760: outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
1761:
1762: return 0;
1763: }
1764:
1765:
1766: #if DEBUG_ISP1020_INTR
1767:
1768: void isp1020_print_status_entry(struct Status_Entry *status)
1769: {
1770: int i;
1771:
1772: printk("qlogicisp : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n",
1773: status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
1774: printk("qlogicisp : scsi status = 0x%04x, completion status = 0x%04x\n",
1775: status->scsi_status, status->completion_status);
1776: printk("qlogicisp : state flags = 0x%04x, status flags = 0x%04x\n",
1777: status->state_flags, status->status_flags);
1778: printk("qlogicisp : time = 0x%04x, request sense length = 0x%04x\n",
1779: status->time, status->req_sense_len);
1780: printk("qlogicisp : residual transfer length = 0x%08x\n", status->residual);
1781:
1782: for (i = 0; i < status->req_sense_len; i++)
1783: printk("qlogicisp : sense data = 0x%02x\n", status->req_sense_data[i]);
1784: }
1785:
1786: #endif /* DEBUG_ISP1020_INTR */
1787:
1788:
1789: #if DEBUG_ISP1020
1790:
1791: void isp1020_print_scsi_cmd(Scsi_Cmnd *cmd)
1792: {
1793: int i;
1794:
1795: printk("qlogicisp : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",
1796: cmd->target, cmd->lun, cmd->cmd_len);
1797: printk("qlogicisp : command = ");
1798: for (i = 0; i < cmd->cmd_len; i++)
1799: printk("0x%02x ", cmd->cmnd[i]);
1800: printk("\n");
1801: }
1802:
1803: #endif /* DEBUG_ISP1020 */
1804:
1805:
1806: #ifdef MODULE
1807: Scsi_Host_Template driver_template = QLOGICISP;
1808:
1809: #include "scsi_module.c"
1810: #endif /* MODULE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.