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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [mac53c94.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
/*
2
 * SCSI low-level driver for the 53c94 SCSI bus adaptor found
3
 * on Power Macintosh computers, controlling the external SCSI chain.
4
 * We assume the 53c94 is connected to a DBDMA (descriptor-based DMA)
5
 * controller.
6
 *
7
 * Paul Mackerras, August 1996.
8
 * Copyright (C) 1996 Paul Mackerras.
9
 */
10
#include <linux/kernel.h>
11
#include <linux/delay.h>
12
#include <linux/types.h>
13
#include <linux/string.h>
14
#include <linux/slab.h>
15
#include <linux/blk.h>
16
#include <linux/proc_fs.h>
17
#include <linux/stat.h>
18
#include <linux/spinlock.h>
19
#include <asm/dbdma.h>
20
#include <asm/io.h>
21
#include <asm/pgtable.h>
22
#include <asm/prom.h>
23
#include <asm/system.h>
24
 
25
#include "scsi.h"
26
#include "hosts.h"
27
#include "mac53c94.h"
28
 
29
enum fsc_phase {
30
        idle,
31
        selecting,
32
        dataing,
33
        completing,
34
        busfreeing,
35
};
36
 
37
struct fsc_state {
38
        volatile struct mac53c94_regs *regs;
39
        int     intr;
40
        volatile struct dbdma_regs *dma;
41
        int     dmaintr;
42
        int     clk_freq;
43
        struct  Scsi_Host *host;
44
        struct  fsc_state *next;
45
        Scsi_Cmnd *request_q;
46
        Scsi_Cmnd *request_qtail;
47
        Scsi_Cmnd *current_req;         /* req we're currently working on */
48
        enum fsc_phase phase;           /* what we're currently trying to do */
49
        struct dbdma_cmd *dma_cmds;     /* space for dbdma commands, aligned */
50
        void    *dma_cmd_space;
51
};
52
 
53
static struct fsc_state *all_53c94s;
54
 
55
static void mac53c94_init(struct fsc_state *);
56
static void mac53c94_start(struct fsc_state *);
57
static void mac53c94_interrupt(int, void *, struct pt_regs *);
58
static void do_mac53c94_interrupt(int, void *, struct pt_regs *);
59
static void cmd_done(struct fsc_state *, int result);
60
static void set_dma_cmds(struct fsc_state *, Scsi_Cmnd *);
61
static int data_goes_out(Scsi_Cmnd *);
62
 
63
int
64
mac53c94_detect(Scsi_Host_Template *tp)
65
{
66
        struct device_node *node;
67
        int nfscs;
68
        struct fsc_state *state, **prev_statep;
69
        struct Scsi_Host *host;
70
        void *dma_cmd_space;
71
        unsigned char *clkprop;
72
        int proplen;
73
 
74
        nfscs = 0;
75
        prev_statep = &all_53c94s;
76
        for (node = find_devices("53c94"); node != 0; node = node->next) {
77
                if (node->n_addrs != 2 || node->n_intrs != 2)
78
                        panic("53c94: expected 2 addrs and intrs (got %d/%d)",
79
                              node->n_addrs, node->n_intrs);
80
                host = scsi_register(tp, sizeof(struct fsc_state));
81
                if (host == NULL)
82
                        break;
83
                host->unique_id = nfscs;
84
#ifndef MODULE
85
                note_scsi_host(node, host);
86
#endif
87
 
88
                state = (struct fsc_state *) host->hostdata;
89
                if (state == 0)
90
                        panic("no 53c94 state");
91
                state->host = host;
92
                state->regs = (volatile struct mac53c94_regs *)
93
                        ioremap(node->addrs[0].address, 0x1000);
94
                state->intr = node->intrs[0].line;
95
                state->dma = (volatile struct dbdma_regs *)
96
                        ioremap(node->addrs[1].address, 0x1000);
97
                state->dmaintr = node->intrs[1].line;
98
 
99
                clkprop = get_property(node, "clock-frequency", &proplen);
100
                if (clkprop == NULL || proplen != sizeof(int)) {
101
                        printk(KERN_ERR "%s: can't get clock frequency\n",
102
                               node->full_name);
103
                        state->clk_freq = 25000000;
104
                } else
105
                        state->clk_freq = *(int *)clkprop;
106
 
107
                /* Space for dma command list: +1 for stop command,
108
                   +1 to allow for aligning. */
109
                dma_cmd_space = kmalloc((host->sg_tablesize + 2) *
110
                                        sizeof(struct dbdma_cmd), GFP_KERNEL);
111
                if (dma_cmd_space == 0)
112
                        panic("53c94: couldn't allocate dma command space");
113
                state->dma_cmds = (struct dbdma_cmd *)
114
                        DBDMA_ALIGN(dma_cmd_space);
115
                memset(state->dma_cmds, 0, (host->sg_tablesize + 1)
116
                       * sizeof(struct dbdma_cmd));
117
                state->dma_cmd_space = dma_cmd_space;
118
 
119
                *prev_statep = state;
120
                prev_statep = &state->next;
121
 
122
                if (request_irq(state->intr, do_mac53c94_interrupt, 0,
123
                                "53C94", state)) {
124
                        printk(KERN_ERR "mac53C94: can't get irq %d\n", state->intr);
125
                }
126
 
127
                mac53c94_init(state);
128
 
129
                ++nfscs;
130
        }
131
        return nfscs;
132
}
133
 
134
int
135
mac53c94_release(struct Scsi_Host *host)
136
{
137
        struct fsc_state *fp = (struct fsc_state *) host->hostdata;
138
 
139
        if (fp == 0)
140
                return 0;
141
        if (fp->regs)
142
                iounmap((void *) fp->regs);
143
        if (fp->dma)
144
                iounmap((void *) fp->dma);
145
        kfree(fp->dma_cmd_space);
146
        free_irq(fp->intr, fp);
147
        return 0;
148
}
149
 
150
int
151
mac53c94_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
152
{
153
        unsigned long flags;
154
        struct fsc_state *state;
155
 
156
#if 0
157
        if (data_goes_out(cmd)) {
158
                int i;
159
                printk(KERN_DEBUG "mac53c94_queue %p: command is", cmd);
160
                for (i = 0; i < cmd->cmd_len; ++i)
161
                        printk(" %.2x", cmd->cmnd[i]);
162
                printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
163
                       cmd->use_sg, cmd->request_bufflen, cmd->request_buffer);
164
        }
165
#endif
166
 
167
        cmd->scsi_done = done;
168
        cmd->host_scribble = NULL;
169
 
170
        state = (struct fsc_state *) cmd->host->hostdata;
171
 
172
        save_flags(flags);
173
        cli();
174
        if (state->request_q == NULL)
175
                state->request_q = cmd;
176
        else
177
                state->request_qtail->host_scribble = (void *) cmd;
178
        state->request_qtail = cmd;
179
 
180
        if (state->phase == idle)
181
                mac53c94_start(state);
182
 
183
        restore_flags(flags);
184
        return 0;
185
}
186
 
