📄 dpt_i2o.c
字号:
geom[2] = cylinders; PDEBUG("adpt_bios_param: exit\n"); return 0;}static const char *adpt_info(struct Scsi_Host *host){ adpt_hba* pHba; pHba = (adpt_hba *) host->hostdata[0]; return (char *) (pHba->detail);}static int adpt_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout){ struct adpt_device* d; int id; int chan; int len = 0; int begin = 0; int pos = 0; adpt_hba* pHba; struct Scsi_Host *host; int unit; *start = buffer; if (inout == TRUE) { /* * The user has done a write and wants us to take the * data in the buffer and do something with it. * proc_scsiwrite calls us with inout = 1 * * Read data from buffer (writing to us) - NOT SUPPORTED */ return -EINVAL; } /* * inout = 0 means the user has done a read and wants information * returned, so we write information about the cards into the buffer * proc_scsiread() calls us with inout = 0 */ // Find HBA (host bus adapter) we are looking for down(&adpt_configuration_lock); for (pHba = hba_chain; pHba; pHba = pHba->next) { if (pHba->host->host_no == hostno) { break; /* found adapter */ } } up(&adpt_configuration_lock); if (pHba == NULL) { return 0; } host = pHba->host; len = sprintf(buffer , "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION); len += sprintf(buffer+len, "%s\n", pHba->detail); len += sprintf(buffer+len, "SCSI Host=scsi%d Control Node=/dev/%s irq=%d\n", pHba->host->host_no, pHba->name, host->irq); len += sprintf(buffer+len, "\tpost fifo size = %d\n\treply fifo size = %d\n\tsg table size = %d\n\n", host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize); pos = begin + len; /* CHECKPOINT */ if(pos > offset + length) { goto stop_output; } if(pos <= offset) { /* * If we haven't even written to where we last left * off (the last time we were called), reset the * beginning pointer. */ len = 0; begin = pos; } len += sprintf(buffer+len, "Devices:\n"); for(chan = 0; chan < MAX_CHANNEL; chan++) { for(id = 0; id < MAX_ID; id++) { d = pHba->channel[chan].device[id]; while(d){ len += sprintf(buffer+len,"\t%-24.24s", d->pScsi_dev->vendor); len += sprintf(buffer+len," Rev: %-8.8s\n", d->pScsi_dev->rev); pos = begin + len; /* CHECKPOINT */ if(pos > offset + length) { goto stop_output; } if(pos <= offset) { len = 0; begin = pos; } unit = d->pI2o_dev->lct_data.tid; len += sprintf(buffer+len, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d) (%s)\n\n", unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun, d->pScsi_dev->online? "online":"offline"); pos = begin + len; /* CHECKPOINT */ if(pos > offset + length) { goto stop_output; } if(pos <= offset) { len = 0; begin = pos; } d = d->next_lun; } } } /* * begin is where we last checked our position with regards to offset * begin is always less than offset. len is relative to begin. It * is the number of bytes written past begin * */stop_output: /* stop the output and calculate the correct length */ *(buffer + len) = '\0'; *start = buffer + (offset - begin); /* Start of wanted data */ len -= (offset - begin); if(len > length) { len = length; } else if(len < 0){ len = 0; **start = '\0'; } return len;}/*=========================================================================== * Error Handling routines *=========================================================================== */static int adpt_abort(Scsi_Cmnd * cmd){ adpt_hba* pHba = NULL; /* host bus adapter structure */ struct adpt_device* dptdevice; /* dpt per device information */ u32 msg[5]; int rcode; if(cmd->serial_number == 0){ return FAILED; } pHba = (adpt_hba*) cmd->host->hostdata[0]; printk(KERN_INFO"%s: Trying to Abort cmd=%ld\n",pHba->name, cmd->serial_number); if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) { printk(KERN_ERR "%s: Unable to abort: No device in cmnd\n",pHba->name); return FAILED; } memset(msg, 0, sizeof(msg)); msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid; msg[2] = 0; msg[3]= 0; msg[4] = (u32)cmd; if( (rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER)) != 0){ if(rcode == -EOPNOTSUPP ){ printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name); return FAILED; } printk(KERN_INFO"%s: Abort cmd=%ld failed.\n",pHba->name, cmd->serial_number); return FAILED; } printk(KERN_INFO"%s: Abort cmd=%ld complete.\n",pHba->name, cmd->serial_number); return SUCCESS;}#define I2O_DEVICE_RESET 0x27// This is the same for BLK and SCSI devices// NOTE this is wrong in the i2o.h definitions// This is not currently supported by our adapter but we issue it anywaystatic int adpt_device_reset(Scsi_Cmnd* cmd){ adpt_hba* pHba; u32 msg[4]; u32 rcode; int old_state; struct adpt_device* d = (void*) cmd->device->hostdata; pHba = (void*) cmd->host->hostdata[0]; printk(KERN_INFO"%s: Trying to reset device\n",pHba->name); if (!d) { printk(KERN_INFO"%s: Reset Device: Device Not found\n",pHba->name); return FAILED; } memset(msg, 0, sizeof(msg)); msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1] = (I2O_DEVICE_RESET<<24|HOST_TID<<12|d->tid); msg[2] = 0; msg[3] = 0; old_state = d->state; d->state |= DPTI_DEV_RESET; if( (rcode = adpt_i2o_post_wait(pHba, (void*)msg,sizeof(msg), FOREVER)) ){ d->state = old_state; if(rcode == -EOPNOTSUPP ){ printk(KERN_INFO"%s: Device reset not supported\n",pHba->name); return FAILED; } printk(KERN_INFO"%s: Device reset failed\n",pHba->name); return FAILED; } else { d->state = old_state; printk(KERN_INFO"%s: Device reset successful\n",pHba->name); return SUCCESS; }}#define I2O_HBA_BUS_RESET 0x87// This version of bus reset is called by the eh_error handlerstatic int adpt_bus_reset(Scsi_Cmnd* cmd){ adpt_hba* pHba; u32 msg[4]; pHba = (adpt_hba*)cmd->host->hostdata[0]; memset(msg, 0, sizeof(msg)); printk(KERN_WARNING"%s: Bus reset: SCSI Bus %d: tid: %d\n",pHba->name, cmd->channel,pHba->channel[cmd->channel].tid ); msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->channel].tid); msg[2] = 0; msg[3] = 0; if(adpt_i2o_post_wait(pHba, (void*)msg,sizeof(msg), FOREVER) ){ printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name); return FAILED; } else { printk(KERN_WARNING"%s: Bus reset success.\n",pHba->name); return SUCCESS; }}// This version of reset is called by the eh_error_handlerstatic int adpt_reset(Scsi_Cmnd* cmd){ adpt_hba* pHba; int rcode; pHba = (adpt_hba*)cmd->host->hostdata[0]; printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n",pHba->name,cmd->channel,pHba->channel[cmd->channel].tid ); rcode = adpt_hba_reset(pHba); if(rcode == 0){ printk(KERN_WARNING"%s: HBA reset complete\n",pHba->name); return SUCCESS; } else { printk(KERN_WARNING"%s: HBA reset failed (%x)\n",pHba->name, rcode); return FAILED; }}// This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_resetstatic int adpt_hba_reset(adpt_hba* pHba){ int rcode; pHba->state |= DPTI_STATE_RESET; // Activate does get status , init outbound, and get hrt if ((rcode=adpt_i2o_activate_hba(pHba)) < 0) { printk(KERN_ERR "%s: Could not activate\n", pHba->name); adpt_i2o_delete_hba(pHba); return rcode; } if ((rcode=adpt_i2o_build_sys_table()) < 0) { adpt_i2o_delete_hba(pHba); return rcode; } PDEBUG("%s: in HOLD state\n",pHba->name); if ((rcode=adpt_i2o_online_hba(pHba)) < 0) { adpt_i2o_delete_hba(pHba); return rcode; } PDEBUG("%s: in OPERATIONAL state\n",pHba->name); if ((rcode=adpt_i2o_lct_get(pHba)) < 0){ adpt_i2o_delete_hba(pHba); return rcode; } if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){ adpt_i2o_delete_hba(pHba); return rcode; } pHba->state &= ~DPTI_STATE_RESET; adpt_fail_posted_scbs(pHba); return 0; /* return success */}/*=========================================================================== * *=========================================================================== */static void adpt_i2o_sys_shutdown(void){ adpt_hba *pHba, *pNext; struct adpt_i2o_post_wait_data *p1, *p2; printk(KERN_INFO"Shutting down Adaptec I2O controllers.\n"); printk(KERN_INFO" This could take a few minutes if there are many devices attached\n"); /* Delete all IOPs from the controller chain */ /* They should have already been released by the * scsi-core */ for (pHba = hba_chain; pHba; pHba = pNext) { pNext = pHba->next; adpt_i2o_delete_hba(pHba); } /* Remove any timedout entries from the wait queue. */ p2 = NULL;// spin_lock_irqsave(&adpt_post_wait_lock, flags); /* Nothing should be outstanding at this point so just * free them */ for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p2->next) { kfree(p1); }// spin_unlock_irqrestore(&adpt_post_wait_lock, flags); adpt_post_wait_queue = 0; printk(KERN_INFO "Adaptec I2O controllers down.\n");}/* * reboot/shutdown notification. * * - Quiesce each IOP in the system * */#ifdef REBOOT_NOTIFIERstatic int adpt_reboot_event(struct notifier_block *n, ulong code, void *p){ if(code != SYS_RESTART && code != SYS_HALT && code != SYS_POWER_OFF) return NOTIFY_DONE; adpt_i2o_sys_shutdown(); return NOTIFY_DONE;}#endifstatic int adpt_install_hba(Scsi_Host_Template* sht, struct pci_dev* pDev) { adpt_hba* pHba = NULL; adpt_hba* p = NULL; ulong base_addr0_phys = 0; ulong base_addr1_phys = 0; u32 hba_map0_area_size = 0; u32 hba_map1_area_size = 0; ulong base_addr_virt = 0; ulong msg_addr_virt = 0; int raptorFlag = FALSE; int i; if(pci_enable_device(pDev)) { return -EINVAL; } pci_set_master(pDev); base_addr0_phys = pci_resource_start(pDev,0); hba_map0_area_size = pci_resource_len(pDev,0); // Check if standard PCI card or single BAR Raptor if(pDev->device == PCI_DPT_DEVICE_ID){ if(pDev->subsystem_device >=0xc032 && pDev->subsystem_device <= 0xc03b){ // Raptor card with this device id needs 4M hba_map0_area_size = 0x400000; } else { // Not Raptor - it is a PCI card if(hba_map0_area_size > 0x100000 ){ hba_map0_area_size = 0x100000; } } } else {// Raptor split BAR config // Use BAR1 in this configuration base_addr1_phys = pci_resource_start(pDev,1); hba_map1_area_size = pci_resource_len(pDev,1); raptorFlag = TRUE; } base_addr_virt = (ulong)ioremap(base_addr0_phys,hba_map0_area_size); if(base_addr_virt == 0) { PERROR("dpti: adpt_config_hba: io remap failed\n"); return -EINVAL; } if(raptorFlag == TRUE) { msg_addr_virt = (ulong)ioremap(base_addr1_phys, hba_map1_area_size ); if(msg_addr_virt == 0) { PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); iounmap((void*)base_addr_virt); return -EINVAL; } } else { msg_addr_virt = base_addr_virt; } // Allocate and zero the data structure pHba = kmalloc(sizeof(adpt_hba), GFP_KERNEL); if( pHba == NULL) { if(msg_addr_virt != base_addr_virt){ iounmap((void*)msg_addr_virt); } iounmap((void*)base_addr_virt); return -ENOMEM; } memset(pHba, 0, sizeof(adpt_hba)); down(&adpt_configuration_lock); for(i=0;i<DPTI_MAX_HBA;i++) { if(hbas[i]==NULL) { hbas[i]=pHba; break; } } if(hba_chain != NULL){ for(p = hba_chain; p->next; p = p->next); p->next = pHba; } else { hba_chain = pHba; } pHba->next = NULL; pHba->unit = hba_count; sprintf(pHba->name, "dpti%d", i); hba_count++; up(&adpt_configuration_lock); pHba->pDev = pDev; pHba->base_addr_phys = base_addr0_phys; // Set up the Virtual Base Address of the I2O Device pHba->base_addr_virt = base_addr_virt; pHba->msg_addr_virt = msg_addr_virt; pHba->irq_mask = (ulong)(base_addr_virt+0x30); pHba->post_port = (ulong)(base_addr_virt+0x40); pHba->reply_port = (ulong)(base_addr_virt+0x44); pHba->hrt = NULL; pHba->lct = NULL; pHba->lct_size = 0; pHba->status_block = NULL; pHba->post_count = 0; pHba->state = DPTI_STATE_RESET; pHba->pDev = pDev; pHba->devices = NULL; // Initializing the spinlocks spin_lock_init(&pHba->state_lock); if(raptorFlag == 0){ printk(KERN_INFO"Adaptec I2O RAID controller %d at %lx size=%x irq=%d\n", hba_count-1, base_addr_virt, hba_map0_area_size, pDev->irq); } else { printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d\n",hba_count-1, pDev->irq); printk(KERN_INFO" BAR0 %lx - size= %x\n",base_addr_virt,hba_map0_area_size); printk(KERN_INFO" BAR1 %lx - size= %x\n",msg_addr_virt,hba_map1_area_size); } if (request_irq (pDev->irq, adpt_isr, SA_SHIRQ, pHba->name, pHba)) { printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq); adpt_i2o_delete_hba(pHba); return -EINVAL; } return 0;}static void adpt_i2o_delete_hba(adpt_hba* pHba){ adpt_hba* p1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -