aha1740.c

来自「linux 内核源代码」· C语言 代码 · 共 697 行 · 第 1/2 页

C
697
字号
#ifdef DEBUG	if (*cmd == READ_10 || *cmd == WRITE_10)		i = xscsi2int(cmd+2);	else if (*cmd == READ_6 || *cmd == WRITE_6)		i = scsi2int(cmd+2);	else		i = -1;	printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ",	       target, *cmd, i, bufflen);	printk("scsi cmd:");	for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]);	printk("\n");#endif	/* locate an available ecb */	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);	ecbno = host->last_ecb_used + 1; /* An optimization */	if (ecbno >= AHA1740_ECBS)		ecbno = 0;	do {		if (!host->ecb[ecbno].cmdw)			break;		ecbno++;		if (ecbno >= AHA1740_ECBS)			ecbno = 0;	} while (ecbno != host->last_ecb_used);	if (host->ecb[ecbno].cmdw)		panic("Unable to find empty ecb for aha1740.\n");	host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command						    doubles as reserved flag */	host->last_ecb_used = ecbno;    	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);#ifdef DEBUG	printk("Sending command (%d %x)...", ecbno, done);#endif	host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command						   * Descriptor Block						   * Length */	direction = 0;	if (*cmd == READ_10 || *cmd == READ_6)		direction = 1;	else if (*cmd == WRITE_10 || *cmd == WRITE_6)		direction = 0;	memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len);	SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev,						   sizeof (struct aha1740_sg),						   &sg_dma, GFP_ATOMIC);	if(SCpnt->host_scribble == NULL) {		printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n");		return 1;	}	sgptr = (struct aha1740_sg *) SCpnt->host_scribble;	sgptr->sg_dma_addr = sg_dma;	nseg = scsi_dma_map(SCpnt);	BUG_ON(nseg < 0);	if (nseg) {		struct scatterlist *sg;		struct aha1740_chain * cptr;		int i;		DEB(unsigned char * ptr);		host->ecb[ecbno].sg = 1;  /* SCSI Initiator Command					   * w/scatter-gather*/		cptr = sgptr->sg_chain;		scsi_for_each_sg(SCpnt, sg, nseg, i) {			cptr[i].datalen = sg_dma_len (sg);			cptr[i].dataptr = sg_dma_address (sg);		}		host->ecb[ecbno].datalen = nseg * sizeof(struct aha1740_chain);		host->ecb[ecbno].dataptr = sg_dma;#ifdef DEBUG		printk("cptr %x: ",cptr);		ptr = (unsigned char *) cptr;		for(i=0;i<24;i++) printk("%02x ", ptr[i]);#endif	} else {		host->ecb[ecbno].datalen = 0;		host->ecb[ecbno].dataptr = 0;	}	host->ecb[ecbno].lun = SCpnt->device->lun;	host->ecb[ecbno].ses = 1; /* Suppress underrun errors */	host->ecb[ecbno].dir = direction;	host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */	host->ecb[ecbno].senselen = 12;	host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host,						    host->ecb[ecbno].sense);	host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host,						     host->ecb[ecbno].status);	host->ecb[ecbno].done = done;	host->ecb[ecbno].SCpnt = SCpnt;#ifdef DEBUG	{		int i;		printk("aha1740_command: sending.. ");		for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++)			printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]);	}	printk("\n");#endif	if (done) {	/* The Adaptec Spec says the card is so fast that the loops           will only be executed once in the code below. Even if this           was true with the fastest processors when the spec was           written, it doesn't seem to be true with todays fast           processors. We print a warning if the code is executed more           often than LOOPCNT_WARN. If this happens, it should be           investigated. If the count reaches LOOPCNT_MAX, we assume           something is broken; since there is no way to return an           error (the return value is ignored by the mid-level scsi           layer) we have to panic (and maybe that's the best thing we           can do then anyhow). */#define LOOPCNT_WARN 10		/* excessive mbxout wait -> syslog-msg */#define LOOPCNT_MAX 1000000	/* mbxout deadlock -> panic() after ~ 2 sec. */		int loopcnt;		unsigned int base = SCpnt->device->host->io_port;		DEB(printk("aha1740[%d] critical section\n",ecbno));		spin_lock_irqsave(SCpnt->device->host->host_lock, flags);		for (loopcnt = 0; ; loopcnt++) {			if (inb(G2STAT(base)) & G2STAT_MBXOUT) break;			if (loopcnt == LOOPCNT_WARN) {				printk("aha1740[%d]_mbxout wait!\n",ecbno);			}			if (loopcnt == LOOPCNT_MAX)				panic("aha1740.c: mbxout busy!\n");		}		outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno),		      MBOXOUT0(base));		for (loopcnt = 0; ; loopcnt++) {			if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break;			if (loopcnt == LOOPCNT_WARN) {				printk("aha1740[%d]_attn wait!\n",ecbno);			}			if (loopcnt == LOOPCNT_MAX)				panic("aha1740.c: attn wait failed!\n");		}		outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */		spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);		DEB(printk("aha1740[%d] request queued.\n",ecbno));	} else		printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n");	return 0;}/* Query the board for its irq_level and irq_type.  Nothing else matters   in enhanced mode on an EISA bus. */static void aha1740_getconfig(unsigned int base, unsigned int *irq_level,			      unsigned int *irq_type,			      unsigned int *translation){	static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 };	*irq_level = intab[inb(INTDEF(base)) & 0x7];	*irq_type  = (inb(INTDEF(base)) & 0x8) >> 3;	*translation = inb(RESV1(base)) & 0x1;	outb(inb(INTDEF(base)) | 0x10, INTDEF(base));}static int aha1740_biosparam(struct scsi_device *sdev,			     struct block_device *dev,			     sector_t capacity, int* ip){	int size = capacity;	int extended = HOSTDATA(sdev->host)->translation;	DEB(printk("aha1740_biosparam\n"));	if (extended && (ip[2] > 1024))	{		ip[0] = 255;		ip[1] = 63;		ip[2] = size / (255 * 63);	} else {		ip[0] = 64;		ip[1] = 32;		ip[2] = size >> 11;	}	return 0;}static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy){/* * From Alan Cox : * The AHA1740 has firmware handled abort/reset handling. The "head in * sand" kernel code is correct for once 8) * * So we define a dummy handler just to keep the kernel SCSI code as * quiet as possible... */	return 0;}static struct scsi_host_template aha1740_template = {	.module           = THIS_MODULE,	.proc_name        = "aha1740",	.proc_info        = aha1740_proc_info,	.name             = "Adaptec 174x (EISA)",	.queuecommand     = aha1740_queuecommand,	.bios_param       = aha1740_biosparam,	.can_queue        = AHA1740_ECBS,	.this_id          = 7,	.sg_tablesize     = AHA1740_SCATTER,	.cmd_per_lun      = AHA1740_CMDLUN,	.use_clustering   = ENABLE_CLUSTERING,	.use_sg_chaining  = ENABLE_SG_CHAINING,	.eh_abort_handler = aha1740_eh_abort_handler,};static int aha1740_probe (struct device *dev){	int slotbase, rc;	unsigned int irq_level, irq_type, translation;	struct Scsi_Host *shpnt;	struct aha1740_hostdata *host;	struct eisa_device *edev = to_eisa_device (dev);	DEB(printk("aha1740_probe: \n"));		slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET;	if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */		return -EBUSY;	if (!aha1740_test_port(slotbase))		goto err_release_region;	aha1740_getconfig(slotbase,&irq_level,&irq_type,&translation);	if ((inb(G2STAT(slotbase)) &	     (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) {		/* If the card isn't ready, hard reset it */		outb(G2CNTRL_HRST, G2CNTRL(slotbase));		outb(0, G2CNTRL(slotbase));	}	printk(KERN_INFO "Configuring slot %d at IO:%x, IRQ %u (%s)\n",	       edev->slot, slotbase, irq_level, irq_type ? "edge" : "level");	printk(KERN_INFO "aha174x: Extended translation %sabled.\n",	       translation ? "en" : "dis");	shpnt = scsi_host_alloc(&aha1740_template,			      sizeof(struct aha1740_hostdata));	if(shpnt == NULL)		goto err_release_region;	shpnt->base = 0;	shpnt->io_port = slotbase;	shpnt->n_io_port = SLOTSIZE;	shpnt->irq = irq_level;	shpnt->dma_channel = 0xff;	host = HOSTDATA(shpnt);	host->edev = edev;	host->translation = translation;	host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb,					     sizeof (host->ecb),					     DMA_BIDIRECTIONAL);	if (!host->ecb_dma_addr) {		printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n");		scsi_unregister (shpnt);		goto err_host_put;	}		DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level));	if (request_irq(irq_level,aha1740_intr_handle,irq_type ? 0 : IRQF_SHARED,			"aha1740",shpnt)) {		printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n",		       irq_level);		goto err_unmap;	}	eisa_set_drvdata (edev, shpnt);	rc = scsi_add_host (shpnt, dev);	if (rc)		goto err_irq;	scsi_scan_host (shpnt);	return 0; err_irq: 	free_irq(irq_level, shpnt); err_unmap:	dma_unmap_single (&edev->dev, host->ecb_dma_addr,			  sizeof (host->ecb), DMA_BIDIRECTIONAL); err_host_put:	scsi_host_put (shpnt); err_release_region:	release_region(slotbase, SLOTSIZE);	return -ENODEV;}static __devexit int aha1740_remove (struct device *dev){	struct Scsi_Host *shpnt = dev->driver_data;	struct aha1740_hostdata *host = HOSTDATA (shpnt);	scsi_remove_host(shpnt);		free_irq (shpnt->irq, shpnt);	dma_unmap_single (dev, host->ecb_dma_addr,			  sizeof (host->ecb), DMA_BIDIRECTIONAL);	release_region (shpnt->io_port, SLOTSIZE);	scsi_host_put (shpnt);		return 0;}static struct eisa_device_id aha1740_ids[] = {	{ "ADP0000" },		/* 1740  */	{ "ADP0001" },		/* 1740A */	{ "ADP0002" },		/* 1742A */	{ "ADP0400" },		/* 1744  */	{ "" }};MODULE_DEVICE_TABLE(eisa, aha1740_ids);static struct eisa_driver aha1740_driver = {	.id_table = aha1740_ids,	.driver   = {		.name    = "aha1740",		.probe   = aha1740_probe,		.remove  = __devexit_p (aha1740_remove),	},};static __init int aha1740_init (void){	return eisa_driver_register (&aha1740_driver);}static __exit void aha1740_exit (void){	eisa_driver_unregister (&aha1740_driver);}module_init (aha1740_init);module_exit (aha1740_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?