PageRenderTime 38ms CodeModel.GetById 11ms app.highlight 22ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/scsi/mac53c94.c

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