inia100.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 581 行 · 第 1/2 页

C
581
字号
/***************************************************************************** Function name  : inia100_device_reset Description    : Reset the device Input          : pHCB  -       Pointer to host adapter structure Output         : None. Return         : pSRB  -       Pointer to SCSI request block.*****************************************************************************/static int inia100_device_reset(struct scsi_cmnd * SCpnt){				/* I need Host Control Block Information */	ORC_HCS *pHCB;	pHCB = (ORC_HCS *) SCpnt->device->host->hostdata;	return orc_device_reset(pHCB, SCpnt, SCpnt->device->id);}/***************************************************************************** Function name  : inia100SCBPost Description    : This is callback routine be called when orc finish one			SCSI command. Input          : pHCB  -       Pointer to host adapter control block.		  pSCB  -       Pointer to SCSI control block. Output         : None. Return         : None.*****************************************************************************/void inia100SCBPost(BYTE * pHcb, BYTE * pScb){	struct scsi_cmnd *pSRB;	/* Pointer to SCSI request block */	ORC_HCS *pHCB;	ORC_SCB *pSCB;	ESCB *pEScb;	pHCB = (ORC_HCS *) pHcb;	pSCB = (ORC_SCB *) pScb;	pEScb = pSCB->SCB_EScb;	if ((pSRB = (struct scsi_cmnd *) pEScb->SCB_Srb) == 0) {		printk("inia100SCBPost: SRB pointer is empty\n");		orc_release_scb(pHCB, pSCB);	/* Release SCB for current channel */		return;	}	pEScb->SCB_Srb = NULL;	switch (pSCB->SCB_HaStat) {	case 0x0:	case 0xa:		/* Linked command complete without error and linked normally */	case 0xb:		/* Linked command complete without error interrupt generated */		pSCB->SCB_HaStat = 0;		break;	case 0x11:		/* Selection time out-The initiator selection or target				   reselection was not complete within the SCSI Time out period */		pSCB->SCB_HaStat = DID_TIME_OUT;		break;	case 0x14:		/* Target bus phase sequence failure-An invalid bus phase or bus				   phase sequence was requested by the target. The host adapter				   will generate a SCSI Reset Condition, notifying the host with				   a SCRD interrupt */		pSCB->SCB_HaStat = DID_RESET;		break;	case 0x1a:		/* SCB Aborted. 07/21/98 */		pSCB->SCB_HaStat = DID_ABORT;		break;	case 0x12:		/* Data overrun/underrun-The target attempted to transfer more data				   than was allocated by the Data Length field or the sum of the				   Scatter / Gather Data Length fields. */	case 0x13:		/* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */	case 0x16:		/* Invalid CCB Operation Code-The first byte of the CCB was invalid. */	default:		printk("inia100: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);		pSCB->SCB_HaStat = DID_ERROR;	/* Couldn't find any better */		break;	}	if (pSCB->SCB_TaStat == 2) {	/* Check condition              */		memcpy((unsigned char *) &pSRB->sense_buffer[0],		   (unsigned char *) &pEScb->ESCB_SGList[0], SENSE_SIZE);	}	pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);	orc_release_dma(pHCB, pSRB);  /* release DMA before we call scsi_done */	pSRB->scsi_done(pSRB);	/* Notify system DONE           */	/* Find the next pending SRB    */	if ((pSRB = inia100PopSRBFromQueue(pHCB)) != NULL) {	/* Assume resend will success   */		inia100BuildSCB(pHCB, pSCB, pSRB);	/* Create corresponding SCB     */		orc_exec_scb(pHCB, pSCB);	/* Start execute SCB            */	} else {		orc_release_scb(pHCB, pSCB);	/* Release SCB for current channel */	}	return;}/* * Interrupt handler (main routine of the driver) */static irqreturn_t inia100_intr(int irqno, void *devid, struct pt_regs *regs){	struct Scsi_Host *host = (struct Scsi_Host *)devid;	ORC_HCS *pHcb = (ORC_HCS *)host->hostdata;	unsigned long flags;	spin_lock_irqsave(host->host_lock, flags);	orc_interrupt(pHcb);	spin_unlock_irqrestore(host->host_lock, flags);	return IRQ_HANDLED;}static struct scsi_host_template inia100_template = {	.proc_name		= "inia100",	.name			= inia100_REVID,	.queuecommand		= inia100_queue,	.eh_abort_handler	= inia100_abort,	.eh_bus_reset_handler	= inia100_bus_reset,	.eh_device_reset_handler = inia100_device_reset,	.can_queue		= 1,	.this_id		= 1,	.sg_tablesize		= SG_ALL,	.cmd_per_lun 		= 1,	.use_clustering		= ENABLE_CLUSTERING,};static int __devinit inia100_probe_one(struct pci_dev *pdev,		const struct pci_device_id *id){	struct Scsi_Host *shost;	ORC_HCS *pHCB;	unsigned long port, bios;	int error = -ENODEV;	u32 sz;	unsigned long dBiosAdr;	char *pbBiosAdr;	if (pci_enable_device(pdev))		goto out;	if (pci_set_dma_mask(pdev, 0xffffffffULL)) {		printk(KERN_WARNING "Unable to set 32bit DMA "				    "on inia100 adapter, ignoring.\n");		goto out_disable_device;	}	pci_set_master(pdev);	port = pci_resource_start(pdev, 0);	if (!request_region(port, 256, "inia100")) {		printk(KERN_WARNING "inia100: io port 0x%lx, is busy.\n", port);		goto out_disable_device;	}	/* <02> read from base address + 0x50 offset to get the bios balue. */	bios = ORC_RDWORD(port, 0x50);	shost = scsi_host_alloc(&inia100_template, sizeof(ORC_HCS));	if (!shost)		goto out_release_region;	pHCB = (ORC_HCS *)shost->hostdata;	pHCB->pdev = pdev;	pHCB->HCS_Base = port;	pHCB->HCS_BIOS = bios;	pHCB->pSRB_head = NULL;	/* Initial SRB save queue       */	pHCB->pSRB_tail = NULL;	/* Initial SRB save queue       */	pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */	pHCB->BitAllocFlagLock = SPIN_LOCK_UNLOCKED;	/* Get total memory needed for SCB */	sz = ORC_MAXQUEUE * sizeof(ORC_SCB);	pHCB->HCS_virScbArray = pci_alloc_consistent(pdev, sz,			&pHCB->HCS_physScbArray);	if (!pHCB->HCS_virScbArray) {		printk("inia100: SCB memory allocation error\n");		goto out_host_put;	}	memset(pHCB->HCS_virScbArray, 0, sz);	/* Get total memory needed for ESCB */	sz = ORC_MAXQUEUE * sizeof(ESCB);	pHCB->HCS_virEscbArray = pci_alloc_consistent(pdev, sz,			&pHCB->HCS_physEscbArray);	if (!pHCB->HCS_virEscbArray) {		printk("inia100: ESCB memory allocation error\n");		goto out_free_scb_array;	}	memset(pHCB->HCS_virEscbArray, 0, sz);	dBiosAdr = pHCB->HCS_BIOS;	dBiosAdr = (dBiosAdr << 4);	pbBiosAdr = phys_to_virt(dBiosAdr);	if (init_orchid(pHCB)) {	/* Initialize orchid chip */		printk("inia100: initial orchid fail!!\n");		goto out_free_escb_array;	}	shost->io_port = pHCB->HCS_Base;	shost->n_io_port = 0xff;	shost->can_queue = ORC_MAXQUEUE;	shost->unique_id = shost->io_port;	shost->max_id = pHCB->HCS_MaxTar;	shost->max_lun = 16;	shost->irq = pHCB->HCS_Intr = pdev->irq;	shost->this_id = pHCB->HCS_SCSI_ID;	/* Assign HCS index */	shost->sg_tablesize = TOTAL_SG_ENTRY;	/* Initial orc chip           */	error = request_irq(pdev->irq, inia100_intr, SA_SHIRQ,			"inia100", shost);	if (error < 0) {		printk(KERN_WARNING "inia100: unable to get irq %d\n",				pdev->irq);		goto out_free_escb_array;	}	pci_set_drvdata(pdev, shost);	error = scsi_add_host(shost, &pdev->dev);	if (error)		goto out_free_irq;	scsi_scan_host(shost);	return 0; out_free_irq:        free_irq(shost->irq, shost); out_free_escb_array:	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),			pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray); out_free_scb_array:	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),			pHCB->HCS_virScbArray, pHCB->HCS_physScbArray); out_host_put:	scsi_host_put(shost); out_release_region:        release_region(port, 256); out_disable_device:	pci_disable_device(pdev); out:	return error;}static void __devexit inia100_remove_one(struct pci_dev *pdev){	struct Scsi_Host *shost = pci_get_drvdata(pdev);	ORC_HCS *pHCB = (ORC_HCS *)shost->hostdata;	scsi_remove_host(shost);        free_irq(shost->irq, shost);	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ESCB),			pHCB->HCS_virEscbArray, pHCB->HCS_physEscbArray);	pci_free_consistent(pdev, ORC_MAXQUEUE * sizeof(ORC_SCB),			pHCB->HCS_virScbArray, pHCB->HCS_physScbArray);        release_region(shost->io_port, 256);	scsi_host_put(shost);} static struct pci_device_id inia100_pci_tbl[] = {	{ORC_VENDOR_ID, ORC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	{0,}};MODULE_DEVICE_TABLE(pci, inia100_pci_tbl);static struct pci_driver inia100_pci_driver = {	.name		= "inia100",	.id_table	= inia100_pci_tbl,	.probe		= inia100_probe_one,	.remove		= __devexit_p(inia100_remove_one),};static int __init inia100_init(void){	return pci_module_init(&inia100_pci_driver);}static void __exit inia100_exit(void){	pci_unregister_driver(&inia100_pci_driver);}MODULE_DESCRIPTION("Initio A100U2W SCSI driver");MODULE_AUTHOR("Initio Corporation");MODULE_LICENSE("Dual BSD/GPL");module_init(inia100_init);module_exit(inia100_exit);

⌨️ 快捷键说明

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