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