📄 pci2000.c
字号:
pdev->SCpnt = SCpnt; // Save this command data if ( WaitReady (padapter) ) { rc = DID_ERROR; goto finished; } outw_p (pun | (lun << 8), padapter->mb0); if ( bus ) { DEB (if(*cdb) printk ("\nCDB: %X- %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9])); DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d, internal_timout: %d", SCpnt->timeout_per_command, SCpnt->timeout_total, SCpnt->timeout, SCpnt->internal_timeout)); outl (SCpnt->timeout_per_command, padapter->mb1); outb_p (CMD_SCSI_TIMEOUT, padapter->cmd); if ( WaitReady (padapter) ) { rc = DID_ERROR; goto finished; } outw_p (pun | (lun << 8), padapter->mb0); outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2); memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE); outl (pdev->cdbDma, padapter->mb1); if ( BuildSgList (SCpnt, padapter, pdev) ) cmd = CMD_SCSI_THRU; else cmd = CMD_SCSI_THRU_SG; if ( (pdev->tag = Command (padapter, cmd)) == 0 ) rc = DID_TIME_OUT; goto finished; } else { if ( lun ) { rc = DID_BAD_TARGET; goto finished; } } switch ( *cdb ) { case SCSIOP_INQUIRY: // inquiry CDB if ( cdb[2] == SC_MY_RAID ) { switch ( cdb[3] ) { case MY_SCSI_REBUILD: OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16); return 0; case MY_SCSI_ALARMMUTE: OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16); return 0; case MY_SCSI_DEMOFAIL: OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16); return 0; default: if ( SCpnt->use_sg ) { rc = DID_ERROR; goto finished; } else { SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen, scsi_to_pci_dma_dir(SCpnt->sc_data_direction)); outl (SCpnt->SCp.have_data_in, padapter->mb2); } outl (cdb[5], padapter->mb0); outl (cdb[3], padapter->mb3); cmd = CMD_DASD_RAID_RQ; break; } break; } if ( SCpnt->use_sg ) { SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)SCpnt->request_buffer)->address, SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction)); } else { SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen, scsi_to_pci_dma_dir (SCpnt->sc_data_direction)); } outl (SCpnt->SCp.have_data_in, padapter->mb2); outl (SCpnt->request_bufflen, padapter->mb3); cmd = CMD_DASD_SCSI_INQ; break; case SCSIOP_TEST_UNIT_READY: // test unit ready CDB SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE); outl (SCpnt->SCp.have_data_in, padapter->mb2); outl (sizeof (SCpnt->sense_buffer), padapter->mb3); cmd = CMD_TEST_READY; break; case SCSIOP_READ_CAPACITY: // read capacity CDB if ( SCpnt->use_sg ) { SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address, 8, PCI_DMA_FROMDEVICE); } else SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE); outl (SCpnt->SCp.have_data_in, padapter->mb2); outl (8, padapter->mb3); cmd = CMD_DASD_CAP; break; case SCSIOP_VERIFY: // verify CDB outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2); outl (XSCSI2LONG (&cdb[2]), padapter->mb1); cmd = CMD_READ_SG; break; case SCSIOP_READ: // read10 CDB outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2); outl (XSCSI2LONG (&cdb[2]), padapter->mb1); if ( BuildSgList (SCpnt, padapter, pdev) ) cmd = CMD_READ; else cmd = CMD_READ_SG; break; case SCSIOP_READ6: // read6 CDB outw_p (cdb[4], padapter->mb0 + 2); outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1); if ( BuildSgList (SCpnt, padapter, pdev) ) cmd = CMD_READ; else cmd = CMD_READ_SG; break; case SCSIOP_WRITE: // write10 CDB outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2); outl (XSCSI2LONG (&cdb[2]), padapter->mb1); if ( BuildSgList (SCpnt, padapter, pdev) ) cmd = CMD_WRITE; else cmd = CMD_WRITE_SG; break; case SCSIOP_WRITE6: // write6 CDB outw_p (cdb[4], padapter->mb0 + 2); outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1); if ( BuildSgList (SCpnt, padapter, pdev) ) cmd = CMD_WRITE; else cmd = CMD_WRITE_SG; break; case SCSIOP_START_STOP_UNIT: cmd = CMD_EJECT_MEDIA; break; case SCSIOP_MEDIUM_REMOVAL: switch ( cdb[4] ) { case 0: cmd = CMD_UNLOCK_DOOR; break; case 1: cmd = CMD_LOCK_DOOR; break; default: cmd = 0; break; } if ( cmd ) break; default: DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb)); OpDone (SCpnt, DID_ERROR << 16); return 0; } if ( (pdev->tag = Command (padapter, cmd)) == 0 ) rc = DID_TIME_OUT;finished:; if ( rc != -1 ) OpDone (SCpnt, rc << 16); return 0; }/**************************************************************** * Name: internal_done :LOCAL * * Description: Done handler for non-queued commands * * Parameters: SCpnt - Pointer to SCSI command structure. * * Returns: Nothing. * ****************************************************************/static void internal_done (Scsi_Cmnd * SCpnt) { SCpnt->SCp.Status++; }/**************************************************************** * Name: Pci2000_Command * * Description: Process a command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * * Returns: Status code. * ****************************************************************/int Pci2000_Command (Scsi_Cmnd *SCpnt) { DEB(printk("pci2000_command: ..calling pci2000_queuecommand\n")); Pci2000_QueueCommand (SCpnt, internal_done); SCpnt->SCp.Status = 0; while (!SCpnt->SCp.Status) barrier (); return SCpnt->result; }/**************************************************************** * Name: Pci2000_Detect * * Description: Detect and initialize our boards. * * Parameters: tpnt - Pointer to SCSI host template structure. * * Returns: Number of adapters installed. * ****************************************************************/int Pci2000_Detect (Scsi_Host_Template *tpnt) { int found = 0; int installed = 0; struct Scsi_Host *pshost; PADAPTER2000 padapter; int z, zz; int setirq; struct pci_dev *pdev = NULL; UCHAR *consistent; dma_addr_t consistentDma; if ( !pci_present () ) { printk ("pci2000: PCI BIOS not present\n"); return 0; } while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL ) { if (pci_enable_device(pdev)) continue; pshost = scsi_register (tpnt, sizeof(ADAPTER2000)); if(pshost == NULL) continue; padapter = HOSTDATA(pshost); padapter->basePort = pci_resource_start (pdev, 1); DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4; padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8; padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12; padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16; padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register padapter->pdev = pdev; if ( WaitReady (padapter) ) goto unregister; outb_p (0x84, padapter->mb0); outb_p (CMD_SPECIFY, padapter->cmd); if ( WaitReady (padapter) ) goto unregister; consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma); if ( !consistent ) { printk ("Unable to allocate DMA memory for PCI-2000 controller.\n"); goto unregister; } pshost->irq = pdev->irq; setirq = 1; padapter->irqOwned = 0; for ( z = 0; z < installed; z++ ) // scan for shared interrupts { if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses setirq = 0; } if ( setirq ) // if not shared, posses { if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 ) { if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 ) { printk ("Unable to allocate IRQ for PCI-2000 controller.\n"); pci_free_consistent (pdev, consistentLen, consistent, consistentDma); goto unregister; } } padapter->irqOwned = pshost->irq; // set IRQ as owned } PsiHost[installed] = pshost; // save SCSI_HOST pointer pshost->io_port = padapter->basePort; pshost->n_io_port = 0xFF; pshost->unique_id = padapter->basePort; pshost->max_id = 16; pshost->max_channel = 1; for ( zz = 0; zz < MAX_BUS; zz++ ) for ( z = 0; z < MAX_UNITS; z++ ) { padapter->dev[zz][z].tag = 0; padapter->dev[zz][z].scatGath = (PSCATGATH)consistent; padapter->dev[zz][z].scatGathDma = consistentDma; consistent += 16 * sizeof (SCATGATH); consistentDma += 16 * sizeof (SCATGATH); padapter->dev[zz][z].cdb = (UCHAR *)consistent; padapter->dev[zz][z].cdbDma = consistentDma; consistent += MAX_COMMAND_SIZE; consistentDma += MAX_COMMAND_SIZE; } printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX IRQ = %d\n", padapter->basePort, pshost->irq); printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__); found++; if ( ++installed < MAXADAPTER ) continue; break;unregister:; scsi_unregister (pshost); found++; } NumAdapters = installed; return installed; }/**************************************************************** * Name: Pci2000_Abort * * Description: Process the Abort command from the SCSI manager. * * Parameters: SCpnt - Pointer to SCSI command structure. * * Returns: Allways snooze. * ****************************************************************/int Pci2000_Abort (Scsi_Cmnd *SCpnt) { DEB (printk ("pci2000_abort\n")); return SCSI_ABORT_SNOOZE; }/**************************************************************** * Name: Pci2000_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 Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags) { return SCSI_RESET_PUNT; }/**************************************************************** * Name: Pci2000_Release * * Description: Release resources allocated for a single each adapter. * * Parameters: pshost - Pointer to SCSI command structure. * * Returns: zero. * ****************************************************************/int Pci2000_Release (struct Scsi_Host *pshost) { PADAPTER2000 padapter = HOSTDATA (pshost); if ( padapter->irqOwned ) free_irq (pshost->irq, padapter); pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma); release_region (pshost->io_port, pshost->n_io_port); scsi_unregister(pshost); return 0; }#include "sd.h"/**************************************************************** * Name: Pci2000_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 Pci2000_BiosParam (Scsi_Disk *disk, kdev_t dev, int geom[]) { PADAPTER2000 padapter; padapter = HOSTDATA(disk->device->host); if ( WaitReady (padapter) ) return 0; outb_p (disk->device->id, padapter->mb0); outb_p (CMD_GET_PARMS, padapter->cmd); if ( WaitReady (padapter) ) return 0; geom[0] = inb_p (padapter->mb2 + 3); geom[1] = inb_p (padapter->mb2 + 2); geom[2] = inw_p (padapter->mb2); return 0; }/* Eventually this will go into an include file, but this will be later */static Scsi_Host_Template driver_template = PCI2000;#include "scsi_module.c"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -