📄 psi240i.c
字号:
}irqerror:; DEB(printk ("\npsi240i error Device Status: %X\n", status)); SCpnt->result = DecodeError (shost, status); SCpnt->scsi_done (SCpnt); }static irqreturn_t do_Irq_Handler (int irq, void *dev_id, struct pt_regs *regs){ unsigned long flags; struct Scsi_Host *dev = dev_id; spin_lock_irqsave(dev->host_lock, flags); Irq_Handler(irq, dev_id, regs); spin_unlock_irqrestore(dev->host_lock, flags); return IRQ_HANDLED;}/**************************************************************** * Name: Psi240i_QueueCommand * * Description: Process a queued command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * done - Pointer to done function to call. * * Returns: Status code. * ****************************************************************/int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB PADAPTER240I padapter = HOSTDATA (SCpnt->device->host); // Pointer to adapter control structure POUR_DEVICE pdev = &padapter->device [SCpnt->device->id];// Pointer to device information UCHAR rc; // command return code SCpnt->scsi_done = done; padapter->ide.ide.ides.spigot = pdev->spigot; padapter->buffer = SCpnt->request_buffer; if (done) { if ( !pdev->device ) { SCpnt->result = DID_BAD_TARGET << 16; done (SCpnt); return 0; } } else { printk("psi240i_queuecommand: %02X: done can't be NULL\n", *cdb); return 0; } switch ( *cdb ) { case SCSIOP_INQUIRY: // inquiry CDB { padapter->ide.ide.ide[6] = pdev->byte6; padapter->ide.ide.ides.cmd = IDE_COMMAND_IDENTIFY; break; } case SCSIOP_TEST_UNIT_READY: // test unit ready CDB SCpnt->result = DID_OK << 16; done (SCpnt); return 0; case SCSIOP_READ_CAPACITY: // read capctiy CDB { PREAD_CAPACITY_DATA pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer; pdata->blksiz = 0x20000; XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks); SCpnt->result = DID_OK << 16; done (SCpnt); return 0; } case SCSIOP_VERIFY: // verify CDB *(ULONG *)padapter->ide.ide.ides.lba = XSCSI2LONG (&cdb[2]); padapter->ide.ide.ide[6] |= pdev->byte6; padapter->ide.ide.ide[2] = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8)); padapter->ide.ide.ides.cmd = IDE_COMMAND_VERIFY; break; case SCSIOP_READ: // read10 CDB padapter->startSector = XSCSI2LONG (&cdb[2]); padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8); SetupTransfer (padapter, pdev->byte6); padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE; break; case SCSIOP_READ6: // read6 CDB padapter->startSector = SCSI2LONG (&cdb[1]); padapter->sectorCount = cdb[4]; SetupTransfer (padapter, pdev->byte6); padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE; break; case SCSIOP_WRITE: // write10 CDB padapter->startSector = XSCSI2LONG (&cdb[2]); padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8); SetupTransfer (padapter, pdev->byte6); padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE; break; case SCSIOP_WRITE6: // write6 CDB padapter->startSector = SCSI2LONG (&cdb[1]); padapter->sectorCount = cdb[4]; SetupTransfer (padapter, pdev->byte6); padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE; break; default: DEB (printk ("psi240i_queuecommand: Unsupported command %02X\n", *cdb)); SCpnt->result = DID_ERROR << 16; done (SCpnt); return 0; } padapter->SCpnt = SCpnt; // Save this command data rc = IdeCmd (padapter); if ( rc ) { padapter->expectingIRQ = 0; DEB (printk ("psi240i_queuecommand: %02X, %02X: Device failed to respond for command\n", *cdb, padapter->ide.ide.ides.cmd)); SCpnt->result = DID_ERROR << 16; done (SCpnt); return 0; } DEB (printk("psi240i_queuecommand: %02X, %02X now waiting for interrupt ", *cdb, padapter->ide.ide.ides.cmd)); return 0; }/*************************************************************************** * Name: ReadChipMemory * * Description: Read information from controller memory. * * Parameters: psetup - Pointer to memory image of setup information. * base - base address of memory. * length - lenght of data space in bytes. * port - I/O address of data port. * * Returns: Nothing. * **************************************************************************/void ReadChipMemory (void *pdata, USHORT base, USHORT length, USHORT port) { USHORT z, zz; UCHAR *pd = (UCHAR *)pdata; outb_p (SEL_NONE, port + REG_SEL_FAIL); // setup data port zz = 0; while ( zz < length ) { outw_p (base, port + REG_ADDRESS); // setup address for ( z = 0; z < 8; z++ ) { if ( (zz + z) < length ) *pd++ = inb_p (port + z); // read data byte } zz += 8; base += 8; } }/**************************************************************** * Name: Psi240i_Detect * * Description: Detect and initialize our boards. * * Parameters: tpnt - Pointer to SCSI host template structure. * * Returns: Number of adapters found. * ****************************************************************/int Psi240i_Detect (Scsi_Host_Template *tpnt) { int board; int count = 0; int unit; int z; USHORT port, port_range = 16; CHIP_CONFIG_N chipConfig; CHIP_DEVICE_N chipDevice[8]; struct Scsi_Host *pshost; for ( board = 0; board < MAXBOARDS; board++ ) // scan for I/O ports { pshost = NULL; port = portAddr[board]; // get base address to test if ( !request_region (port, port_range, "psi240i") ) continue; if ( inb_p (port + REG_FAIL) != CHIP_ID ) // do the first test for likley hood that it is us goto host_init_failure; outb_p (SEL_NONE, port + REG_SEL_FAIL); // setup EEPROM/RAM access outw (0, port + REG_ADDRESS); // setup EEPROM address zero if ( inb_p (port) != 0x55 ) // test 1st byte goto host_init_failure; // nope if ( inb_p (port + 1) != 0xAA ) // test 2nd byte goto host_init_failure; // nope // at this point our board is found and can be accessed. Now we need to initialize // our informatation and register with the kernel. ReadChipMemory (&chipConfig, CHIP_CONFIG, sizeof (chipConfig), port); ReadChipMemory (&chipDevice, CHIP_DEVICE, sizeof (chipDevice), port); ReadChipMemory (&ChipSetup, CHIP_EEPROM_DATA, sizeof (ChipSetup), port); if ( !chipConfig.numDrives ) // if no devices on this board goto host_init_failure; pshost = scsi_register (tpnt, sizeof(ADAPTER240I)); if(pshost == NULL) goto host_init_failure; PsiHost[chipConfig.irq - 10] = pshost; pshost->unique_id = port; pshost->io_port = port; pshost->n_io_port = 16; /* Number of bytes of I/O space used */ pshost->irq = chipConfig.irq; for ( z = 0; z < 11; z++ ) // build regester address array HOSTDATA(pshost)->ports[z] = port + z; HOSTDATA(pshost)->ports[11] = port + REG_FAIL; HOSTDATA(pshost)->ports[12] = port + REG_ALT_STAT; DEB (printk ("\nPorts =")); DEB (for (z=0;z<13;z++) printk(" %#04X",HOSTDATA(pshost)->ports[z]);); for ( z = 0; z < chipConfig.numDrives; ++z ) { unit = chipDevice[z].channel & 0x0F; HOSTDATA(pshost)->device[unit].device = ChipSetup.setupDevice[unit].device; HOSTDATA(pshost)->device[unit].byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0); HOSTDATA(pshost)->device[unit].spigot = (UCHAR)(1 << (unit >> 1)); HOSTDATA(pshost)->device[unit].sectors = ChipSetup.setupDevice[unit].sectors; HOSTDATA(pshost)->device[unit].heads = ChipSetup.setupDevice[unit].heads; HOSTDATA(pshost)->device[unit].cylinders = ChipSetup.setupDevice[unit].cylinders; HOSTDATA(pshost)->device[unit].blocks = ChipSetup.setupDevice[unit].blocks; DEB (printk ("\nHOSTDATA->device = %X", HOSTDATA(pshost)->device[unit].device)); DEB (printk ("\n byte6 = %X", HOSTDATA(pshost)->device[unit].byte6)); DEB (printk ("\n spigot = %X", HOSTDATA(pshost)->device[unit].spigot)); DEB (printk ("\n sectors = %X", HOSTDATA(pshost)->device[unit].sectors)); DEB (printk ("\n heads = %X", HOSTDATA(pshost)->device[unit].heads)); DEB (printk ("\n cylinders = %X", HOSTDATA(pshost)->device[unit].cylinders)); DEB (printk ("\n blocks = %lX", HOSTDATA(pshost)->device[unit].blocks)); } if ( request_irq (chipConfig.irq, do_Irq_Handler, 0, "psi240i", pshost) == 0 ) { printk("\nPSI-240I EIDE CONTROLLER: at I/O = %x IRQ = %d\n", port, chipConfig.irq); printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n"); count++; continue; } printk ("Unable to allocate IRQ for PSI-240I controller.\n"); host_init_failure: release_region (port, port_range); if (pshost) scsi_unregister (pshost); } return count; }static int Psi240i_Release(struct Scsi_Host *shost){ if (shost->irq) free_irq(shost->irq, NULL); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); return 0;}/**************************************************************** * Name: Psi240i_Abort * * Description: Process the Abort command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * * Returns: Allways snooze. * ****************************************************************/int Psi240i_Abort (Scsi_Cmnd *SCpnt) { DEB (printk ("psi240i_abort\n")); return SCSI_ABORT_SNOOZE; }/**************************************************************** * Name: Psi240i_Reset * * Description: Process the Reset command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * flags - Flags about the reset command * * Returns: No active command at this time, so this means * that each time we got some kind of response the * last time through. Tell the mid-level code to * request sense information in order to decide what * to do next. * ****************************************************************/int Psi240i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) { return SCSI_RESET_PUNT; }/**************************************************************** * Name: Psi240i_BiosParam * * Description: Process the biosparam request from the SCSI manager to * return C/H/S data. * * Parameters: disk - Pointer to SCSI disk structure. * dev - Major/minor number from kernel. * geom - Pointer to integer array to place geometry data. * * Returns: zero. * ****************************************************************/int Psi240i_BiosParam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]) { POUR_DEVICE pdev; pdev = &(HOSTDATA(sdev->host)->device[sdev->id]); geom[0] = pdev->heads; geom[1] = pdev->sectors; geom[2] = pdev->cylinders; return 0; }MODULE_LICENSE("GPL");static Scsi_Host_Template driver_template = { .proc_name = "psi240i", .name = "PSI-240I EIDE Disk Controller", .detect = Psi240i_Detect, .release = Psi240i_Release, .queuecommand = Psi240i_QueueCommand, .abort = Psi240i_Abort, .reset = Psi240i_Reset, .bios_param = Psi240i_BiosParam, .can_queue = 1, .this_id = -1, .sg_tablesize = SG_NONE, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING,};#include "scsi_module.c"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -