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)
7 * Paul Mackerras, August 1996.
8 * Copyright (C) 1996 Paul Mackerras.
10 #include <linux/kernel.h>
11 #include <linux/delay.h>
12 #include <linux/types.h>
13 #include <linux/string.h>
14 #include <linux/malloc.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>
21 #include <asm/pgtable.h>
23 #include <asm/system.h>
29 struct proc_dir_entry proc_scsi_mac53c94
= {
30 PROC_SCSI_53C94
, 5, "53c94",
31 S_IFDIR
| S_IRUGO
| S_IXUGO
, 2
43 volatile struct mac53c94_regs
*regs
;
45 volatile struct dbdma_regs
*dma
;
48 struct Scsi_Host
*host
;
49 struct fsc_state
*next
;
51 Scsi_Cmnd
*request_qtail
;
52 Scsi_Cmnd
*current_req
; /* req we're currently working on */
53 enum fsc_phase phase
; /* what we're currently trying to do */
54 struct dbdma_cmd
*dma_cmds
; /* space for dbdma commands, aligned */
57 static struct fsc_state
*all_53c94s
;
59 static void mac53c94_init(struct fsc_state
*);
60 static void mac53c94_start(struct fsc_state
*);
61 static void mac53c94_interrupt(int, void *, struct pt_regs
*);
62 static void do_mac53c94_interrupt(int, void *, struct pt_regs
*);
63 static void cmd_done(struct fsc_state
*, int result
);
64 static void set_dma_cmds(struct fsc_state
*, Scsi_Cmnd
*);
65 static int data_goes_out(Scsi_Cmnd
*);
68 mac53c94_detect(Scsi_Host_Template
*tp
)
70 struct device_node
*node
;
72 struct fsc_state
*state
, **prev_statep
;
73 struct Scsi_Host
*host
;
75 unsigned char *clkprop
;
79 prev_statep
= &all_53c94s
;
80 for (node
= find_devices("53c94"); node
!= 0; node
= node
->next
) {
81 if (node
->n_addrs
!= 2 || node
->n_intrs
!= 2)
82 panic("53c94: expected 2 addrs and intrs (got %d/%d)",
83 node
->n_addrs
, node
->n_intrs
);
84 host
= scsi_register(tp
, sizeof(struct fsc_state
));
86 panic("couldn't register 53c94 host");
87 host
->unique_id
= nfscs
;
88 note_scsi_host(node
, host
);
90 state
= (struct fsc_state
*) host
->hostdata
;
92 panic("no 53c94 state");
94 state
->regs
= (volatile struct mac53c94_regs
*)
95 ioremap(node
->addrs
[0].address
, 0x1000);
96 state
->intr
= node
->intrs
[0].line
;
97 state
->dma
= (volatile struct dbdma_regs
*)
98 ioremap(node
->addrs
[1].address
, 0x1000);
99 state
->dmaintr
= node
->intrs
[1].line
;
101 clkprop
= get_property(node
, "clock-frequency", &proplen
);
102 if (clkprop
== NULL
|| proplen
!= sizeof(int)) {
103 printk(KERN_ERR
"%s: can't get clock frequency\n",
105 state
->clk_freq
= 25000000;
107 state
->clk_freq
= *(int *)clkprop
;
109 /* Space for dma command list: +1 for stop command,
110 +1 to allow for aligning. */
111 dma_cmd_space
= kmalloc((host
->sg_tablesize
+ 2) *
112 sizeof(struct dbdma_cmd
), GFP_KERNEL
);
113 if (dma_cmd_space
== 0)
114 panic("53c94: couldn't allocate dma command space");
115 state
->dma_cmds
= (struct dbdma_cmd
*)
116 DBDMA_ALIGN(dma_cmd_space
);
117 memset(state
->dma_cmds
, 0, (host
->sg_tablesize
+ 1)
118 * sizeof(struct dbdma_cmd
));
120 *prev_statep
= state
;
121 prev_statep
= &state
->next
;
123 if (request_irq(state
->intr
, do_mac53c94_interrupt
, 0,
125 printk(KERN_ERR
"mac53C94: can't get irq %d\n", state
->intr
);
128 mac53c94_init(state
);
136 mac53c94_queue(Scsi_Cmnd
*cmd
, void (*done
)(Scsi_Cmnd
*))
139 struct fsc_state
*state
;
142 if (data_goes_out(cmd
)) {
144 printk(KERN_DEBUG
"mac53c94_queue %p: command is", cmd
);
145 for (i
= 0; i
< cmd
->cmd_len
; ++i
)
146 printk(" %.2x", cmd
->cmnd
[i
]);
147 printk("\n" KERN_DEBUG
"use_sg=%d request_bufflen=%d request_buffer=%p\n",
148 cmd
->use_sg
, cmd
->request_bufflen
, cmd
->request_buffer
);
152 cmd
->scsi_done
= done
;
153 cmd
->host_scribble
= NULL
;
155 state
= (struct fsc_state
*) cmd
->host
->hostdata
;
159 if (state
->request_q
== NULL
)
160 state
->request_q
= cmd
;
162 state
->request_qtail
->host_scribble
= (void *) cmd
;
163 state
->request_qtail
= cmd
;
165 if (state
->phase
== idle
)
166 mac53c94_start(state
);
168 restore_flags(flags
);
173 mac53c94_abort(Scsi_Cmnd
*cmd
)
175 return SCSI_ABORT_SNOOZE
;
179 mac53c94_reset(Scsi_Cmnd
*cmd
, unsigned how
)
181 struct fsc_state
*state
= (struct fsc_state
*) cmd
->host
->hostdata
;
182 volatile struct mac53c94_regs
*regs
= state
->regs
;
183 volatile struct dbdma_regs
*dma
= state
->dma
;
188 st_le32(&dma
->control
, (RUN
|PAUSE
|FLUSH
|WAKE
) << 16);
189 regs
->command
= CMD_SCSI_RESET
; /* assert RST */
191 udelay(100); /* leave it on for a while (>= 25us) */
192 regs
->command
= CMD_RESET
;
195 mac53c94_init(state
);
196 regs
->command
= CMD_NOP
;
198 restore_flags(flags
);
199 return SCSI_RESET_PENDING
;
203 mac53c94_command(Scsi_Cmnd
*cmd
)
205 printk(KERN_DEBUG
"whoops... mac53c94_command called\n");
210 mac53c94_init(struct fsc_state
*state
)
212 volatile struct mac53c94_regs
*regs
= state
->regs
;
213 volatile struct dbdma_regs
*dma
= state
->dma
;
216 regs
->config1
= state
->host
->this_id
| CF1_PAR_ENABLE
;
217 regs
->sel_timeout
= TIMO_VAL(250); /* 250ms */
218 regs
->clk_factor
= CLKF_VAL(state
->clk_freq
);
219 regs
->config2
= CF2_FEATURE_EN
;
221 regs
->sync_period
= 0;
222 regs
->sync_offset
= 0;
225 st_le32(&dma
->control
, (RUN
|PAUSE
|FLUSH
|WAKE
) << 16);
229 * Start the next command for a 53C94.
230 * Should be called with interrupts disabled.
233 mac53c94_start(struct fsc_state
*state
)
236 volatile struct mac53c94_regs
*regs
= state
->regs
;
239 if (state
->phase
!= idle
|| state
->current_req
!= NULL
)
240 panic("inappropriate mac53c94_start (state=%p)", state
);
241 if (state
->request_q
== NULL
)
243 state
->current_req
= cmd
= state
->request_q
;
244 state
->request_q
= (Scsi_Cmnd
*) cmd
->host_scribble
;
251 regs
->command
= CMD_NOP
+ CMD_DMA_MODE
;
254 regs
->command
= CMD_FLUSH
;
257 regs
->dest_id
= cmd
->target
;
258 regs
->sync_period
= 0;
259 regs
->sync_offset
= 0;
262 /* load the command into the FIFO */
263 for (i
= 0; i
< cmd
->cmd_len
; ++i
) {
264 regs
->fifo
= cmd
->cmnd
[i
];
268 /* do select without ATN XXX */
269 regs
->command
= CMD_SELECT
;
270 state
->phase
= selecting
;
272 if (cmd
->use_sg
> 0 || cmd
->request_bufflen
!= 0)
273 set_dma_cmds(state
, cmd
);
277 do_mac53c94_interrupt(int irq
, void *dev_id
, struct pt_regs
*ptregs
)
281 spin_lock_irqsave(&io_request_lock
, flags
);
282 mac53c94_interrupt(irq
, dev_id
, ptregs
);
283 spin_unlock_irqrestore(&io_request_lock
, flags
);
287 mac53c94_interrupt(int irq
, void *dev_id
, struct pt_regs
*ptregs
)
289 struct fsc_state
*state
= (struct fsc_state
*) dev_id
;
290 volatile struct mac53c94_regs
*regs
= state
->regs
;
291 volatile struct dbdma_regs
*dma
= state
->dma
;
292 Scsi_Cmnd
*cmd
= state
->current_req
;
293 int nb
, stat
, seq
, intr
;
294 static int mac53c94_errors
;
297 * Apparently, reading the interrupt register unlatches
298 * the status and sequence step registers.
302 intr
= regs
->interrupt
;
305 printk(KERN_DEBUG
"mac53c94_intr, intr=%x stat=%x seq=%x phase=%d\n",
306 intr
, stat
, seq
, state
->phase
);
309 if (intr
& INTR_RESET
) {
310 /* SCSI bus was reset */
311 printk(KERN_INFO
"external SCSI bus reset detected\n");
312 regs
->command
= CMD_NOP
;
313 st_le32(&dma
->control
, RUN
<< 16); /* stop dma */
314 cmd_done(state
, DID_RESET
<< 16);
317 if (intr
& INTR_ILL_CMD
) {
318 printk(KERN_ERR
"53c94: illegal cmd, intr=%x stat=%x seq=%x phase=%d\n",
319 intr
, stat
, seq
, state
->phase
);
320 cmd_done(state
, DID_ERROR
<< 16);
323 if (stat
& STAT_ERROR
) {
325 /* XXX these seem to be harmless? */
326 printk("53c94: bad error, intr=%x stat=%x seq=%x phase=%d\n",
327 intr
, stat
, seq
, state
->phase
);
330 regs
->command
= CMD_NOP
+ CMD_DMA_MODE
;
334 printk(KERN_DEBUG
"53c94: interrupt with no command active?\n");
337 if (stat
& STAT_PARITY
) {
338 printk(KERN_ERR
"mac53c94: parity error\n");
339 cmd_done(state
, DID_PARITY
<< 16);
342 switch (state
->phase
) {
344 if (intr
& INTR_DISCONNECT
) {
345 /* selection timed out */
346 cmd_done(state
, DID_BAD_TARGET
<< 16);
349 if (intr
!= INTR_BUS_SERV
+ INTR_DONE
) {
350 printk(KERN_DEBUG
"got intr %x during selection\n", intr
);
351 cmd_done(state
, DID_ERROR
<< 16);
354 if ((seq
& SS_MASK
) != SS_DONE
) {
355 printk(KERN_DEBUG
"seq step %x after command\n", seq
);
356 cmd_done(state
, DID_ERROR
<< 16);
359 regs
->command
= CMD_NOP
;
360 /* set DMA controller going if any data to transfer */
361 if ((stat
& (STAT_MSG
|STAT_CD
)) == 0
362 && (cmd
->use_sg
> 0 || cmd
->request_bufflen
!= 0)) {
363 nb
= cmd
->SCp
.this_residual
;
366 cmd
->SCp
.this_residual
-= nb
;
368 regs
->count_mid
= nb
>> 8;
370 regs
->command
= CMD_DMA_MODE
+ CMD_NOP
;
372 st_le32(&dma
->cmdptr
, virt_to_phys(state
->dma_cmds
));
373 st_le32(&dma
->control
, (RUN
<< 16) | RUN
);
375 regs
->command
= CMD_DMA_MODE
+ CMD_XFER_DATA
;
376 state
->phase
= dataing
;
378 } else if ((stat
& STAT_PHASE
) == STAT_CD
+ STAT_IO
) {
379 /* up to status phase already */
380 regs
->command
= CMD_I_COMPLETE
;
381 state
->phase
= completing
;
383 printk(KERN_DEBUG
"in unexpected phase %x after cmd\n",
385 cmd_done(state
, DID_ERROR
<< 16);
391 if (intr
!= INTR_BUS_SERV
) {
392 printk(KERN_DEBUG
"got intr %x before status\n", intr
);
393 cmd_done(state
, DID_ERROR
<< 16);
396 if (cmd
->SCp
.this_residual
!= 0
397 && (stat
& (STAT_MSG
|STAT_CD
)) == 0) {
398 /* Set up the count regs to transfer more */
399 nb
= cmd
->SCp
.this_residual
;
402 cmd
->SCp
.this_residual
-= nb
;
404 regs
->count_mid
= nb
>> 8;
406 regs
->command
= CMD_DMA_MODE
+ CMD_NOP
;
408 regs
->command
= CMD_DMA_MODE
+ CMD_XFER_DATA
;
411 if ((stat
& STAT_PHASE
) != STAT_CD
+ STAT_IO
) {
412 printk(KERN_DEBUG
"intr %x before data xfer complete\n", intr
);
414 st_le32(&dma
->control
, RUN
<< 16); /* stop dma */
415 /* should check dma status */
416 regs
->command
= CMD_I_COMPLETE
;
417 state
->phase
= completing
;
420 if (intr
!= INTR_DONE
) {
421 printk(KERN_DEBUG
"got intr %x on completion\n", intr
);
422 cmd_done(state
, DID_ERROR
<< 16);
425 cmd
->SCp
.Status
= regs
->fifo
; eieio();
426 cmd
->SCp
.Message
= regs
->fifo
; eieio();
428 regs
->command
= CMD_ACCEPT_MSG
;
429 state
->phase
= busfreeing
;
432 if (intr
!= INTR_DISCONNECT
) {
433 printk(KERN_DEBUG
"got intr %x when expected disconnect\n", intr
);
435 cmd_done(state
, (DID_OK
<< 16) + (cmd
->SCp
.Message
<< 8)
439 printk(KERN_DEBUG
"don't know about phase %d\n", state
->phase
);
444 cmd_done(struct fsc_state
*state
, int result
)
448 cmd
= state
->current_req
;
450 cmd
->result
= result
;
451 (*cmd
->scsi_done
)(cmd
);
452 state
->current_req
= NULL
;
455 mac53c94_start(state
);
459 * Set up DMA commands for transferring data.
462 set_dma_cmds(struct fsc_state
*state
, Scsi_Cmnd
*cmd
)
464 int i
, dma_cmd
, total
;
465 struct scatterlist
*scl
;
466 struct dbdma_cmd
*dcmds
;
468 dma_cmd
= data_goes_out(cmd
)? OUTPUT_MORE
: INPUT_MORE
;
469 dcmds
= state
->dma_cmds
;
470 if (cmd
->use_sg
> 0) {
472 scl
= (struct scatterlist
*) cmd
->buffer
;
473 for (i
= 0; i
< cmd
->use_sg
; ++i
) {
474 if (scl
->length
> 0xffff)
475 panic("mac53c94: scatterlist element >= 64k");
476 total
+= scl
->length
;
477 st_le16(&dcmds
->req_count
, scl
->length
);
478 st_le16(&dcmds
->command
, dma_cmd
);
479 st_le32(&dcmds
->phy_addr
, virt_to_phys(scl
->address
));
480 dcmds
->xfer_status
= 0;
485 total
= cmd
->request_bufflen
;
487 panic("mac53c94: transfer size >= 64k");
488 st_le16(&dcmds
->req_count
, total
);
489 st_le32(&dcmds
->phy_addr
, virt_to_phys(cmd
->request_buffer
));
490 dcmds
->xfer_status
= 0;
493 dma_cmd
+= OUTPUT_LAST
- OUTPUT_MORE
;
494 st_le16(&dcmds
[-1].command
, dma_cmd
);
495 st_le16(&dcmds
->command
, DBDMA_STOP
);
496 cmd
->SCp
.this_residual
= total
;
500 * Work out whether data will be going out from the host adaptor or into it.
501 * (If this information is available from somewhere else in the scsi
502 * code, somebody please let me know :-)
505 data_goes_out(Scsi_Cmnd
*cmd
)
507 switch (cmd
->cmnd
[0]) {
508 case CHANGE_DEFINITION
:
517 case REASSIGN_BLOCKS
:
520 case SEARCH_EQUAL_12
:
525 case SEND_DIAGNOSTIC
:
526 case SEND_VOLUME_TAG
:
534 case WRITE_LONG_2
: /* alternate code for WRITE_LONG */
537 case WRITE_VERIFY_12
: