]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/scsi/dtc.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / 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 DMA_WORKS_RIGHT
7
8
9 /*
10  * DTC 3180/3280 driver, by
11  *      Ray Van Tassle  rayvt@comm.mot.com
12  *
13  *      taken from ...
14  *      Trantor T128/T128F/T228 driver by...
15  *
16  *      Drew Eckhardt
17  *      Visionary Computing
18  *      (Unix and Linux consulting and custom programming)
19  *      drew@colorado.edu
20  *      +1 (303) 440-4894
21  *
22  * DISTRIBUTION RELEASE 1.
23  *
24  * For more information, please consult 
25  *
26  * NCR 5380 Family
27  * SCSI Protocol Controller
28  * Databook
29 */
30
31 /*
32  * Options : 
33  * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
34  *      for commands that return with a CHECK CONDITION status. 
35  *
36  * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
37  * increase compared to polled I/O.
38  *
39  * PARITY - enable parity checking.  Not supported.
40  *
41  * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. 
42  *              You probably want this.
43  *
44  * The card is detected and initialized in one of several ways : 
45  * 1.  Autoprobe (default) - since the board is memory mapped, 
46  *     a BIOS signature is scanned for to locate the registers.
47  *     An interrupt is triggered to autoprobe for the interrupt
48  *     line.
49  *
50  * 2.  With command line overrides - dtc=address,irq may be 
51  *     used on the LILO command line to override the defaults.
52  * 
53 */
54
55 /*----------------------------------------------------------------*/
56 /* the following will set the monitor border color (useful to find
57  where something crashed or gets stuck at */
58 /* 1 = blue
59  2 = green
60  3 = cyan
61  4 = red
62  5 = magenta
63  6 = yellow
64  7 = white
65 */
66 #if 0
67 #define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);}
68 #else
69 #define rtrc(i) {}
70 #endif
71
72
73 #include <linux/module.h>
74 #include <linux/signal.h>
75 #include <linux/blkdev.h>
76 #include <linux/delay.h>
77 #include <linux/stat.h>
78 #include <linux/string.h>
79 #include <linux/init.h>
80 #include <linux/interrupt.h>
81 #include <linux/io.h>
82 #include "scsi.h"
83 #include <scsi/scsi_host.h>
84 #include "dtc.h"
85 #define AUTOPROBE_IRQ
86 #include "NCR5380.h"
87
88
89 #define DTC_PUBLIC_RELEASE 2
90
91 /*
92  * The DTC3180 & 3280 boards are memory mapped.
93  * 
94  */
95
96 /*
97  */
98 /* Offset from DTC_5380_OFFSET */
99 #define DTC_CONTROL_REG         0x100   /* rw */
100 #define D_CR_ACCESS             0x80    /* ro set=can access 3280 registers */
101 #define CSR_DIR_READ            0x40    /* rw direction, 1 = read 0 = write */
102
103 #define CSR_RESET              0x80     /* wo  Resets 53c400 */
104 #define CSR_5380_REG           0x80     /* ro  5380 registers can be accessed */
105 #define CSR_TRANS_DIR          0x40     /* rw  Data transfer direction */
106 #define CSR_SCSI_BUFF_INTR     0x20     /* rw  Enable int on transfer ready */
107 #define CSR_5380_INTR          0x10     /* rw  Enable 5380 interrupts */
108 #define CSR_SHARED_INTR        0x08     /* rw  Interrupt sharing */
109 #define CSR_HOST_BUF_NOT_RDY   0x04     /* ro  Host buffer not ready */
110 #define CSR_SCSI_BUF_RDY       0x02     /* ro  SCSI buffer ready */
111 #define CSR_GATED_5380_IRQ     0x01     /* ro  Last block xferred */
112 #define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR)
113
114
115 #define DTC_BLK_CNT             0x101   /* rw 
116                                          * # of 128-byte blocks to transfer */
117
118
119 #define D_CR_ACCESS             0x80    /* ro set=can access 3280 registers */
120
121 #define DTC_SWITCH_REG          0x3982  /* ro - DIP switches */
122 #define DTC_RESUME_XFER         0x3982  /* wo - resume data xfer 
123                                          * after disconnect/reconnect*/
124
125 #define DTC_5380_OFFSET         0x3880  /* 8 registers here, see NCR5380.h */
126
127 /*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */
128 #define DTC_DATA_BUF            0x3900  /* rw 128 bytes long */
129
130 static struct override {
131         unsigned int address;
132         int irq;
133 } overrides
134 #ifdef OVERRIDE
135 [] __initdata = OVERRIDE;
136 #else
137 [4] __initdata = {
138         { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }
139 };
140 #endif
141
142 #define NO_OVERRIDES ARRAY_SIZE(overrides)
143
144 static struct base {
145         unsigned long address;
146         int noauto;
147 } bases[] __initdata = {
148         { 0xcc000, 0 },
149         { 0xc8000, 0 },
150         { 0xdc000, 0 },
151         { 0xd8000, 0 }
152 };
153
154 #define NO_BASES ARRAY_SIZE(bases)
155
156 static const struct signature {
157         const char *string;
158         int offset;
159 } signatures[] = {
160         {"DATA TECHNOLOGY CORPORATION BIOS", 0x25},
161 };
162
163 #define NO_SIGNATURES ARRAY_SIZE(signatures)
164
165 #ifndef MODULE
166 /*
167  * Function : dtc_setup(char *str, int *ints)
168  *
169  * Purpose : LILO command line initialization of the overrides array,
170  *
171  * Inputs : str - unused, ints - array of integer parameters with ints[0]
172  *      equal to the number of ints.
173  *
174  */
175
176 static void __init dtc_setup(char *str, int *ints)
177 {
178         static int commandline_current = 0;
179         int i;
180         if (ints[0] != 2)
181                 printk("dtc_setup: usage dtc=address,irq\n");
182         else if (commandline_current < NO_OVERRIDES) {
183                 overrides[commandline_current].address = ints[1];
184                 overrides[commandline_current].irq = ints[2];
185                 for (i = 0; i < NO_BASES; ++i)
186                         if (bases[i].address == ints[1]) {
187                                 bases[i].noauto = 1;
188                                 break;
189                         }
190                 ++commandline_current;
191         }
192 }
193 #endif
194
195 /* 
196  * Function : int dtc_detect(struct scsi_host_template * tpnt)
197  *
198  * Purpose : detects and initializes DTC 3180/3280 controllers
199  *      that were autoprobed, overridden on the LILO command line, 
200  *      or specified at compile time.
201  *
202  * Inputs : tpnt - template for this SCSI adapter.
203  * 
204  * Returns : 1 if a host adapter was found, 0 if not.
205  *
206 */
207
208 static int __init dtc_detect(struct scsi_host_template * tpnt)
209 {
210         static int current_override = 0, current_base = 0;
211         struct Scsi_Host *instance;
212         unsigned int addr;
213         void __iomem *base;
214         int sig, count;
215
216         tpnt->proc_name = "dtc3x80";
217         tpnt->show_info = dtc_show_info;
218         tpnt->write_info = dtc_write_info;
219
220         for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
221                 addr = 0;
222                 base = NULL;
223
224                 if (overrides[current_override].address) {
225                         addr = overrides[current_override].address;
226                         base = ioremap(addr, 0x2000);
227                         if (!base)
228                                 addr = 0;
229                 } else
230                         for (; !addr && (current_base < NO_BASES); ++current_base) {
231 #if (DTCDEBUG & DTCDEBUG_INIT)
232                                 printk(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address);
233 #endif
234                                 if (bases[current_base].noauto)
235                                         continue;
236                                 base = ioremap(bases[current_base].address, 0x2000);
237                                 if (!base)
238                                         continue;
239                                 for (sig = 0; sig < NO_SIGNATURES; ++sig) {
240                                         if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
241                                                 addr = bases[current_base].address;
242 #if (DTCDEBUG & DTCDEBUG_INIT)
243                                                 printk(KERN_DEBUG "scsi-dtc : detected board.\n");
244 #endif
245                                                 goto found;
246                                         }
247                                 }
248                                 iounmap(base);
249                         }
250
251 #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
252                 printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr);
253 #endif
254
255                 if (!addr)
256                         break;
257
258 found:
259                 instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
260                 if (instance == NULL)
261                         break;
262
263                 instance->base = addr;
264                 ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base;
265
266                 NCR5380_init(instance, 0);
267
268                 NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);  /* Enable int's */
269                 if (overrides[current_override].irq != IRQ_AUTO)
270                         instance->irq = overrides[current_override].irq;
271                 else
272                         instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
273
274 #ifndef DONT_USE_INTR
275                 /* With interrupts enabled, it will sometimes hang when doing heavy
276                  * reads. So better not enable them until I finger it out. */
277                 if (instance->irq != SCSI_IRQ_NONE)
278                         if (request_irq(instance->irq, dtc_intr, 0,
279                                         "dtc", instance)) {
280                                 printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
281                                 instance->irq = SCSI_IRQ_NONE;
282                         }
283
284                 if (instance->irq == SCSI_IRQ_NONE) {
285                         printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
286                         printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
287                 }
288 #else
289                 if (instance->irq != SCSI_IRQ_NONE)
290                         printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
291                 instance->irq = SCSI_IRQ_NONE;
292 #endif
293 #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
294                 printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
295 #endif
296
297                 printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
298                 if (instance->irq == SCSI_IRQ_NONE)
299                         printk(" interrupts disabled");
300                 else
301                         printk(" irq %d", instance->irq);
302                 printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
303                 NCR5380_print_options(instance);
304                 printk("\n");
305
306                 ++current_override;
307                 ++count;
308         }
309         return count;
310 }
311
312 /*
313  * Function : int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip)
314  *
315  * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for 
316  *      the specified device / size.
317  * 
318  * Inputs : size = size of device in sectors (512 bytes), dev = block device
319  *      major / minor, ip[] = {heads, sectors, cylinders}  
320  *
321  * Returns : always 0 (success), initializes ip
322  *      
323 */
324
325 /* 
326  * XXX Most SCSI boards use this mapping, I could be incorrect.  Some one
327  * using hard disks on a trantor should verify that this mapping corresponds
328  * to that used by the BIOS / ASPI driver by running the linux fdisk program
329  * and matching the H_C_S coordinates to what DOS uses.
330 */
331
332 static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev,
333                          sector_t capacity, int *ip)
334 {
335         int size = capacity;
336
337         ip[0] = 64;
338         ip[1] = 32;
339         ip[2] = size >> 11;
340         return 0;
341 }
342
343
344 /****************************************************************
345  * Function : int NCR5380_pread (struct Scsi_Host *instance, 
346  *      unsigned char *dst, int len)
347  *
348  * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to 
349  *      dst
350  * 
351  * Inputs : dst = destination, len = length in bytes
352  *
353  * Returns : 0 on success, non zero on a failure such as a watchdog 
354  *      timeout.
355 */
356
357 static int dtc_maxi = 0;
358 static int dtc_wmaxi = 0;
359
360 static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
361 {
362         unsigned char *d = dst;
363         int i;                  /* For counting time spent in the poll-loop */
364         NCR5380_local_declare();
365         NCR5380_setup(instance);
366
367         i = 0;
368         NCR5380_read(RESET_PARITY_INTERRUPT_REG);
369         NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
370         if (instance->irq == SCSI_IRQ_NONE)
371                 NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
372         else
373                 NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
374         NCR5380_write(DTC_BLK_CNT, len >> 7);   /* Block count */
375         rtrc(1);
376         while (len > 0) {
377                 rtrc(2);
378                 while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
379                         ++i;
380                 rtrc(3);
381                 memcpy_fromio(d, base + DTC_DATA_BUF, 128);
382                 d += 128;
383                 len -= 128;
384                 rtrc(7);
385                 /*** with int's on, it sometimes hangs after here.
386                  * Looks like something makes HBNR go away. */
387         }
388         rtrc(4);
389         while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
390                 ++i;
391         NCR5380_write(MODE_REG, 0);     /* Clear the operating mode */
392         rtrc(0);
393         NCR5380_read(RESET_PARITY_INTERRUPT_REG);
394         if (i > dtc_maxi)
395                 dtc_maxi = i;
396         return (0);
397 }
398
399 /****************************************************************
400  * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 
401  *      unsigned char *src, int len)
402  *
403  * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
404  *      src
405  * 
406  * Inputs : src = source, len = length in bytes
407  *
408  * Returns : 0 on success, non zero on a failure such as a watchdog 
409  *      timeout.
410 */
411
412 static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
413 {
414         int i;
415         NCR5380_local_declare();
416         NCR5380_setup(instance);
417
418         NCR5380_read(RESET_PARITY_INTERRUPT_REG);
419         NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
420         /* set direction (write) */
421         if (instance->irq == SCSI_IRQ_NONE)
422                 NCR5380_write(DTC_CONTROL_REG, 0);
423         else
424                 NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
425         NCR5380_write(DTC_BLK_CNT, len >> 7);   /* Block count */
426         for (i = 0; len > 0; ++i) {
427                 rtrc(5);
428                 /* Poll until the host buffer can accept data. */
429                 while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
430                         ++i;
431                 rtrc(3);
432                 memcpy_toio(base + DTC_DATA_BUF, src, 128);
433                 src += 128;
434                 len -= 128;
435         }
436         rtrc(4);
437         while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
438                 ++i;
439         rtrc(6);
440         /* Wait until the last byte has been sent to the disk */
441         while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
442                 ++i;
443         rtrc(7);
444         /* Check for parity error here. fixme. */
445         NCR5380_write(MODE_REG, 0);     /* Clear the operating mode */
446         rtrc(0);
447         if (i > dtc_wmaxi)
448                 dtc_wmaxi = i;
449         return (0);
450 }
451
452 MODULE_LICENSE("GPL");
453
454 #include "NCR5380.c"
455
456 static int dtc_release(struct Scsi_Host *shost)
457 {
458         NCR5380_local_declare();
459         NCR5380_setup(shost);
460         if (shost->irq)
461                 free_irq(shost->irq, shost);
462         NCR5380_exit(shost);
463         if (shost->io_port && shost->n_io_port)
464                 release_region(shost->io_port, shost->n_io_port);
465         scsi_unregister(shost);
466         iounmap(base);
467         return 0;
468 }
469
470 static struct scsi_host_template driver_template = {
471         .name                           = "DTC 3180/3280 ",
472         .detect                         = dtc_detect,
473         .release                        = dtc_release,
474         .queuecommand                   = dtc_queue_command,
475         .eh_abort_handler               = dtc_abort,
476         .eh_bus_reset_handler           = dtc_bus_reset,
477         .bios_param                     = dtc_biosparam,
478         .can_queue                      = CAN_QUEUE,
479         .this_id                        = 7,
480         .sg_tablesize                   = SG_ALL,
481         .cmd_per_lun                    = CMD_PER_LUN,
482         .use_clustering                 = DISABLE_CLUSTERING,
483 };
484 #include "scsi_module.c"