• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/scsi/
1/*
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/blkdev.h>
16#include <linux/proc_fs.h>
17#include <linux/stat.h>
18#include <linux/spinlock.h>
19#include <linux/interrupt.h>
20#include <asm/dbdma.h>
21#include <asm/io.h>
22#include <asm/pgtable.h>
23#include <asm/prom.h>
24#include <asm/system.h>
25#include <asm/pci-bridge.h>
26#include <asm/macio.h>
27
28#include <scsi/scsi.h>
29#include <scsi/scsi_cmnd.h>
30#include <scsi/scsi_device.h>
31#include <scsi/scsi_host.h>
32
33#include "mac53c94.h"
34
35enum fsc_phase {
36	idle,
37	selecting,
38	dataing,
39	completing,
40	busfreeing,
41};
42
43struct fsc_state {
44	struct	mac53c94_regs __iomem *regs;
45	int	intr;
46	struct	dbdma_regs __iomem *dma;
47	int	dmaintr;
48	int	clk_freq;
49	struct	Scsi_Host *host;
50	struct scsi_cmnd *request_q;
51	struct scsi_cmnd *request_qtail;
52	struct 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 */
55	void	*dma_cmd_space;
56	struct	pci_dev *pdev;
57	dma_addr_t dma_addr;
58	struct macio_dev *mdev;
59};
60
61static void mac53c94_init(struct fsc_state *);
62static void mac53c94_start(struct fsc_state *);
63static void mac53c94_interrupt(int, void *);
64static irqreturn_t do_mac53c94_interrupt(int, void *);
65static void cmd_done(struct fsc_state *, int result);
66static void set_dma_cmds(struct fsc_state *, struct scsi_cmnd *);
67
68
69static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
70{
71	struct fsc_state *state;
72
73
74	cmd->scsi_done = done;
75	cmd->host_scribble = NULL;
76
77	state = (struct fsc_state *) cmd->device->host->hostdata;
78
79	if (state->request_q == NULL)
80		state->request_q = cmd;
81	else
82		state->request_qtail->host_scribble = (void *) cmd;
83	state->request_qtail = cmd;
84
85	if (state->phase == idle)
86		mac53c94_start(state);
87
88	return 0;
89}
90
91static int mac53c94_host_reset(struct scsi_cmnd *cmd)
92{
93	struct fsc_state *state = (struct fsc_state *) cmd->device->host->hostdata;
94	struct mac53c94_regs __iomem *regs = state->regs;
95	struct dbdma_regs __iomem *dma = state->dma;
96	unsigned long flags;
97
98	spin_lock_irqsave(cmd->device->host->host_lock, flags);
99
100	writel((RUN|PAUSE|FLUSH|WAKE) << 16, &dma->control);
101	writeb(CMD_SCSI_RESET, &regs->command);	/* assert RST */
102	udelay(100);			/* leave it on for a while (>= 25us) */
103	writeb(CMD_RESET, &regs->command);
104	udelay(20);
105	mac53c94_init(state);
106	writeb(CMD_NOP, &regs->command);
107
108	spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
109	return SUCCESS;
110}
111
112static void mac53c94_init(struct fsc_state *state)
113{
114	struct mac53c94_regs __iomem *regs = state->regs;
115	struct dbdma_regs __iomem *dma = state->dma;
116	int x;
117
118	writeb(state->host->this_id | CF1_PAR_ENABLE, &regs->config1);
119	writeb(TIMO_VAL(250), &regs->sel_timeout);	/* 250ms */
120	writeb(CLKF_VAL(state->clk_freq), &regs->clk_factor);
121	writeb(CF2_FEATURE_EN, &regs->config2);
122	writeb(0, &regs->config3);
123	writeb(0, &regs->sync_period);
124	writeb(0, &regs->sync_offset);
125	x = readb(&regs->interrupt);
126	writel((RUN|PAUSE|FLUSH|WAKE) << 16, &dma->control);
127}
128
129/*
130 * Start the next command for a 53C94.
131 * Should be called with interrupts disabled.
132 */
133static void mac53c94_start(struct fsc_state *state)
134{
135	struct scsi_cmnd *cmd;
136	struct mac53c94_regs __iomem *regs = state->regs;
137	int i;
138
139	if (state->phase != idle || state->current_req != NULL)
140		panic("inappropriate mac53c94_start (state=%p)", state);
141	if (state->request_q == NULL)
142		return;
143	state->current_req = cmd = state->request_q;
144	state->request_q = (struct scsi_cmnd *) cmd->host_scribble;
145
146	/* Off we go */
147	writeb(0, &regs->count_lo);
148	writeb(0, &regs->count_mid);
149	writeb(0, &regs->count_hi);
150	writeb(CMD_NOP + CMD_DMA_MODE, &regs->command);
151	udelay(1);
152	writeb(CMD_FLUSH, &regs->command);
153	udelay(1);
154	writeb(cmd->device->id, &regs->dest_id);
155	writeb(0, &regs->sync_period);
156	writeb(0, &regs->sync_offset);
157
158	/* load the command into the FIFO */
159	for (i = 0; i < cmd->cmd_len; ++i)
160		writeb(cmd->cmnd[i], &regs->fifo);
161
162	writeb(CMD_SELECT, &regs->command);
163	state->phase = selecting;
164
165	set_dma_cmds(state, cmd);
166}
167
168static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id)
169{
170	unsigned long flags;
171	struct Scsi_Host *dev = ((struct fsc_state *) dev_id)->current_req->device->host;
172
173	spin_lock_irqsave(dev->host_lock, flags);
174	mac53c94_interrupt(irq, dev_id);
175	spin_unlock_irqrestore(dev->host_lock, flags);
176	return IRQ_HANDLED;
177}
178
179static void mac53c94_interrupt(int irq, void *dev_id)
180{
181	struct fsc_state *state = (struct fsc_state *) dev_id;
182	struct mac53c94_regs __iomem *regs = state->regs;
183	struct dbdma_regs __iomem *dma = state->dma;
184	struct scsi_cmnd *cmd = state->current_req;
185	int nb, stat, seq, intr;
186	static int mac53c94_errors;
187
188	/*
189	 * Apparently, reading the interrupt register unlatches
190	 * the status and sequence step registers.
191	 */
192	seq = readb(&regs->seqstep);
193	stat = readb(&regs->status);
194	intr = readb(&regs->interrupt);
195
196
197	if (intr & INTR_RESET) {
198		/* SCSI bus was reset */
199		printk(KERN_INFO "external SCSI bus reset detected\n");
200		writeb(CMD_NOP, &regs->command);
201		writel(RUN << 16, &dma->control);	/* stop dma */
202		cmd_done(state, DID_RESET << 16);
203		return;
204	}
205	if (intr & INTR_ILL_CMD) {
206		printk(KERN_ERR "53c94: invalid cmd, intr=%x stat=%x seq=%x phase=%d\n",
207		       intr, stat, seq, state->phase);
208		cmd_done(state, DID_ERROR << 16);
209		return;
210	}
211	if (stat & STAT_ERROR) {
212		++mac53c94_errors;
213		writeb(CMD_NOP + CMD_DMA_MODE, &regs->command);
214	}
215	if (cmd == 0) {
216		printk(KERN_DEBUG "53c94: interrupt with no command active?\n");
217		return;
218	}
219	if (stat & STAT_PARITY) {
220		printk(KERN_ERR "mac53c94: parity error\n");
221		cmd_done(state, DID_PARITY << 16);
222		return;
223	}
224	switch (state->phase) {
225	case selecting:
226		if (intr & INTR_DISCONNECT) {
227			/* selection timed out */
228			cmd_done(state, DID_BAD_TARGET << 16);
229			return;
230		}
231		if (intr != INTR_BUS_SERV + INTR_DONE) {
232			printk(KERN_DEBUG "got intr %x during selection\n", intr);
233			cmd_done(state, DID_ERROR << 16);
234			return;
235		}
236		if ((seq & SS_MASK) != SS_DONE) {
237			printk(KERN_DEBUG "seq step %x after command\n", seq);
238			cmd_done(state, DID_ERROR << 16);
239			return;
240		}
241		writeb(CMD_NOP, &regs->command);
242		/* set DMA controller going if any data to transfer */
243		if ((stat & (STAT_MSG|STAT_CD)) == 0
244		    && (scsi_sg_count(cmd) > 0 || scsi_bufflen(cmd))) {
245			nb = cmd->SCp.this_residual;
246			if (nb > 0xfff0)
247				nb = 0xfff0;
248			cmd->SCp.this_residual -= nb;
249			writeb(nb, &regs->count_lo);
250			writeb(nb >> 8, &regs->count_mid);
251			writeb(CMD_DMA_MODE + CMD_NOP, &regs->command);
252			writel(virt_to_phys(state->dma_cmds), &dma->cmdptr);
253			writel((RUN << 16) | RUN, &dma->control);
254			writeb(CMD_DMA_MODE + CMD_XFER_DATA, &regs->command);
255			state->phase = dataing;
256			break;
257		} else if ((stat & STAT_PHASE) == STAT_CD + STAT_IO) {
258			/* up to status phase already */
259			writeb(CMD_I_COMPLETE, &regs->command);
260			state->phase = completing;
261		} else {
262			printk(KERN_DEBUG "in unexpected phase %x after cmd\n",
263			       stat & STAT_PHASE);
264			cmd_done(state, DID_ERROR << 16);
265			return;
266		}
267		break;
268
269	case dataing:
270		if (intr != INTR_BUS_SERV) {
271			printk(KERN_DEBUG "got intr %x before status\n", intr);
272			cmd_done(state, DID_ERROR << 16);
273			return;
274		}
275		if (cmd->SCp.this_residual != 0
276		    && (stat & (STAT_MSG|STAT_CD)) == 0) {
277			/* Set up the count regs to transfer more */
278			nb = cmd->SCp.this_residual;
279			if (nb > 0xfff0)
280				nb = 0xfff0;
281			cmd->SCp.this_residual -= nb;
282			writeb(nb, &regs->count_lo);
283			writeb(nb >> 8, &regs->count_mid);
284			writeb(CMD_DMA_MODE + CMD_NOP, &regs->command);
285			writeb(CMD_DMA_MODE + CMD_XFER_DATA, &regs->command);
286			break;
287		}
288		if ((stat & STAT_PHASE) != STAT_CD + STAT_IO) {
289			printk(KERN_DEBUG "intr %x before data xfer complete\n", intr);
290		}
291		writel(RUN << 16, &dma->control);	/* stop dma */
292		scsi_dma_unmap(cmd);
293		/* should check dma status */
294		writeb(CMD_I_COMPLETE, &regs->command);
295		state->phase = completing;
296		break;
297	case completing:
298		if (intr != INTR_DONE) {
299			printk(KERN_DEBUG "got intr %x on completion\n", intr);
300			cmd_done(state, DID_ERROR << 16);
301			return;
302		}
303		cmd->SCp.Status = readb(&regs->fifo);
304		cmd->SCp.Message = readb(&regs->fifo);
305		cmd->result = CMD_ACCEPT_MSG;
306		writeb(CMD_ACCEPT_MSG, &regs->command);
307		state->phase = busfreeing;
308		break;
309	case busfreeing:
310		if (intr != INTR_DISCONNECT) {
311			printk(KERN_DEBUG "got intr %x when expected disconnect\n", intr);
312		}
313		cmd_done(state, (DID_OK << 16) + (cmd->SCp.Message << 8)
314			 + cmd->SCp.Status);
315		break;
316	default:
317		printk(KERN_DEBUG "don't know about phase %d\n", state->phase);
318	}
319}
320
321static void cmd_done(struct fsc_state *state, int result)
322{
323	struct scsi_cmnd *cmd;
324
325	cmd = state->current_req;
326	if (cmd != 0) {
327		cmd->result = result;
328		(*cmd->scsi_done)(cmd);
329		state->current_req = NULL;
330	}
331	state->phase = idle;
332	mac53c94_start(state);
333}
334
335/*
336 * Set up DMA commands for transferring data.
337 */
338static void set_dma_cmds(struct fsc_state *state, struct scsi_cmnd *cmd)
339{
340	int i, dma_cmd, total, nseg;
341	struct scatterlist *scl;
342	struct dbdma_cmd *dcmds;
343	dma_addr_t dma_addr;
344	u32 dma_len;
345
346	nseg = scsi_dma_map(cmd);
347	BUG_ON(nseg < 0);
348	if (!nseg)
349		return;
350
351	dma_cmd = cmd->sc_data_direction == DMA_TO_DEVICE ?
352			OUTPUT_MORE : INPUT_MORE;
353	dcmds = state->dma_cmds;
354	total = 0;
355
356	scsi_for_each_sg(cmd, scl, nseg, i) {
357		dma_addr = sg_dma_address(scl);
358		dma_len = sg_dma_len(scl);
359		if (dma_len > 0xffff)
360			panic("mac53c94: scatterlist element >= 64k");
361		total += dma_len;
362		st_le16(&dcmds->req_count, dma_len);
363		st_le16(&dcmds->command, dma_cmd);
364		st_le32(&dcmds->phy_addr, dma_addr);
365		dcmds->xfer_status = 0;
366		++dcmds;
367	}
368
369	dma_cmd += OUTPUT_LAST - OUTPUT_MORE;
370	st_le16(&dcmds[-1].command, dma_cmd);
371	st_le16(&dcmds->command, DBDMA_STOP);
372	cmd->SCp.this_residual = total;
373}
374
375static struct scsi_host_template mac53c94_template = {
376	.proc_name	= "53c94",
377	.name		= "53C94",
378	.queuecommand	= mac53c94_queue,
379	.eh_host_reset_handler = mac53c94_host_reset,
380	.can_queue	= 1,
381	.this_id	= 7,
382	.sg_tablesize	= SG_ALL,
383	.cmd_per_lun	= 1,
384	.use_clustering	= DISABLE_CLUSTERING,
385};
386
387static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *match)
388{
389	struct device_node *node = macio_get_of_node(mdev);
390	struct pci_dev *pdev = macio_get_pci_dev(mdev);
391	struct fsc_state *state;
392	struct Scsi_Host *host;
393	void *dma_cmd_space;
394	const unsigned char *clkprop;
395	int proplen, rc = -ENODEV;
396
397	if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) {
398		printk(KERN_ERR "mac53c94: expected 2 addrs and intrs"
399		       " (got %d/%d)\n",
400		       macio_resource_count(mdev), macio_irq_count(mdev));
401		return -ENODEV;
402	}
403
404	if (macio_request_resources(mdev, "mac53c94") != 0) {
405       		printk(KERN_ERR "mac53c94: unable to request memory resources");
406		return -EBUSY;
407	}
408
409       	host = scsi_host_alloc(&mac53c94_template, sizeof(struct fsc_state));
410	if (host == NULL) {
411		printk(KERN_ERR "mac53c94: couldn't register host");
412		rc = -ENOMEM;
413		goto out_release;
414	}
415
416	state = (struct fsc_state *) host->hostdata;
417	macio_set_drvdata(mdev, state);
418	state->host = host;
419	state->pdev = pdev;
420	state->mdev = mdev;
421
422	state->regs = (struct mac53c94_regs __iomem *)
423		ioremap(macio_resource_start(mdev, 0), 0x1000);
424	state->intr = macio_irq(mdev, 0);
425	state->dma = (struct dbdma_regs __iomem *)
426		ioremap(macio_resource_start(mdev, 1), 0x1000);
427	state->dmaintr = macio_irq(mdev, 1);
428	if (state->regs == NULL || state->dma == NULL) {
429		printk(KERN_ERR "mac53c94: ioremap failed for %s\n",
430		       node->full_name);
431		goto out_free;
432	}
433
434	clkprop = of_get_property(node, "clock-frequency", &proplen);
435       	if (clkprop == NULL || proplen != sizeof(int)) {
436       		printk(KERN_ERR "%s: can't get clock frequency, "
437       		       "assuming 25MHz\n", node->full_name);
438       		state->clk_freq = 25000000;
439       	} else
440       		state->clk_freq = *(int *)clkprop;
441
442       	dma_cmd_space = kmalloc((host->sg_tablesize + 2) *
443       				sizeof(struct dbdma_cmd), GFP_KERNEL);
444       	if (dma_cmd_space == 0) {
445       		printk(KERN_ERR "mac53c94: couldn't allocate dma "
446       		       "command space for %s\n", node->full_name);
447		rc = -ENOMEM;
448       		goto out_free;
449       	}
450	state->dma_cmds = (struct dbdma_cmd *)DBDMA_ALIGN(dma_cmd_space);
451	memset(state->dma_cmds, 0, (host->sg_tablesize + 1)
452	       * sizeof(struct dbdma_cmd));
453	state->dma_cmd_space = dma_cmd_space;
454
455	mac53c94_init(state);
456
457	if (request_irq(state->intr, do_mac53c94_interrupt, 0, "53C94",state)) {
458		printk(KERN_ERR "mac53C94: can't get irq %d for %s\n",
459		       state->intr, node->full_name);
460		goto out_free_dma;
461	}
462
463	rc = scsi_add_host(host, &mdev->ofdev.dev);
464	if (rc != 0)
465		goto out_release_irq;
466
467	scsi_scan_host(host);
468	return 0;
469
470 out_release_irq:
471	free_irq(state->intr, state);
472 out_free_dma:
473	kfree(state->dma_cmd_space);
474 out_free:
475	if (state->dma != NULL)
476		iounmap(state->dma);
477	if (state->regs != NULL)
478		iounmap(state->regs);
479	scsi_host_put(host);
480 out_release:
481	macio_release_resources(mdev);
482
483	return rc;
484}
485
486static int mac53c94_remove(struct macio_dev *mdev)
487{
488	struct fsc_state *fp = (struct fsc_state *)macio_get_drvdata(mdev);
489	struct Scsi_Host *host = fp->host;
490
491	scsi_remove_host(host);
492
493	free_irq(fp->intr, fp);
494
495	if (fp->regs)
496		iounmap(fp->regs);
497	if (fp->dma)
498		iounmap(fp->dma);
499	kfree(fp->dma_cmd_space);
500
501	scsi_host_put(host);
502
503	macio_release_resources(mdev);
504
505	return 0;
506}
507
508
509static struct of_device_id mac53c94_match[] =
510{
511	{
512	.name 		= "53c94",
513	},
514	{},
515};
516MODULE_DEVICE_TABLE (of, mac53c94_match);
517
518static struct macio_driver mac53c94_driver =
519{
520	.driver = {
521		.name 		= "mac53c94",
522		.owner		= THIS_MODULE,
523		.of_match_table	= mac53c94_match,
524	},
525	.probe		= mac53c94_probe,
526	.remove		= mac53c94_remove,
527};
528
529
530static int __init init_mac53c94(void)
531{
532	return macio_register_driver(&mac53c94_driver);
533}
534
535static void __exit exit_mac53c94(void)
536{
537	return macio_unregister_driver(&mac53c94_driver);
538}
539
540module_init(init_mac53c94);
541module_exit(exit_mac53c94);
542
543MODULE_DESCRIPTION("PowerMac 53c94 SCSI driver");
544MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
545MODULE_LICENSE("GPL");
546