187
int
188
mac53c94_abort(Scsi_Cmnd *cmd)
189
{
190
        return SCSI_ABORT_SNOOZE;
191
}
192
 
193
int
194
mac53c94_reset(Scsi_Cmnd *cmd, unsigned how)
195
{
196
        struct fsc_state *state = (struct fsc_state *) cmd->host->hostdata;
197
        volatile struct mac53c94_regs *regs = state->regs;
198
        volatile struct dbdma_regs *dma = state->dma;
199
        unsigned long flags;
200
 
201
        save_flags(flags);
202
        cli();
203
        st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
204
        regs->command = CMD_SCSI_RESET; /* assert RST */
205
        eieio();
206
        udelay(100);                    /* leave it on for a while (>= 25us) */
207
        regs->command = CMD_RESET;
208
        eieio();
209
        udelay(20);
210
        mac53c94_init(state);
211
        regs->command = CMD_NOP;
212
        eieio();
213
        restore_flags(flags);
214
        return SCSI_RESET_PENDING;
215
}
216
 
217
int
218
mac53c94_command(Scsi_Cmnd *cmd)
219
{
220
        printk(KERN_DEBUG "whoops... mac53c94_command called\n");
221
        return -1;
222
}
223
 
224
static void
225
mac53c94_init(struct fsc_state *state)
226
{
227
        volatile struct mac53c94_regs *regs = state->regs;
228
        volatile struct dbdma_regs *dma = state->dma;
229
        int x;
230
 
231
        regs->config1 = state->host->this_id | CF1_PAR_ENABLE;
232
        regs->sel_timeout = TIMO_VAL(250);      /* 250ms */
233
        regs->clk_factor = CLKF_VAL(state->clk_freq);
234
        regs->config2 = CF2_FEATURE_EN;
235
        regs->config3 = 0;
236
        regs->sync_period = 0;
237
        regs->sync_offset = 0;
238
        eieio();
239
        x = regs->interrupt;
240
        st_le32(&dma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
241
}
242
 
243
/*
244
 * Start the next command for a 53C94.
245
 * Should be called with interrupts disabled.
246
 */
247
static void
248
mac53c94_start(struct fsc_state *state)
249
{
250
        Scsi_Cmnd *cmd;
251
        volatile struct mac53c94_regs *regs = state->regs;
252
        int i;
253
 
254
        if (state->phase != idle || state->current_req != NULL)
255
                panic("inappropriate mac53c94_start (state=%p)", state);
256
        if (state->request_q == NULL)
257
                return;
258
        state->current_req = cmd = state->request_q;
259
        state->request_q = (Scsi_Cmnd *) cmd->host_scribble;
260
 
261
        /* Off we go */
262
        regs->count_lo = 0;
263
        regs->count_mid = 0;
264
        regs->count_hi = 0;
265
        eieio();
266
        regs->command = CMD_NOP + CMD_DMA_MODE;
267
        udelay(1);
268
        eieio();
269
        regs->command = CMD_FLUSH;
270
        udelay(1);
271
        eieio();
272
        regs->dest_id = cmd->target;
273
        regs->sync_period = 0;
274
        regs->sync_offset = 0;
275
        eieio();
276
 
277
        /* load the command into the FIFO */
278
        for (i = 0; i < cmd->cmd_len; ++i) {
279
                regs->fifo = cmd->cmnd[i];
280
                eieio();
281
        }
282
 
283
        /* do select without ATN XXX */
284
        regs->command = CMD_SELECT;
285
        state->phase = selecting;
286
 
287
        if (cmd->use_sg > 0 || cmd->request_bufflen != 0)
288
                set_dma_cmds(state, cmd);
289
}
290
 
291
static void
292
do_mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
293
{
294
        unsigned long flags;
295
 
296
        spin_lock_irqsave(&io_request_lock, flags);
297
        mac53c94_interrupt(irq, dev_id, ptregs);
298
        spin_unlock_irqrestore(&io_request_lock, flags);
299
}
300
 
301
static void
302
mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
303
{
304
        struct fsc_state *state = (struct fsc_state *) dev_id;
305
        volatile struct mac53c94_regs *regs = state->regs;
306
        volatile struct dbdma_regs *dma = state->dma;
307
        Scsi_Cmnd *cmd = state->current_req;
308
        int nb, stat, seq, intr;
309
        static int mac53c94_errors;
310
 
311
        /*
312
         * Apparently, reading the interrupt register unlatches
313
         * the status and sequence step registers.
314
         */
315
        seq = regs->seqstep;
316
        stat = regs->status;
317
        intr = regs->interrupt;
318
 
319
#if 0
320
        printk(KERN_DEBUG "mac53c94_intr, intr=%x stat=%x seq=%x phase=%d\n",
321
               intr, stat, seq, state->phase);
322
#endif
323
 
324
        if (intr & INTR_RESET) {
325
                /* SCSI bus was reset */
326
                printk(KERN_INFO "external SCSI bus reset detected\n");
327
                regs->command = CMD_NOP;
328
                st_le32(&dma->control, RUN << 16);      /* stop dma */
329
                cmd_done(state, DID_RESET << 16);
330
                return;
331
        }
332
        if (intr & INTR_ILL_CMD) {
333
                printk(KERN_ERR "53c94: illegal cmd, intr=%x stat=%x seq=%x phase=%d\n",
334
                       intr, stat, seq, state->phase);
335
                cmd_done(state, DID_ERROR << 16);
336
                return;
337
        }
338
        if (stat & STAT_ERROR) {
339
#if 0
340
                /* XXX these seem to be harmless? */
341
                printk("53c94: bad error, intr=%x stat=%x seq=%x phase=%d\n",
342
                       intr, stat, seq, state->phase);
343
#endif
344
                ++mac53c94_errors;
345
                regs->command = CMD_NOP + CMD_DMA_MODE;
346
                eieio();
347
        }
348
        if (cmd == 0) {
349
                printk(KERN_DEBUG "53c94: interrupt with no command active?\n");
350
                return;
351
        }
352
        if (stat & STAT_PARITY) {
353
                printk(KERN_ERR "mac53c94: parity error\n");
354
                cmd_done(state, DID_PARITY << 16);
355
                return;
356
        }
357
        switch (state->phase) {
358
        case selecting:
359
                if (intr & INTR_DISCONNECT) {
360
                        /* selection timed out */
361
                        cmd_done(state, DID_BAD_TARGET << 16);
362
                        return;
363
                }
364
                if (intr != INTR_BUS_SERV + INTR_DONE) {
365
                        printk(KERN_DEBUG "got intr %x during selection\n", intr);
366
                        cmd_done(state, DID_ERROR << 16);
367
                        return;
368
                }
369
                if ((seq & SS_MASK) != SS_DONE) {
370
                        printk(KERN_DEBUG "seq step %x after command\n", seq);
371
                        cmd_done(state, DID_ERROR << 16);
372
                        return;
373
                }
374
                regs->command = CMD_NOP;
375
                /* set DMA controller going if any data to transfer */
376
                if ((stat & (STAT_MSG|STAT_CD)) == 0
377
                    && (cmd->use_sg > 0 || cmd->request_bufflen != 0)) {
378
                        nb = cmd->SCp.this_residual;
379
                        if (nb > 0xfff0)
380
                                nb = 0xfff0;
381
                        cmd->SCp.this_residual -= nb;
382
                        regs->count_lo = nb;
383
                        regs->count_mid = nb >> 8;
384
                        eieio();
385
                        regs->command = CMD_DMA_MODE + CMD_NOP;
386
                        eieio();
387
                        st_le32(&dma->cmdptr, virt_to_phys(state->dma_cmds));
388
                        st_le32(&dma->control, (RUN << 16) | RUN);
389
                        eieio();
390
                        regs->command = CMD_DMA_MODE + CMD_XFER_DATA;
391
                        state->phase = dataing;
392
                        break;
393
                } else if ((stat & STAT_PHASE) == STAT_CD + STAT_IO) {
394
                        /* up to status phase already */
395
                        regs->command = CMD_I_COMPLETE;
396
                        state->phase = completing;
397
                } else {
398
                        printk(KERN_DEBUG "in unexpected phase %x after cmd\n",
399
                               stat & STAT_PHASE);
400
                        cmd_done(state, DID_ERROR << 16);
401
                        return;
402
                }
403
                break;
404
 
405
        case dataing:
406
                if (intr != INTR_BUS_SERV) {
407
                        printk(KERN_DEBUG "got intr %x before status\n", intr);
408
                        cmd_done(state, DID_ERROR << 16);
409
                        return;
410
                }
411
                if (cmd->SCp.this_residual != 0
412
                    && (stat & (STAT_MSG|STAT_CD)) == 0) {
413
                        /* Set up the count regs to transfer more */
414
                        nb = cmd->SCp.this_residual;
415
                        if (nb > 0xfff0)
416
                                nb = 0xfff0;
417
                        cmd->SCp.this_residual -= nb;
418
                        regs->count_lo = nb;
419
                        regs->count_mid = nb >> 8;
420
                        eieio();
421
                        regs->command = CMD_DMA_MODE + CMD_NOP;
422
                        eieio();
423
                        regs->command = CMD_DMA_MODE + CMD_XFER_DATA;
424
                        break;
425
                }
426
                if ((stat & STAT_PHASE) != STAT_CD + STAT_IO) {
427
                        printk(KERN_DEBUG "intr %x before data xfer complete\n", intr);
428
                }
429
                st_le32(&dma->control, RUN << 16);      /* stop dma */
430
                /* should check dma status */
431
                regs->command = CMD_I_COMPLETE;
432
                state->phase = completing;
433
                break;
434
        case completing:
435
                if (intr != INTR_DONE) {
436
                        printk(KERN_DEBUG "got intr %x on completion\n", intr);
437
                        cmd_done(state, DID_ERROR << 16);
438
                        return;
439
                }
440
                cmd->SCp.Status = regs->fifo; eieio();
441
                cmd->SCp.Message = regs->fifo; eieio();
442
                cmd->result =
443
                regs->command = CMD_ACCEPT_MSG;
444
                state->phase = busfreeing;
445
                break;
446
        case busfreeing:
447
                if (intr != INTR_DISCONNECT) {
448
                        printk(KERN_DEBUG "got intr %x when expected disconnect\n", intr);
449
                }
450
                cmd_done(state, (DID_OK << 16) + (cmd->SCp.Message << 8)
451
                         + cmd->SCp.Status);
452
                break;
453
        default:
454
                printk(KERN_DEBUG "don't know about phase %d\n", state->phase);
455
        }
456
}
457
 
458
static void
459
cmd_done(struct fsc_state *state, int result)
460
{
461
        Scsi_Cmnd *cmd;
462
 
463
        cmd = state->current_req;
464
        if (cmd != 0) {
465
                cmd->result = result;
466
                (*cmd->scsi_done)(cmd);
467
                state->current_req = NULL;
468
        }
469
        state->phase = idle;
470
        mac53c94_start(state);
471
}
472
 
473
/*
474
 * Set up DMA commands for transferring data.
475
 */
476
static void
477
set_dma_cmds(struct fsc_state *state, Scsi_Cmnd *cmd)
478
{
479
        int i, dma_cmd, total;
480
        struct scatterlist *scl;
481
        struct dbdma_cmd *dcmds;
482
 
483
        dma_cmd = data_goes_out(cmd)? OUTPUT_MORE: INPUT_MORE;
484
        dcmds = state->dma_cmds;
485
        if (cmd->use_sg > 0) {
486
                total = 0;
487
                scl = (struct scatterlist *) cmd->buffer;
488
                for (i = 0; i < cmd->use_sg; ++i) {
489
                        if (scl->length > 0xffff)
490
                                panic("mac53c94: scatterlist element >= 64k");
491
                        total += scl->length;
492
                        st_le16(&dcmds->req_count, scl->length);
493
                        st_le16(&dcmds->command, dma_cmd);
494
                        st_le32(&dcmds->phy_addr, virt_to_phys(scl->address));
495
                        dcmds->xfer_status = 0;
496
                        ++scl;
497
                        ++dcmds;
498
                }
499
        } else {
500
                total = cmd->request_bufflen;
501
                if (total > 0xffff)
502
                        panic("mac53c94: transfer size >= 64k");
503
                st_le16(&dcmds->req_count, total);
504
                st_le32(&dcmds->phy_addr, virt_to_phys(cmd->request_buffer));
505
                dcmds->xfer_status = 0;
506
                ++dcmds;
507
        }
508
        dma_cmd += OUTPUT_LAST - OUTPUT_MORE;
509
        st_le16(&dcmds[-1].command, dma_cmd);
510
        st_le16(&dcmds->command, DBDMA_STOP);
511
        cmd->SCp.this_residual = total;
512
}
513
 
514
/*
515
 * Work out whether data will be going out from the host adaptor or into it.
516
 * (If this information is available from somewhere else in the scsi
517
 * code, somebody please let me know :-)
518
 */
519
static int
520
data_goes_out(Scsi_Cmnd *cmd)
521
{
522
        switch (cmd->cmnd[0]) {
523
        case CHANGE_DEFINITION:
524
        case COMPARE:
525
        case COPY:
526
        case COPY_VERIFY:
527
        case FORMAT_UNIT:
528
        case LOG_SELECT:
529
        case MEDIUM_SCAN:
530
        case MODE_SELECT:
531
        case MODE_SELECT_10:
532
        case REASSIGN_BLOCKS:
533
        case RESERVE:
534
        case SEARCH_EQUAL:
535
        case SEARCH_EQUAL_12:
536
        case SEARCH_HIGH:
537
        case SEARCH_HIGH_12:
538
        case SEARCH_LOW:
539
        case SEARCH_LOW_12:
540
        case SEND_DIAGNOSTIC:
541
        case SEND_VOLUME_TAG:
542
        case SET_WINDOW:
543
        case UPDATE_BLOCK:
544
        case WRITE_BUFFER:
545
        case WRITE_6:
546
        case WRITE_10:
547
        case WRITE_12:
548
        case WRITE_LONG:
549
        case WRITE_LONG_2:      /* alternate code for WRITE_LONG */
550
        case WRITE_SAME:
551
        case WRITE_VERIFY:
552
        case WRITE_VERIFY_12:
553
                return 1;
554
        default:
555
                return 0;
556
        }
557
}
558
 
559
static Scsi_Host_Template driver_template = SCSI_MAC53C94;
560
 
561
#include "scsi_module.c"

powered by: WebSVN 2.1.0

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