|
|
1.1 root 1:
2: #define AUTOSENSE
3: #define PSEUDO_DMA
4: #define DONT_USE_INTR
5: #define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */
6: #define xNDEBUG (NDEBUG_INTR+NDEBUG_RESELECTION+\
7: NDEBUG_SELECTION+NDEBUG_ARBITRATION)
8: #define DMA_WORKS_RIGHT
9:
10:
11: /*
12: * DTC 3180/3280 driver, by
13: * Ray Van Tassle [email protected]
14: *
15: * taken from ...
16: * Trantor T128/T128F/T228 driver by...
17: *
18: * Drew Eckhardt
19: * Visionary Computing
20: * (Unix and Linux consulting and custom programming)
21: * [email protected]
22: * +1 (303) 440-4894
23: *
24: * DISTRIBUTION RELEASE 1.
25: *
26: * For more information, please consult
27: *
28: * NCR 5380 Family
29: * SCSI Protocol Controller
30: * Databook
31: */
32:
33: /*
34: * Options :
35: * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
36: * for commands that return with a CHECK CONDITION status.
37: *
38: * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
39: * increase compared to polled I/O.
40: *
41: * PARITY - enable parity checking. Not supported.
42: *
43: * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.
44: * You probably want this.
45: *
46: * The card is detected and initialized in one of several ways :
47: * 1. Autoprobe (default) - since the board is memory mapped,
48: * a BIOS signature is scanned for to locate the registers.
49: * An interrupt is triggered to autoprobe for the interrupt
50: * line.
51: *
52: * 2. With command line overrides - dtc=address,irq may be
53: * used on the LILO command line to override the defaults.
54: *
55: */
56:
57: /*----------------------------------------------------------------*/
58: /* the following will set the monitor border color (useful to find
59: where something crashed or gets stuck at */
60: /* 1 = blue
61: 2 = green
62: 3 = cyan
63: 4 = red
64: 5 = magenta
65: 6 = yellow
66: 7 = white
67: */
68: #if 0
69: #define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);}
70: #else
71: #define rtrc(i) {}
72: #endif
73:
74:
75: #include <asm/system.h>
76: #include <linux/signal.h>
77: #include <linux/sched.h>
78: #include <linux/blk.h>
79: #include <asm/io.h>
80: #include "scsi.h"
81: #include "hosts.h"
82: #include "dtc.h"
83: #define AUTOPROBE_IRQ
84: #include "NCR5380.h"
85: #include "constants.h"
86: #include "sd.h"
87: #include<linux/stat.h>
88: #include<linux/string.h>
89:
90: struct proc_dir_entry proc_scsi_dtc = {
91: PROC_SCSI_T128, 7, "dtc3x80",
92: S_IFDIR | S_IRUGO | S_IXUGO, 2
93: };
94:
95:
96: static struct override {
97: __u32 address;
98: int irq;
99: } overrides
100: #ifdef OVERRIDE
101: [] = OVERRIDE;
102: #else
103: [4] = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO},
104: {0, IRQ_AUTO}};
105: #endif
106:
107: #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
108:
109: static struct base {
110: __u32 address;
111: int noauto;
112: } bases[] = {{0xcc000, 0}, {0xc8000, 0},
113: {0xdc000, 0}, {0xd8000, 0}};
114:
115: #define NO_BASES (sizeof (bases) / sizeof (struct base))
116:
117: static const struct signature {
118: const char *string;
119: int offset;
120: } signatures[] = { {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, };
121:
122: #define NO_SIGNATURES (sizeof (signatures) / sizeof (struct signature))
123:
124: /*
125: * Function : dtc_setup(char *str, int *ints)
126: *
127: * Purpose : LILO command line initialization of the overrides array,
128: *
129: * Inputs : str - unused, ints - array of integer parameters with ints[0]
130: * equal to the number of ints.
131: *
132: */
133:
134: void dtc_setup(char *str, int *ints) {
135: static int commandline_current = 0;
136: int i;
137: if (ints[0] != 2)
138: printk("dtc_setup: usage dtc=address,irq\n");
139: else
140: if (commandline_current < NO_OVERRIDES) {
141: overrides[commandline_current].address = ints[1];
142: overrides[commandline_current].irq = ints[2];
143: for (i = 0; i < NO_BASES; ++i)
144: if (bases[i].address == ints[1]) {
145: bases[i].noauto = 1;
146: break;
147: }
148: ++commandline_current;
149: }
150: }
151:
152: /*
153: * Function : int dtc_detect(Scsi_Host_Template * tpnt)
154: *
155: * Purpose : detects and initializes DTC 3180/3280 controllers
156: * that were autoprobed, overridden on the LILO command line,
157: * or specified at compile time.
158: *
159: * Inputs : tpnt - template for this SCSI adapter.
160: *
161: * Returns : 1 if a host adapter was found, 0 if not.
162: *
163: */
164:
165:
166: int dtc_detect(Scsi_Host_Template * tpnt) {
167: static int current_override = 0, current_base = 0;
168: struct Scsi_Host *instance;
169: unsigned char *base;
170: int sig, count;
171:
172: tpnt->proc_dir = &proc_scsi_dtc;
173: tpnt->proc_info = &dtc_proc_info;
174:
175: for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
176: base = NULL;
177:
178: if (overrides[current_override].address)
179: base = (unsigned char *)overrides[current_override].address;
180: else
181: for (; !base && (current_base < NO_BASES); ++current_base) {
182: #if (DTCDEBUG & DTCDEBUG_INIT)
183: printk("scsi : probing address %08x\n", (unsigned int) bases[current_base].address);
184: #endif
185: for (sig = 0; sig < NO_SIGNATURES; ++sig)
186: if (!bases[current_base].noauto && !memcmp
187: ((unsigned char *)(bases[current_base].address + signatures[sig].offset),
188: signatures[sig].string, strlen(signatures[sig].string))) {
189: base = (unsigned char *)bases[current_base].address;
190: #if (DTCDEBUG & DTCDEBUG_INIT)
191: printk("scsi-dtc : detected board.\n");
192: #endif
193: break;
194: }
195: }
196:
197: #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
198: printk("scsi-dtc : base = %08x\n", (unsigned int) base);
199: #endif
200:
201: if (!base)
202: break;
203:
204: instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
205: instance->base = base;
206:
207: NCR5380_init(instance, 0);
208:
209: NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */
210: if (overrides[current_override].irq != IRQ_AUTO)
211: instance->irq = overrides[current_override].irq;
212: else
213: instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
214:
215: #ifndef DONT_USE_INTR
216: /* With interrupts enabled, it will sometimes hang when doing heavy
217: * reads. So better not enable them until I finger it out. */
218: if (instance->irq != IRQ_NONE)
219: if (request_irq(instance->irq, dtc_intr, SA_INTERRUPT, "dtc")) {
220: printk("scsi%d : IRQ%d not free, interrupts disabled\n",
221: instance->host_no, instance->irq);
222: instance->irq = IRQ_NONE;
223: }
224:
225: if (instance->irq == IRQ_NONE) {
226: printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
227: printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
228: }
229: #else
230: if (instance->irq != IRQ_NONE)
231: printk("scsi%d : interrupts not used. Might as well not jumper it.\n",
232: instance->host_no);
233: instance->irq = IRQ_NONE;
234: #endif
235: #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
236: printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
237: #endif
238:
239: printk("scsi%d : at 0x%05X", instance->host_no, (int)instance->base);
240: if (instance->irq == IRQ_NONE)
241: printk (" interrupts disabled");
242: else
243: printk (" irq %d", instance->irq);
244: printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
245: CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
246: NCR5380_print_options(instance);
247: printk("\n");
248:
249: ++current_override;
250: ++count;
251: }
252: return count;
253: }
254:
255: /*
256: * Function : int dtc_biosparam(Disk * disk, kdev_t dev, int *ip)
257: *
258: * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for
259: * the specified device / size.
260: *
261: * Inputs : size = size of device in sectors (512 bytes), dev = block device
262: * major / minor, ip[] = {heads, sectors, cylinders}
263: *
264: * Returns : always 0 (success), initializes ip
265: *
266: */
267:
268: /*
269: * XXX Most SCSI boards use this mapping, I could be incorrect. Some one
270: * using hard disks on a trantor should verify that this mapping corresponds
271: * to that used by the BIOS / ASPI driver by running the linux fdisk program
272: * and matching the H_C_S coordinates to what DOS uses.
273: */
274:
275: int dtc_biosparam(Disk * disk, kdev_t dev, int * ip)
276: {
277: int size = disk->capacity;
278:
279: ip[0] = 64;
280: ip[1] = 32;
281: ip[2] = size >> 11;
282: return 0;
283: }
284:
285: /****************************************************************
286: * Function : int NCR5380_pread (struct Scsi_Host *instance,
287: * unsigned char *dst, int len)
288: *
289: * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to
290: * dst
291: *
292: * Inputs : dst = destination, len = length in bytes
293: *
294: * Returns : 0 on success, non zero on a failure such as a watchdog
295: * timeout.
296: */
297:
298: static int dtc_maxi = 0;
299: static int dtc_wmaxi = 0;
300:
301: static inline int NCR5380_pread (struct Scsi_Host *instance,
302: unsigned char *dst, int len)
303: {
304: unsigned char *d = dst;
305: int i; /* For counting time spent in the poll-loop */
306: NCR5380_local_declare();
307: NCR5380_setup(instance);
308:
309: i = 0;
310: NCR5380_read(RESET_PARITY_INTERRUPT_REG);
311: NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
312: if (instance->irq == IRQ_NONE)
313: NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
314: else
315: NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
316: NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */
317: rtrc(1);
318: while (len > 0) {
319: rtrc(2);
320: while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
321: ++i;
322: rtrc(3);
323: memcpy(d, (char *)(base + DTC_DATA_BUF), 128);
324: d += 128;
325: len -= 128;
326: rtrc(7); /*** with int's on, it sometimes hangs after here.
327: * Looks like something makes HBNR go away. */
328: }
329: rtrc(4);
330: while ( !(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
331: ++i;
332: NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
333: rtrc(0);
334: NCR5380_read(RESET_PARITY_INTERRUPT_REG);
335: if (i > dtc_maxi)
336: dtc_maxi = i;
337: return(0);
338: }
339:
340: /****************************************************************
341: * Function : int NCR5380_pwrite (struct Scsi_Host *instance,
342: * unsigned char *src, int len)
343: *
344: * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
345: * src
346: *
347: * Inputs : src = source, len = length in bytes
348: *
349: * Returns : 0 on success, non zero on a failure such as a watchdog
350: * timeout.
351: */
352:
353: static inline int NCR5380_pwrite (struct Scsi_Host *instance,
354: unsigned char *src, int len) {
355: int i;
356: NCR5380_local_declare();
357: NCR5380_setup(instance);
358:
359: NCR5380_read(RESET_PARITY_INTERRUPT_REG);
360: NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
361: /* set direction (write) */
362: if (instance->irq == IRQ_NONE)
363: NCR5380_write(DTC_CONTROL_REG, 0);
364: else
365: NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
366: NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */
367: for (i = 0; len > 0; ++i) {
368: rtrc(5);
369: /* Poll until the host buffer can accept data. */
370: while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
371: ++i;
372: rtrc(3);
373: memcpy((char *)(base + DTC_DATA_BUF), src, 128);
374: src += 128;
375: len -= 128;
376: }
377: rtrc(4);
378: while ( !(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
379: ++i;
380: rtrc(6);
381: /* Wait until the last byte has been sent to the disk */
382: while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
383: ++i;
384: rtrc(7);
385: /* Check for parity error here. fixme. */
386: NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
387: rtrc(0);
388: if (i > dtc_wmaxi)
389: dtc_wmaxi = i;
390: return (0);
391: }
392:
393: #include "NCR5380.c"
394:
395: #ifdef MODULE
396: /* Eventually this will go into an include file, but this will be later */
397: Scsi_Host_Template driver_template = DTC3x80;
398:
399: #include "scsi_module.c"
400: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.