File: /usr/src/linux/drivers/scsi/dtc.c

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	rayvt@comm.mot.com
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      *	drew@colorado.edu
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     #include <linux/init.h>
90     
91     
92     #define DTC_PUBLIC_RELEASE 2
93     
94     /*#define DTCDEBUG 0x1*/
95     #define DTCDEBUG_INIT	0x1
96     #define DTCDEBUG_TRANSFER 0x2
97     
98     /*
99      * The DTC3180 & 3280 boards are memory mapped.
100      * 
101      */
102     
103     /*
104      */ 
105     /* Offset from DTC_5380_OFFSET */
106     #define DTC_CONTROL_REG		0x100	/* rw */
107     #define D_CR_ACCESS		0x80	/* ro set=can access 3280 registers */
108     #define CSR_DIR_READ		0x40	/* rw direction, 1 = read 0 = write */
109     
110     #define CSR_RESET              0x80    /* wo  Resets 53c400 */
111     #define CSR_5380_REG           0x80    /* ro  5380 registers can be accessed */
112     #define CSR_TRANS_DIR          0x40    /* rw  Data transfer direction */
113     #define CSR_SCSI_BUFF_INTR     0x20    /* rw  Enable int on transfer ready */
114     #define CSR_5380_INTR          0x10    /* rw  Enable 5380 interrupts */
115     #define CSR_SHARED_INTR        0x08    /* rw  Interrupt sharing */
116     #define CSR_HOST_BUF_NOT_RDY   0x04    /* ro  Host buffer not ready */
117     #define CSR_SCSI_BUF_RDY       0x02    /* ro  SCSI buffer ready */
118     #define CSR_GATED_5380_IRQ     0x01    /* ro  Last block xferred */
119     #define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR)
120     
121     
122     #define DTC_BLK_CNT		0x101   /* rw 
123     					 * # of 128-byte blocks to transfer */
124     
125     
126     #define D_CR_ACCESS             0x80    /* ro set=can access 3280 registers */
127     
128     #define DTC_SWITCH_REG		0x3982	/* ro - DIP switches */
129     #define DTC_RESUME_XFER		0x3982	/* wo - resume data xfer 
130     					   * after disconnect/reconnect*/
131     
132     #define DTC_5380_OFFSET		0x3880	/* 8 registers here, see NCR5380.h */
133     
134     /*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */
135     #define DTC_DATA_BUF		0x3900  /* rw 128 bytes long */
136     
137     static struct override {
138        unsigned int address;
139        int irq;
140     } overrides
141     #ifdef OVERRIDE
142     [] __initdata = OVERRIDE;
143     #else
144     [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO}};
145     #endif
146     
147     #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
148     
149     static struct base {
150        unsigned long address;
151        int noauto;
152     } bases[] __initdata = {{0xcc000, 0}, {0xc8000, 0}, {0xdc000, 0}, {0xd8000, 0}};
153     
154     #define NO_BASES (sizeof (bases) / sizeof (struct base))
155     
156     static const struct signature {
157        const char *string;
158        int offset;
159     } signatures[] = { {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, };
160     
161     #define NO_SIGNATURES (sizeof (signatures) /  sizeof (struct signature))
162     
163     /*
164      * Function : dtc_setup(char *str, int *ints)
165      *
166      * Purpose : LILO command line initialization of the overrides array,
167      * 
168      * Inputs : str - unused, ints - array of integer parameters with ints[0]
169      *	equal to the number of ints.
170      *
171     */
172     
173     void __init dtc_setup(char *str, int *ints){
174        static int commandline_current = 0;
175        int i;
176        if (ints[0] != 2)
177           printk("dtc_setup: usage dtc=address,irq\n");
178        else
179           if (commandline_current < NO_OVERRIDES) {
180           overrides[commandline_current].address = ints[1];
181           overrides[commandline_current].irq = ints[2];
182           for (i = 0; i < NO_BASES; ++i)
183     	 if (bases[i].address == ints[1]) {
184     	 bases[i].noauto = 1;
185     	 break;
186           }
187           ++commandline_current;
188        }
189     }
190     
191     /* 
192      * Function : int dtc_detect(Scsi_Host_Template * tpnt)
193      *
194      * Purpose : detects and initializes DTC 3180/3280 controllers
195      *	that were autoprobed, overridden on the LILO command line, 
196      *	or specified at compile time.
197      *
198      * Inputs : tpnt - template for this SCSI adapter.
199      * 
200      * Returns : 1 if a host adapter was found, 0 if not.
201      *
202     */
203     
204     int __init dtc_detect(Scsi_Host_Template * tpnt){
205        static int current_override = 0, current_base = 0;
206        struct Scsi_Host *instance;
207        unsigned int base;
208        int sig, count;
209     
210        tpnt->proc_name = "dtc3x80";
211        tpnt->proc_info = &dtc_proc_info;
212     
213        for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
214           base = 0;
215     
216           if (overrides[current_override].address)
217     	 base = overrides[current_override].address;
218           else
219     	 for (; !base && (current_base < NO_BASES); ++current_base) {
220     #if (DTCDEBUG & DTCDEBUG_INIT)
221     	 printk("scsi-dtc : probing address %08x\n", bases[current_base].address);
222     #endif
223     	 for (sig = 0; sig < NO_SIGNATURES; ++sig)
224     	    if (!bases[current_base].noauto && 
225     		isa_check_signature(bases[current_base].address +
226     				signatures[sig].offset,
227     	      signatures[sig].string, strlen(signatures[sig].string))) {
228     	    base = bases[current_base].address;
229     #if (DTCDEBUG & DTCDEBUG_INIT)
230     	    printk("scsi-dtc : detected board.\n");
231     #endif
232     	    break;
233     	 }
234           }
235     
236     #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
237           printk("scsi-dtc : base = %08x\n", base);
238     #endif
239     
240           if (!base)
241     	 break;
242     
243           instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
244           if(instance == NULL)
245           	break;
246           	
247           instance->base = base;
248     
249           NCR5380_init(instance, 0);
250     
251           NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */
252           if (overrides[current_override].irq != IRQ_AUTO)
253     	 instance->irq = overrides[current_override].irq;
254           else
255     	 instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
256     
257     #ifndef DONT_USE_INTR
258     /* With interrupts enabled, it will sometimes hang when doing heavy
259      * reads. So better not enable them until I finger it out. */
260           if (instance->irq != IRQ_NONE)
261     	 if (request_irq(instance->irq, do_dtc_intr, SA_INTERRUPT, "dtc")) {
262     	 printk("scsi%d : IRQ%d not free, interrupts disabled\n",
263     	      instance->host_no, instance->irq);
264     	 instance->irq = IRQ_NONE;
265           }
266     
267           if (instance->irq == IRQ_NONE) {
268     	 printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
269     	 printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
270           }
271     #else
272           if (instance->irq != IRQ_NONE)
273     	 printk("scsi%d : interrupts not used. Might as well not jumper it.\n",
274     		instance->host_no);
275           instance->irq = IRQ_NONE;
276     #endif
277     #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
278           printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
279     #endif
280     
281           printk("scsi%d : at 0x%05X", instance->host_no, (int)instance->base);
282           if (instance->irq == IRQ_NONE)
283     	 printk (" interrupts disabled");
284           else
285     	 printk (" irq %d", instance->irq);
286           printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
287     	   CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
288           NCR5380_print_options(instance);
289           printk("\n");
290     
291           ++current_override;
292           ++count;
293        }
294        return count;
295     }
296     
297     /*
298      * Function : int dtc_biosparam(Disk * disk, kdev_t dev, int *ip)
299      *
300      * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for 
301      *	the specified device / size.
302      * 
303      * Inputs : size = size of device in sectors (512 bytes), dev = block device
304      *	major / minor, ip[] = {heads, sectors, cylinders}  
305      *
306      * Returns : always 0 (success), initializes ip
307      *	
308     */
309     
310     /* 
311      * XXX Most SCSI boards use this mapping, I could be incorrect.  Some one
312      * using hard disks on a trantor should verify that this mapping corresponds
313      * to that used by the BIOS / ASPI driver by running the linux fdisk program
314      * and matching the H_C_S coordinates to what DOS uses.
315     */
316     
317     int dtc_biosparam(Disk * disk, kdev_t dev, int * ip)
318     {
319        int size = disk->capacity;
320     
321        ip[0] = 64;
322        ip[1] = 32;
323        ip[2] = size >> 11;
324        return 0;
325     }
326     
327     
328     /****************************************************************
329      * Function : int NCR5380_pread (struct Scsi_Host *instance, 
330      *	unsigned char *dst, int len)
331      *
332      * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to 
333      *	dst
334      * 
335      * Inputs : dst = destination, len = length in bytes
336      *
337      * Returns : 0 on success, non zero on a failure such as a watchdog 
338      * 	timeout.
339     */
340     
341     static int dtc_maxi = 0;
342     static int dtc_wmaxi = 0;
343     
344     static inline int NCR5380_pread (struct Scsi_Host *instance,
345          unsigned char *dst, int len)
346          {
347        unsigned char *d = dst;
348        int i;	/* For counting time spent in the poll-loop */
349        NCR5380_local_declare();
350        NCR5380_setup(instance);
351     
352        i = 0;
353        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
354        NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
355        if (instance->irq == IRQ_NONE)
356           NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
357        else
358           NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
359        NCR5380_write(DTC_BLK_CNT, len >> 7);        /* Block count */
360        rtrc(1);
361        while (len > 0) {
362           rtrc(2);
363           while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
364     	 ++i;
365           rtrc(3);
366           isa_memcpy_fromio(d, base + DTC_DATA_BUF, 128);
367           d += 128;
368           len -= 128;
369           rtrc(7);	/*** with int's on, it sometimes hangs after here.
370     		 * Looks like something makes HBNR go away. */
371        }
372        rtrc(4);
373        while ( !(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
374           ++i;
375        NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
376        rtrc(0);
377        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
378        if (i > dtc_maxi)
379           dtc_maxi = i;
380        return(0);
381     }
382     
383     /****************************************************************
384      * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 
385      *	unsigned char *src, int len)
386      *
387      * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
388      *	src
389      * 
390      * Inputs : src = source, len = length in bytes
391      *
392      * Returns : 0 on success, non zero on a failure such as a watchdog 
393      * 	timeout.
394     */
395     
396     static inline int NCR5380_pwrite (struct Scsi_Host *instance,
397          unsigned char *src, int len) {
398        int i;
399        NCR5380_local_declare();
400        NCR5380_setup(instance);
401     
402        NCR5380_read(RESET_PARITY_INTERRUPT_REG);
403        NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
404        /* set direction (write) */
405        if (instance->irq == IRQ_NONE)
406           NCR5380_write(DTC_CONTROL_REG, 0);
407        else
408           NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
409        NCR5380_write(DTC_BLK_CNT, len >> 7);        /* Block count */
410        for (i = 0; len > 0; ++i) {
411           rtrc(5);
412           /* Poll until the host buffer can accept data. */
413           while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
414     	 ++i;
415           rtrc(3);
416           isa_memcpy_toio(base + DTC_DATA_BUF, src, 128);
417           src += 128;
418           len -= 128;
419        }
420        rtrc(4);
421        while ( !(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
422           ++i;
423        rtrc(6);
424        /* Wait until the last byte has been sent to the disk */
425        while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
426           ++i;
427        rtrc(7);
428        /* Check for parity error here. fixme. */
429        NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
430        rtrc(0);
431        if (i > dtc_wmaxi)
432           dtc_wmaxi = i;
433        return (0);
434     }
435     
436     #include "NCR5380.c"
437     
438     /* Eventually this will go into an include file, but this will be later */
439     static Scsi_Host_Template driver_template = DTC3x80;
440     #include "scsi_module.c"
441