~ubuntu-branches/ubuntu/utopic/linux-ti-omap/utopic

« back to all changes in this revision

Viewing changes to drivers/scsi/dtc.c

  • Committer: Bazaar Package Importer
  • Author(s): Amit Kucheria, Amit Kucheria
  • Date: 2010-03-10 02:28:15 UTC
  • Revision ID: james.westby@ubuntu.com-20100310022815-7sd3gwvn5kenaq33
Tags: 2.6.33-500.1
[ Amit Kucheria ]

* Initial release of a 2.6.33-based OMAP kernel
* UBUNTU: [Upstream] Fix omap 1-wire driver compilation
* UBUNTU: ubuntu: AppArmor -- update to mainline 2010-03-04

Show diffs side-by-side

added added

removed removed

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