OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [mca_53c9x.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* mca_53c9x.c: Driver for the SCSI adapter found on NCR 35xx
2
 *  (and maybe some other) Microchannel machines
3
 *
4
 * Code taken mostly from Cyberstorm SCSI drivers
5
 *   Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
6
 *
7
 * Hacked to work with the NCR MCA stuff by Tymm Twillman (tymm@computer.org)
8
 *
9
 * The CyberStorm SCSI driver (and this driver) is based on David S. Miller's
10
 *   ESP driver  * for the Sparc computers.
11
 *
12
 * Special thanks to Ken Stewart at Symbios (LSI) for helping with info on
13
 *  the 86C01.  I was on the brink of going ga-ga...
14
 *
15
 * Also thanks to Jesper Skov for helping me with info on how the Amiga
16
 *  does things...
17
 */
18
 
19
/*
20
 * This is currently only set up to use one 53c9x card at a time; it could be
21
 *  changed fairly easily to detect/use more than one, but I'm not too sure how
22
 *  many cards that use the 53c9x on MCA systems there are (if, in fact, there
23
 *  are cards that use them, other than the one built into some NCR systems)...
24
 *  If anyone requests this, I'll throw it in, otherwise it's not worth the
25
 *  effort.
26
 */
27
 
28
/*
29
 * Info on the 86C01 MCA interface chip at the bottom, if you care enough to
30
 *  look.
31
 */
32
 
33
#include <linux/kernel.h>
34
#include <linux/delay.h>
35
#include <linux/types.h>
36
#include <linux/string.h>
37
#include <linux/slab.h>
38
#include <linux/blk.h>
39
#include <linux/proc_fs.h>
40
#include <linux/stat.h>
41
 
42
#include "scsi.h"
43
#include "hosts.h"
44
#include "NCR53C9x.h"
45
#include "mca_53c9x.h"
46
 
47
#include <asm/dma.h>
48
#include <linux/mca.h>
49
#include <asm/irq.h>
50
#include <asm/mca_dma.h>
51
 
52
#include <asm/pgtable.h>
53
 
54
static int  dma_bytes_sent(struct NCR_ESP *, int);
55
static int  dma_can_transfer(struct NCR_ESP *, Scsi_Cmnd *);
56
static void dma_dump_state(struct NCR_ESP *);
57
static void dma_init_read(struct NCR_ESP *, __u32, int);
58
static void dma_init_write(struct NCR_ESP *, __u32, int);
59
static void dma_ints_off(struct NCR_ESP *);
60
static void dma_ints_on(struct NCR_ESP *);
61
static int  dma_irq_p(struct NCR_ESP *);
62
static int  dma_ports_p(struct NCR_ESP *);
63
static void dma_setup(struct NCR_ESP *, __u32, int, int);
64
static void dma_led_on(struct NCR_ESP *);
65
static void dma_led_off(struct NCR_ESP *);
66
 
67
/* This is where all commands are put before they are trasfered to the
68
 *  53c9x via PIO.
69
 */
70
 
71
static volatile unsigned char cmd_buffer[16];
72
 
73
/*
74
 * We keep the structure that is used to access the registers on the 53c9x
75
 *  here.
76
 */
77
 
78
static struct ESP_regs eregs;
79
 
80
/***************************************************************** Detection */
81
int mca_esp_detect(Scsi_Host_Template *tpnt)
82
{
83
        struct NCR_ESP *esp;
84
        static int io_port_by_pos[] = MCA_53C9X_IO_PORTS;
85
        int mca_53c9x_ids[] = MCA_53C9X_IDS;
86
        int *id_to_check = mca_53c9x_ids;
87
        int slot;
88
        int pos[3];
89
        unsigned int tmp_io_addr;
90
        unsigned char tmp_byte;
91
 
92
 
93
        if (!MCA_bus)
94
                return 0;
95
 
96
        while (*id_to_check) {
97
                if ((slot = mca_find_adapter(*id_to_check, 0)) !=
98
                  MCA_NOTFOUND)
99
                {
100
                        esp = esp_allocate(tpnt, (void *) NULL);
101
 
102
                        pos[0] = mca_read_stored_pos(slot, 2);
103
                        pos[1] = mca_read_stored_pos(slot, 3);
104
                        pos[2] = mca_read_stored_pos(slot, 4);
105
 
106
                        esp->eregs = &eregs;
107
 
108
                        /*
109
                         * IO port base is given in the first (non-ID) pos
110
                         *  register, like so:
111
                         *
112
                         *  Bits 3  2  1       IO base
113
                         * ----------------------------
114
                         *       0  0  0       <disabled>
115
                         *       0  0  1       0x0240
116
                         *       0  1  0       0x0340
117
                         *       0  1  1       0x0400
118
                         *       1  0  0       0x0420
119
                         *       1  0  1       0x3240
120
                         *       1  1  0       0x8240
121
                         *       1  1  1       0xA240
122
                         */
123
 
124
                        tmp_io_addr =
125
                          io_port_by_pos[(pos[0] & 0x0E) >> 1];
126
 
127
                        esp->eregs->io_addr = tmp_io_addr + 0x10;
128
 
129
                        if (esp->eregs->io_addr == 0x0000) {
130
                                printk("Adapter is disabled.\n");
131
                                break;
132
                        }
133
 
134
                        /*
135
                         * IRQ is specified in bits 4 and 5:
136
                         *
137
                         *  Bits  4  5        IRQ
138
                         * -----------------------
139
                         *        0  0         3
140
                         *        0  1         5
141
                         *        1  0         7
142
                         *        1  1         9
143
                         */
144
 
145
                        esp->irq = ((pos[0] & 0x30) >> 3) + 3;
146
 
147
                        /*
148
                         * DMA channel is in the low 3 bits of the second
149
                         *  POS register
150
                         */
151
 
152
                        esp->dma = pos[1] & 7;
153
                        esp->slot = slot;
154
 
155
                        if (request_irq(esp->irq, esp_intr, 0,
156
                         "NCR 53c9x SCSI", esp_intr))
157
                        {
158
                                printk("Unable to request IRQ %d.\n", esp->irq);
159
                                esp_deallocate(esp);
160
                                scsi_unregister(esp->ehost);
161
                                return 0;
162
                        }
163
 
164
                        if (request_dma(esp->dma, "NCR 53c9x SCSI")) {
165
                                printk("Unable to request DMA channel %d.\n",
166
                                 esp->dma);
167
                                free_irq(esp->irq, esp_intr);
168
                                esp_deallocate(esp);
169
                                scsi_unregister(esp->ehost);
170
                                return 0;
171
                        }
172
 
173
                        request_region(tmp_io_addr, 32, "NCR 53c9x SCSI");
174
 
175
                        /*
176
                         * 86C01 handles DMA, IO mode, from address
177
                         *  (base + 0x0a)
178
                         */
179
 
180
                        mca_disable_dma(esp->dma);
181
                        mca_set_dma_io(esp->dma, tmp_io_addr + 0x0a);
182
                        mca_enable_dma(esp->dma);
183
 
184
                        /* Tell the 86C01 to give us interrupts */
185
 
186
                        tmp_byte = inb(tmp_io_addr + 0x02) | 0x40;
187
                        outb(tmp_byte, tmp_io_addr + 0x02);
188
 
189
                        /*
190
                         * Scsi ID -- general purpose register, hi
191
                         *  2 bits; add 4 to this number to get the
192
                         *  ID
193
                         */
194
 
195
                        esp->scsi_id = ((pos[2] & 0xC0) >> 6) + 4;
196
 
197
                        /* Do command transfer with programmed I/O */
198
 
199
                        esp->do_pio_cmds = 1;
200
 
201
                        /* Required functions */
202
 
203
                        esp->dma_bytes_sent = &dma_bytes_sent;
204
                        esp->dma_can_transfer = &dma_can_transfer;
205
                        esp->dma_dump_state = &dma_dump_state;
206
                        esp->dma_init_read = &dma_init_read;
207
                        esp->dma_init_write = &dma_init_write;
208
                        esp->dma_ints_off = &dma_ints_off;
209
                        esp->dma_ints_on = &dma_ints_on;
210
                        esp->dma_irq_p = &dma_irq_p;
211
                        esp->dma_ports_p = &dma_ports_p;
212
                        esp->dma_setup = &dma_setup;
213
 
214
                        /* Optional functions */
215
 
216
                        esp->dma_barrier = 0;
217
                        esp->dma_drain = 0;
218
                        esp->dma_invalidate = 0;
219
                        esp->dma_irq_entry = 0;
220
                        esp->dma_irq_exit = 0;
221
                        esp->dma_led_on = dma_led_on;
222
                        esp->dma_led_off = dma_led_off;
223
                        esp->dma_poll = 0;
224
                        esp->dma_reset = 0;
225
 
226
                        /* Set the command buffer */
227
 
228
                        esp->esp_command = (volatile unsigned char*)
229
                          cmd_buffer;
230
                        esp->esp_command_dvma = virt_to_bus(cmd_buffer);
231
 
232
                        /* SCSI chip speed */
233
 
234
                        esp->cfreq = 25000000;
235
 
236
                        /* Differential SCSI? I think not. */
237
 
238
                        esp->diff = 0;
239
 
240
                        esp_initialize(esp);
241
 
242
                        printk(" Adapter found in slot %2d: io port 0x%x "
243
                          "irq %d dma channel %d\n", slot + 1, tmp_io_addr,
244
                           esp->irq, esp->dma);
245
 
246
                        mca_set_adapter_name(slot, "NCR 53C9X SCSI Adapter");
247
                        mca_mark_as_used(slot);
248
 
249
                        break;
250
                }
251
 
252
                id_to_check++;
253
        }
254
 
255
        return esps_in_use;
256
}
257
 
258
 
259
/******************************************************************* Release */
260
 
261
int mca_esp_release(struct Scsi_Host *host)
262
{
263
        struct NCR_ESP *esp = (struct NCR_ESP *)host->hostdata;
264
        unsigned char tmp_byte;
265
 
266
        esp_deallocate(esp);
267
        /*
268
         * Tell the 86C01 to stop sending interrupts
269
         */
270
 
271
        tmp_byte = inb(esp->eregs->io_addr - 0x0E);
272
        tmp_byte &= ~0x40;
273
        outb(tmp_byte, esp->eregs->io_addr - 0x0E);
274
 
275
        free_irq(esp->irq, esp_intr);
276
        free_dma(esp->dma);
277
 
278
        mca_mark_as_unused(esp->slot);
279
 
280
        return 0;
281
}
282
 
283
/************************************************************* DMA Functions */
284
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
285
{
286
        /* Ask the 53c9x.  It knows. */
287
 
288
        return fifo_count;
289
}
290
 
291
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
292
{
293
        /*
294
         * The MCA dma channels can only do up to 128K bytes at a time.
295
         *  (16 bit mode)
296
         */
297
 
298
        unsigned long sz = sp->SCp.this_residual;
299
        if(sz > 0x20000)
300
                sz = 0x20000;
301
        return sz;
302
}
303
 
304
static void dma_dump_state(struct NCR_ESP *esp)
305
{
306
        /*
307
         * Doesn't quite match up to the other drivers, but we do what we
308
         *  can.
309
         */
310
 
311
        ESPLOG(("esp%d: dma channel <%d>\n", esp->esp_id, esp->dma));
312
        ESPLOG(("bytes left to dma: %d\n", mca_get_dma_residue(esp->dma)));
313
}
314
 
315
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
316
{
317
        unsigned long flags;
318
 
319
 
320
        save_flags(flags);
321
        cli();
322
 
323
        mca_disable_dma(esp->dma);
324
        mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_16 |
325
          MCA_DMA_MODE_IO);
326
        mca_set_dma_addr(esp->dma, addr);
327
        mca_set_dma_count(esp->dma, length / 2); /* !!! */
328
        mca_enable_dma(esp->dma);
329
 
330
        restore_flags(flags);
331
}
332
 
333
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
334
{
335
        unsigned long flags;
336
 
337
 
338
        save_flags(flags);
339
        cli();
340
 
341
        mca_disable_dma(esp->dma);
342
        mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_WRITE |
343
          MCA_DMA_MODE_16 | MCA_DMA_MODE_IO);
344
        mca_set_dma_addr(esp->dma, addr);
345
        mca_set_dma_count(esp->dma, length / 2); /* !!! */
346
        mca_enable_dma(esp->dma);
347
 
348
        restore_flags(flags);
349
}
350
 
351
static void dma_ints_off(struct NCR_ESP *esp)
352
{
353
        /*
354
         * Tell the 'C01 to shut up.  All interrupts are routed through it.
355
         */
356
 
357
        outb(inb(esp->eregs->io_addr - 0x0E) & ~0x40,
358
         esp->eregs->io_addr - 0x0E);
359
}
360
 
361
static void dma_ints_on(struct NCR_ESP *esp)
362
{
363
        /*
364
         * Ok.  You can speak again.
365
         */
366
 
367
        outb(inb(esp->eregs->io_addr - 0x0E) | 0x40,
368
         esp->eregs->io_addr - 0x0E);
369
}
370
 
371
static int dma_irq_p(struct NCR_ESP *esp)
372
{
373
        /*
374
         * DaveM says that this should return a "yes" if there is an interrupt
375
         *  or a DMA error occurred.  I copied the Amiga driver's semantics,
376
         *  though, because it seems to work and we can't really tell if
377
         *  a DMA error happened.  This gives the "yes" if the scsi chip
378
         *  is sending an interrupt and no DMA activity is taking place
379
         */
380
 
381
        return (!(inb(esp->eregs->io_addr - 0x04) & 1) &&
382
         !(inb(esp->eregs->io_addr - 0x04) & 2) );
383
}
384
 
385
static int dma_ports_p(struct NCR_ESP *esp)
386
{
387
        /*
388
         * Check to see if interrupts are enabled on the 'C01 (in case abort
389
         *  is entered multiple times, so we only do the abort once)
390
         */
391
 
392
        return (inb(esp->eregs->io_addr - 0x0E) & 0x40) ? 1:0;
393
}
394
 
395
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
396
{
397
        if(write){
398
                dma_init_write(esp, addr, count);
399
        } else {
400
                dma_init_read(esp, addr, count);
401
        }
402
}
403
 
404
/*
405
 * These will not play nicely with other disk controllers that try to use the
406
 *  disk active LED... but what can you do?  Don't answer that.
407
 *
408
 * Stolen shamelessly from ibmmca.c -- IBM Microchannel SCSI adapter driver
409
 *
410
 */
411
 
412
static void dma_led_on(struct NCR_ESP *esp)
413
{
414
        outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR);
415
}
416
 
417
static void dma_led_off(struct NCR_ESP *esp)
418
{
419
        outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR);
420
}
421
 
422
static Scsi_Host_Template driver_template = MCA_53C9X;
423
#include "scsi_module.c"
424
 
425
/*
426
 * OK, here's the goods I promised.  The NCR 86C01 is an MCA interface chip
427
 *  that handles enabling/diabling IRQ, dma interfacing, IO port selection
428
 *  and other fun stuff.  It takes up 16 addresses, and the chip it is
429
 *  connnected to gets the following 16.  Registers are as follows:
430
 *
431
 * Offsets 0-1 : Card ID
432
 *
433
 * Offset    2 : Mode enable register --
434
 *                Bit    7 : Data Word width (1 = 16, 0 = 8)
435
 *                Bit    6 : IRQ enable (1 = enabled)
436
 *                Bits 5,4 : IRQ select
437
 *                              0  0 : IRQ 3
438
 *                              0  1 : IRQ 5
439
 *                              1  0 : IRQ 7
440
 *                              1  1 : IRQ 9
441
 *                Bits 3-1 : Base Address
442
 *                           0  0  0 : <disabled>
443
 *                           0  0  1 : 0x0240
444
 *                           0  1  0 : 0x0340
445
 *                           0  1  1 : 0x0400
446
 *                           1  0  0 : 0x0420
447
 *                           1  0  1 : 0x3240
448
 *                           1  1  0 : 0x8240
449
 *                           1  1  1 : 0xA240
450
 *                Bit    0 : Card enable (1 = enabled)
451
 *
452
 * Offset    3 : DMA control register --
453
 *                Bit    7 : DMA enable (1 = enabled)
454
 *                Bits 6,5 : Preemt Count Select (transfers to complete after
455
 *                            'C01 has been preempted on MCA bus)
456
 *                              0  0 : 0
457
 *                              0  1 : 1
458
 *                              1  0 : 3
459
 *                              1  1 : 7
460
 *  (all these wacky numbers; I'm sure there's a reason somewhere)
461
 *                Bit    4 : Fairness enable (1 = fair bus priority)
462
 *                Bits 3-0 : Arbitration level (0-15 consecutive)
463
 *
464
 * Offset    4 : General purpose register
465
 *                Bits 7-3 : User definable (here, 7,6 are SCSI ID)
466
 *                Bits 2-0 : reserved
467
 *
468
 * Offset   10 : DMA decode register (used for IO based DMA; also can do
469
 *                PIO through this port)
470
 *
471
 * Offset   12 : Status
472
 *                Bits 7-2 : reserved
473
 *                Bit    1 : DMA pending (1 = pending)
474
 *                Bit    0 : IRQ pending (0 = pending)
475
 *
476
 * Exciting, huh?
477
 *
478
 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.