|
|
1.1 root 1: /*
2: * Generic Generic NCR5380 driver
3: *
4: * Copyright 1993, Drew Eckhardt
5: * Visionary Computing
6: * (Unix and Linux consulting and custom programming)
7: * [email protected]
8: * +1 (303) 440-4894
9: *
10: * NCR53C400 extensions (c) 1994,1995,1996, Kevin Lentin
11: * [email protected]
12: *
13: * ALPHA RELEASE 1.
14: *
15: * For more information, please consult
16: *
17: * NCR 5380 Family
18: * SCSI Protocol Controller
19: * Databook
20: *
21: * NCR Microelectronics
22: * 1635 Aeroplaza Drive
23: * Colorado Springs, CO 80916
24: * 1+ (719) 578-3400
25: * 1+ (800) 334-5454
26: */
27:
28: /*
29: * TODO : flesh out DMA support, find some one actually using this (I have
30: * a memory mapped Trantor board that works fine)
31: */
32:
33: /*
34: * Options :
35: *
36: * PARITY - enable parity checking. Not supported.
37: *
38: * SCSI2 - enable support for SCSI-II tagged queueing. Untested.
39: *
40: * USLEEP - enable support for devices that don't disconnect. Untested.
41: *
42: * The card is detected and initialized in one of several ways :
43: * 1. With command line overrides - NCR5380=port,irq may be
44: * used on the LILO command line to override the defaults.
45: *
46: * 2. With the GENERIC_NCR5380_OVERRIDE compile time define. This is
47: * specified as an array of address, irq, dma, board tuples. Ie, for
48: * one board at 0x350, IRQ5, no dma, I could say
49: * -DGENERIC_NCR5380_OVERRIDE={{0xcc000, 5, DMA_NONE, BOARD_NCR5380}}
50: *
51: * -1 should be specified for no or DMA interrupt, -2 to autoprobe for an
52: * IRQ line if overridden on the command line.
53: *
54: * 3. When included as a module, with arguments passed on the command line:
55: * ncr_irq=xx the interrupt
56: * ncr_addr=xx the port or base address (for port or memory
57: * mapped, resp.)
58: * ncr_dma=xx the DMA
59: * ncr_5380=1 to set up for a NCR5380 board
60: * ncr_53c400=1 to set up for a NCR53C400 board
61: * e.g.
62: * modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
63: * for a port mapped NCR5380 board or
64: * modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
65: * for a memory mapped NCR53C400 board with interrupts disabled.
66: *
67: * 255 should be specified for no or DMA interrupt, 254 to autoprobe for an
68: * IRQ line if overridden on the command line.
69: *
70: */
71:
72: /*
73: * $Log: g_NCR5380.c,v $
74: * Revision 1.1 1999/04/26 05:54:33 tb
75: * 1998-11-30 OKUJI Yoshinori <[email protected]>
76: *
77: * Clean up linux emulation code to make it architecture-independent
78: * as much as possible.
79: *
80: * * linux: Renamed from linuxdev.
81: * * Makefile.in (objfiles): Add linux.o instead of linuxdev.o.
82: * (MAKE): New variable. Used for the linux.o target.
83: * * configure.in: Add AC_CHECK_TOOL(MAKE, make).
84: * * i386/i386/spl.h: Include <i386/ipl.h>, for compatibility with
85: * OSF Mach 3.0. Suggested by Elgin Lee <[email protected]>.
86: * * linux/src: Renamed from linux/linux.
87: * * linux/dev: Renamed from linux/mach.
88: * * linux/Drivers.in (AC_INIT): Use dev/include/linux/autoconf.h,
89: * instead of mach/include/linux/autoconf.h.
90: * * Makefile.in (all): Target ../linux.o instead of ../linuxdev.o.
91: * * linux/dev/drivers/block/genhd.c: Include <machine/spl.h> instead
92: * of <i386/ipl.h>.
93: * * linux/dev/drivers/net/auto_irq.c: Remove unneeded header files,
94: * <i386/ipl.h> and <i386/pic.h>.
95: * * linux/dev/init/main.c: Many i386-dependent codes moved to ...
96: * * linux/dev/arch/i386/irq.c: ... here.
97: * * linux/dev/arch/i386/setup.c: New file.
98: * * linux/dev/arch/i386/linux_emul.h: Likewise.
99: * * linux/dev/arch/i386/glue/timer.c: Merged into sched.c.
100: * * linux/dev/arch/i386/glue/sched.c: Include <machine/spl.h> instead
101: * of <i386/ipl.h>, and moved to ...
102: * * linux/dev/kernel/sched.c: ... here.
103: * * linux/dev/arch/i386/glue/block.c: Include <machine/spl.h> and
104: * <linux_emul.h>, instead of i386-dependent header files, and
105: * moved to ...
106: * * linux/dev/glue/blocl.c: ... here.
107: * * linux/dev/arch/i386/glue/net.c: Include <machine/spl.h> and
108: * <linux_emul.h>, instead of i386-dependent header files, and
109: * moved to ...
110: * * linux/dev/glue/net.c: ... here.
111: * * linux/dev/arch/i386/glue/misc.c: Remove `x86' and moved to ...
112: * * linux/dev/glue/misc.c: ... here.
113: * * linux/dev/arch/i386/glue/kmem.c: Moved to ...
114: * * linux/dev/glue/kmem.c: ... here.
115: *
116: */
117:
118: #define AUTOPROBE_IRQ
119: #define AUTOSENSE
120:
121: #include <linux/config.h>
122:
123: #ifdef CONFIG_SCSI_GENERIC_NCR53C400
124: #define NCR53C400_PSEUDO_DMA 1
125: #define PSEUDO_DMA
126: #define NCR53C400
127: #define NCR5380_STATS
128: #undef NCR5380_STAT_LIMIT
129: #endif
130: #if defined(CONFIG_SCSI_G_NCR5380_PORT) && defined(CONFIG_SCSI_G_NCR5380_MEM)
131: #error You can not configure the Generic NCR 5380 SCSI Driver for memory mapped I/O and port mapped I/O at the same time (yet)
132: #endif
133: #if !defined(CONFIG_SCSI_G_NCR5380_PORT) && !defined(CONFIG_SCSI_G_NCR5380_MEM)
134: #error You must configure the Generic NCR 5380 SCSI Driver for one of memory mapped I/O and port mapped I/O.
135: #endif
136:
137: #include <asm/system.h>
138: #include <asm/io.h>
139: #include <linux/signal.h>
140: #include <linux/sched.h>
141: #include <linux/blk.h>
142: #include "scsi.h"
143: #include "hosts.h"
144: #include "g_NCR5380.h"
145: #include "NCR5380.h"
146: #include "constants.h"
147: #include "sd.h"
148: #include<linux/stat.h>
149:
150: struct proc_dir_entry proc_scsi_g_ncr5380 = {
151: PROC_SCSI_GENERIC_NCR5380, 9, "g_NCR5380",
152: S_IFDIR | S_IRUGO | S_IXUGO, 2
153: };
154:
155: #define NCR_NOT_SET 0
156: static int ncr_irq=NCR_NOT_SET;
157: static int ncr_dma=NCR_NOT_SET;
158: static int ncr_addr=NCR_NOT_SET;
159: static int ncr_5380=NCR_NOT_SET;
160: static int ncr_53c400=NCR_NOT_SET;
161:
162: static struct override {
163: NCR5380_implementation_fields;
164: int irq;
165: int dma;
166: int board; /* Use NCR53c400, Ricoh, etc. extensions ? */
167: } overrides
168: #ifdef GENERIC_NCR5380_OVERRIDE
169: [] = GENERIC_NCR5380_OVERRIDE
170: #else
171: [1] = {{0,},};
172: #endif
173:
174: #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
175:
176: /*
177: * Function : static internal_setup(int board, char *str, int *ints)
178: *
179: * Purpose : LILO command line initialization of the overrides array,
180: *
181: * Inputs : board - either BOARD_NCR5380 for a normal NCR5380 board,
182: * or BOARD_NCR53C400 for a NCR53C400 board. str - unused, ints -
183: * array of integer parameters with ints[0] equal to the number of ints.
184: *
185: */
186:
187: static void internal_setup(int board, char *str, int *ints) {
188: static int commandline_current = 0;
189: switch (board) {
190: case BOARD_NCR5380:
191: if (ints[0] != 2 && ints[0] != 3) {
192: printk("generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n");
193: return;
194: }
195: case BOARD_NCR53C400:
196: if (ints[0] != 2) {
197: printk("generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n");
198: return;
199: }
200: }
201:
202: if (commandline_current < NO_OVERRIDES) {
203: overrides[commandline_current].NCR5380_map_name = (NCR5380_map_type)ints[1];
204: overrides[commandline_current].irq = ints[2];
205: if (ints[0] == 3)
206: overrides[commandline_current].dma = ints[3];
207: else
208: overrides[commandline_current].dma = DMA_NONE;
209: overrides[commandline_current].board = board;
210: ++commandline_current;
211: }
212: }
213:
214: /*
215: * Function : generic_NCR5380_setup (char *str, int *ints)
216: *
217: * Purpose : LILO command line initialization of the overrides array,
218: *
219: * Inputs : str - unused, ints - array of integer parameters with ints[0]
220: * equal to the number of ints.
221: */
222:
223: void generic_NCR5380_setup (char *str, int *ints) {
224: internal_setup (BOARD_NCR5380, str, ints);
225: }
226:
227: /*
228: * Function : generic_NCR53C400_setup (char *str, int *ints)
229: *
230: * Purpose : LILO command line initialization of the overrides array,
231: *
232: * Inputs : str - unused, ints - array of integer parameters with ints[0]
233: * equal to the number of ints.
234: */
235:
236: void generic_NCR53C400_setup (char *str, int *ints) {
237: internal_setup (BOARD_NCR53C400, str, ints);
238: }
239:
240: /*
241: * Function : int generic_NCR5380_detect(Scsi_Host_Template * tpnt)
242: *
243: * Purpose : initializes generic NCR5380 driver based on the
244: * command line / compile time port and irq definitions.
245: *
246: * Inputs : tpnt - template for this SCSI adapter.
247: *
248: * Returns : 1 if a host adapter was found, 0 if not.
249: *
250: */
251:
252: int generic_NCR5380_detect(Scsi_Host_Template * tpnt) {
253: static int current_override = 0;
254: int count;
255: int flags = 0;
256: struct Scsi_Host *instance;
257:
258: if (ncr_irq != NCR_NOT_SET)
259: overrides[0].irq=ncr_irq;
260: if (ncr_dma != NCR_NOT_SET)
261: overrides[0].dma=ncr_dma;
262: if (ncr_addr != NCR_NOT_SET)
263: overrides[0].NCR5380_map_name=(NCR5380_map_type)ncr_addr;
264: if (ncr_5380 != NCR_NOT_SET)
265: overrides[0].board=BOARD_NCR5380;
266: else if (ncr_53c400 != NCR_NOT_SET)
267: overrides[0].board=BOARD_NCR53C400;
268:
269: tpnt->proc_dir = &proc_scsi_g_ncr5380;
270:
271: for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
272: if (!(overrides[current_override].NCR5380_map_name))
273: continue;
274:
275: switch (overrides[current_override].board) {
276: case BOARD_NCR5380:
277: flags = FLAG_NO_PSEUDO_DMA;
278: break;
279: case BOARD_NCR53C400:
280: flags = FLAG_NCR53C400;
281: break;
282: }
283:
284: instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
285: instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name;
286:
287: NCR5380_init(instance, flags);
288:
289: if (overrides[current_override].irq != IRQ_AUTO)
290: instance->irq = overrides[current_override].irq;
291: else
292: instance->irq = NCR5380_probe_irq(instance, 0xffff);
293:
294: if (instance->irq != IRQ_NONE)
295: if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) {
296: printk("scsi%d : IRQ%d not free, interrupts disabled\n",
297: instance->host_no, instance->irq);
298: instance->irq = IRQ_NONE;
299: }
300:
301: if (instance->irq == IRQ_NONE) {
302: printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
303: printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
304: }
305:
306: printk("scsi%d : at " STRVAL(NCR5380_map_name) " 0x%x", instance->host_no, (unsigned int)instance->NCR5380_instance_name);
307: if (instance->irq == IRQ_NONE)
308: printk (" interrupts disabled");
309: else
310: printk (" irq %d", instance->irq);
311: printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
312: CAN_QUEUE, CMD_PER_LUN, GENERIC_NCR5380_PUBLIC_RELEASE);
313: NCR5380_print_options(instance);
314: printk("\n");
315:
316: ++current_override;
317: ++count;
318: }
319: return count;
320: }
321:
322: const char * generic_NCR5380_info (struct Scsi_Host* host) {
323: static const char string[]="Generic NCR5380/53C400 Driver";
324: return string;
325: }
326:
327: int generic_NCR5380_release_resources(struct Scsi_Host * instance)
328: {
329: NCR5380_local_declare();
330:
331: NCR5380_setup(instance);
332:
333: if (instance->irq != IRQ_NONE)
334: free_irq(instance->irq, NULL);
335:
336: return 0;
337: }
338:
339: #ifdef BIOSPARAM
340: /*
341: * Function : int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip)
342: *
343: * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for
344: * the specified device / size.
345: *
346: * Inputs : size = size of device in sectors (512 bytes), dev = block device
347: * major / minor, ip[] = {heads, sectors, cylinders}
348: *
349: * Returns : always 0 (success), initializes ip
350: *
351: */
352:
353: /*
354: * XXX Most SCSI boards use this mapping, I could be incorrect. Some one
355: * using hard disks on a trantor should verify that this mapping corresponds
356: * to that used by the BIOS / ASPI driver by running the linux fdisk program
357: * and matching the H_C_S coordinates to what DOS uses.
358: */
359:
360: int generic_NCR5380_biosparam(Disk * disk, kdev_t dev, int *ip)
361: {
362: int size = disk->capacity;
363: ip[0] = 64;
364: ip[1] = 32;
365: ip[2] = size >> 11;
366: return 0;
367: }
368: #endif
369:
370: #if NCR53C400_PSEUDO_DMA
371: static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, int len)
372: {
373: int blocks = len / 128;
374: int start = 0;
375: int i;
376: int bl;
377: NCR5380_local_declare();
378:
379: NCR5380_setup(instance);
380:
381: #if (NDEBUG & NDEBUG_C400_PREAD)
382: printk("53C400r: About to read %d blocks for %d bytes\n", blocks, len);
383: #endif
384:
385: NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
386: NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
387: while (1) {
388:
389: #if (NDEBUG & NDEBUG_C400_PREAD)
390: printk("53C400r: %d blocks left\n", blocks);
391: #endif
392:
393: if ((bl=NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
394: #if (NDEBUG & NDEBUG_C400_PREAD)
395: if (blocks)
396: printk("53C400r: blocks still == %d\n", blocks);
397: else
398: printk("53C400r: Exiting loop\n");
399: #endif
400: break;
401: }
402:
403: #if 1
404: if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
405: printk("53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
406: return -1;
407: }
408: #endif
409:
410: #if (NDEBUG & NDEBUG_C400_PREAD)
411: printk("53C400r: Waiting for buffer, bl=%d\n", bl);
412: #endif
413:
414: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
415: ;
416: #if (NDEBUG & NDEBUG_C400_PREAD)
417: printk("53C400r: Transferring 128 bytes\n");
418: #endif
419:
420: #ifdef CONFIG_SCSI_G_NCR5380_PORT
421: for (i=0; i<128; i++)
422: dst[start+i] = NCR5380_read(C400_HOST_BUFFER);
423: #else
424: /* implies CONFIG_SCSI_G_NCR5380_MEM */
425: memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
426: #endif
427: start+=128;
428: blocks--;
429: }
430:
431: if (blocks) {
432: #if (NDEBUG & NDEBUG_C400_PREAD)
433: printk("53C400r: EXTRA: Waiting for buffer\n");
434: #endif
435: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
436: ;
437:
438: #if (NDEBUG & NDEBUG_C400_PREAD)
439: printk("53C400r: Transferring EXTRA 128 bytes\n");
440: #endif
441: #ifdef CONFIG_SCSI_G_NCR5380_PORT
442: for (i=0; i<128; i++)
443: dst[start+i] = NCR5380_read(C400_HOST_BUFFER);
444: #else
445: /* implies CONFIG_SCSI_G_NCR5380_MEM */
446: memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
447: #endif
448: start+=128;
449: blocks--;
450: }
451: #if (NDEBUG & NDEBUG_C400_PREAD)
452: else
453: printk("53C400r: No EXTRA required\n");
454: #endif
455:
456: #if (NDEBUG & NDEBUG_C400_PREAD)
457: printk("53C400r: Final values: blocks=%d start=%d\n", blocks, start);
458: #endif
459:
460: if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
461: printk("53C400r: no 53C80 gated irq after transfer");
462: #if (NDEBUG & NDEBUG_C400_PREAD)
463: else
464: printk("53C400r: Got 53C80 interrupt and tried to clear it\n");
465: #endif
466:
467: /* DON'T DO THIS - THEY NEVER ARRIVE!
468: printk("53C400r: Waiting for 53C80 registers\n");
469: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
470: ;
471: */
472:
473: if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
474: printk("53C400r: no end dma signal\n");
475: #if (NDEBUG & NDEBUG_C400_PREAD)
476: else
477: printk("53C400r: end dma as expected\n");
478: #endif
479:
480: NCR5380_write(MODE_REG, MR_BASE);
481: NCR5380_read(RESET_PARITY_INTERRUPT_REG);
482: return 0;
483: }
484:
485: static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, int len)
486: {
487: int blocks = len / 128;
488: int start = 0;
489: int i;
490: int bl;
491: NCR5380_local_declare();
492:
493: NCR5380_setup(instance);
494:
495: #if (NDEBUG & NDEBUG_C400_PWRITE)
496: printk("53C400w: About to write %d blocks for %d bytes\n", blocks, len);
497: #endif
498:
499: NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
500: NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
501: while (1) {
502: if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
503: printk("53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
504: return -1;
505: }
506:
507: if ((bl=NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
508: #if (NDEBUG & NDEBUG_C400_PWRITE)
509: if (blocks)
510: printk("53C400w: exiting loop, blocks still == %d\n", blocks);
511: else
512: printk("53C400w: exiting loop\n");
513: #endif
514: break;
515: }
516:
517: #if (NDEBUG & NDEBUG_C400_PWRITE)
518: printk("53C400w: %d blocks left\n", blocks);
519:
520: printk("53C400w: waiting for buffer, bl=%d\n", bl);
521: #endif
522: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
523: ;
524:
525: #if (NDEBUG & NDEBUG_C400_PWRITE)
526: printk("53C400w: transferring 128 bytes\n");
527: #endif
528: #ifdef CONFIG_SCSI_G_NCR5380_PORT
529: for (i=0; i<128; i++)
530: NCR5380_write(C400_HOST_BUFFER, src[start+i]);
531: #else
532: /* implies CONFIG_SCSI_G_NCR5380_MEM */
533: memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128);
534: #endif
535: start+=128;
536: blocks--;
537: }
538: if (blocks) {
539: #if (NDEBUG & NDEBUG_C400_PWRITE)
540: printk("53C400w: EXTRA waiting for buffer\n");
541: #endif
542: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
543: ;
544:
545: #if (NDEBUG & NDEBUG_C400_PWRITE)
546: printk("53C400w: transferring EXTRA 128 bytes\n");
547: #endif
548: #ifdef CONFIG_SCSI_G_NCR5380_PORT
549: for (i=0; i<128; i++)
550: NCR5380_write(C400_HOST_BUFFER, src[start+i]);
551: #else
552: /* implies CONFIG_SCSI_G_NCR5380_MEM */
553: memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128);
554: #endif
555: start+=128;
556: blocks--;
557: }
558: #if (NDEBUG & NDEBUG_C400_PWRITE)
559: else
560: printk("53C400w: No EXTRA required\n");
561: #endif
562:
563: #if (NDEBUG & NDEBUG_C400_PWRITE)
564: printk("53C400w: Final values: blocks=%d start=%d\n", blocks, start);
565: #endif
566:
567: #if 0
568: printk("53C400w: waiting for registers to be available\n");
569: THEY NEVER DO!
570: while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
571: ;
572: printk("53C400w: Got em\n");
573: #endif
574:
575: /* Let's wait for this instead - could be ugly */
576: /* All documentation says to check for this. Maybe my hardware is too
577: * fast. Waiting for it seems to work fine! KLL
578: */
579: while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
580: ;
581:
582: /*
583: * I know. i is certainly != 0 here but the loop is new. See previous
584: * comment.
585: */
586: if (i) {
587: #if (NDEBUG & NDEBUG_C400_PWRITE)
588: printk("53C400w: got 53C80 gated irq (last block)\n");
589: #endif
590: if (!((i=NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER))
591: printk("53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n",i);
592: #if (NDEBUG & NDEBUG_C400_PWRITE)
593: else
594: printk("53C400w: Got END OF DMA\n");
595: #endif
596: }
597: else
598: printk("53C400w: no 53C80 gated irq after transfer (last block)\n");
599:
600: #if 0
601: if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
602: printk("53C400w: no end dma signal\n");
603: }
604: #endif
605:
606: #if (NDEBUG & NDEBUG_C400_PWRITE)
607: printk("53C400w: waiting for last byte...\n");
608: #endif
609: while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
610: ;
611:
612: #if (NDEBUG & NDEBUG_C400_PWRITE)
613: printk("53C400w: got last byte.\n");
614: printk("53C400w: pwrite exiting with status 0, whoopee!\n");
615: #endif
616: return 0;
617: }
618: #endif /* PSEUDO_DMA */
619:
620: #include "NCR5380.c"
621:
622: #define PRINTP(x) len += sprintf(buffer+len, x)
623: #define ANDP ,
624:
625: static int sprint_opcode(char* buffer, int len, int opcode) {
626: int start = len;
627: PRINTP("0x%02x " ANDP opcode);
628: return len-start;
629: }
630:
631: static int sprint_command (char* buffer, int len, unsigned char *command) {
632: int i,s,start=len;
633: len += sprint_opcode(buffer, len, command[0]);
634: for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
635: PRINTP("%02x " ANDP command[i]);
636: PRINTP("\n");
637: return len-start;
638: }
639:
640: static int sprint_Scsi_Cmnd (char* buffer, int len, Scsi_Cmnd *cmd) {
641: int start = len;
642: PRINTP("host number %d destination target %d, lun %d\n" ANDP
643: cmd->host->host_no ANDP
644: cmd->target ANDP
645: cmd->lun);
646: PRINTP(" command = ");
647: len += sprint_command (buffer, len, cmd->cmnd);
648: return len-start;
649: }
650:
651: int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout)
652: {
653: int len = 0;
654: NCR5380_local_declare();
655: unsigned char status;
656: int i;
657: struct Scsi_Host *scsi_ptr;
658: Scsi_Cmnd *ptr;
659: Scsi_Device *dev;
660: struct NCR5380_hostdata *hostdata;
661:
662: cli();
663:
664: for (scsi_ptr = first_instance; scsi_ptr; scsi_ptr=scsi_ptr->next)
665: if (scsi_ptr->host_no == hostno)
666: break;
667: NCR5380_setup(scsi_ptr);
668: hostdata = (struct NCR5380_hostdata *)scsi_ptr->hostdata;
669:
670: PRINTP("SCSI host number %d : %s\n" ANDP scsi_ptr->host_no ANDP scsi_ptr->hostt->name);
671: PRINTP("Generic NCR5380 driver version %d\n" ANDP GENERIC_NCR5380_PUBLIC_RELEASE);
672: PRINTP("NCR5380 core version %d\n" ANDP NCR5380_PUBLIC_RELEASE);
673: #ifdef NCR53C400
674: PRINTP("NCR53C400 extension version %d\n" ANDP NCR53C400_PUBLIC_RELEASE);
675: PRINTP("NCR53C400 card%s detected\n" ANDP (((struct NCR5380_hostdata *)scsi_ptr->hostdata)->flags & FLAG_NCR53C400)?"":" not");
676: # if NCR53C400_PSEUDO_DMA
677: PRINTP("NCR53C400 pseudo DMA used\n");
678: # endif
679: #else
680: PRINTP("NO NCR53C400 driver extensions\n");
681: #endif
682: PRINTP("Using %s mapping at %s 0x%x, " ANDP STRVAL(NCR5380_map_config) ANDP STRVAL(NCR5380_map_name) ANDP scsi_ptr->NCR5380_instance_name);
683: if (scsi_ptr->irq == IRQ_NONE)
684: PRINTP("no interrupt\n");
685: else
686: PRINTP("on interrupt %d\n" ANDP scsi_ptr->irq);
687:
688: #ifdef NCR5380_STATS
689: if (hostdata->connected || hostdata->issue_queue || hostdata->disconnected_queue)
690: PRINTP("There are commands pending, transfer rates may be crud\n");
691: if (hostdata->pendingr)
692: PRINTP(" %d pending reads" ANDP hostdata->pendingr);
693: if (hostdata->pendingw)
694: PRINTP(" %d pending writes" ANDP hostdata->pendingw);
695: if (hostdata->pendingr || hostdata->pendingw)
696: PRINTP("\n");
697: for (dev = scsi_devices; dev; dev=dev->next) {
698: if (dev->host == scsi_ptr) {
699: unsigned long br = hostdata->bytes_read[dev->id];
700: unsigned long bw = hostdata->bytes_write[dev->id];
701: long tr = hostdata->time_read[dev->id] / HZ;
702: long tw = hostdata->time_write[dev->id] / HZ;
703:
704: PRINTP(" T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(int)dev->type] : "Unknown");
705: for (i=0; i<8; i++)
706: if (dev->vendor[i] >= 0x20)
707: *(buffer+(len++)) = dev->vendor[i];
708: *(buffer+(len++)) = ' ';
709: for (i=0; i<16; i++)
710: if (dev->model[i] >= 0x20)
711: *(buffer+(len++)) = dev->model[i];
712: *(buffer+(len++)) = ' ';
713: for (i=0; i<4; i++)
714: if (dev->rev[i] >= 0x20)
715: *(buffer+(len++)) = dev->rev[i];
716: *(buffer+(len++)) = ' ';
717:
718: PRINTP("\n%10ld kb read in %5ld secs" ANDP br/1024 ANDP tr);
719: if (tr)
720: PRINTP(" @ %5ld bps" ANDP br / tr);
721:
722: PRINTP("\n%10ld kb written in %5ld secs" ANDP bw/1024 ANDP tw);
723: if (tw)
724: PRINTP(" @ %5ld bps" ANDP bw / tw);
725: PRINTP("\n");
726: }
727: }
728: #endif
729:
730: status = NCR5380_read(STATUS_REG);
731: if (!(status & SR_REQ))
732: PRINTP("REQ not asserted, phase unknown.\n");
733: else {
734: for (i = 0; (phases[i].value != PHASE_UNKNOWN) &&
735: (phases[i].value != (status & PHASE_MASK)); ++i)
736: ;
737: PRINTP("Phase %s\n" ANDP phases[i].name);
738: }
739:
740: if (!hostdata->connected) {
741: PRINTP("No currently connected command\n");
742: } else {
743: len += sprint_Scsi_Cmnd (buffer, len, (Scsi_Cmnd *) hostdata->connected);
744: }
745:
746: PRINTP("issue_queue\n");
747:
748: for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr;
749: ptr = (Scsi_Cmnd *) ptr->host_scribble)
750: len += sprint_Scsi_Cmnd (buffer, len, ptr);
751:
752: PRINTP("disconnected_queue\n");
753:
754: for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
755: ptr = (Scsi_Cmnd *) ptr->host_scribble)
756: len += sprint_Scsi_Cmnd (buffer, len, ptr);
757:
758: *start = buffer + offset;
759: len -= offset;
760: if (len > length)
761: len = length;
762: sti();
763: return len;
764: }
765:
766: #undef PRINTP
767: #undef ANDP
768:
769: #ifdef MODULE
770: /* Eventually this will go into an include file, but this will be later */
771: Scsi_Host_Template driver_template = GENERIC_NCR5380;
772:
773: #include <linux/module.h>
774: #include "scsi_module.c"
775: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.