📄 i2o_scsi.c
字号:
if(sg_chain_pool!=NULL) { kfree(sg_chain_pool); sg_chain_pool = NULL; } flush_pending(); del_timer(&retry_timer); i2o_remove_handler(&i2o_scsi_handler); } return count;}int i2o_scsi_release(struct Scsi_Host *host){ if(--i2o_scsi_hosts==0) { if(sg_chain_pool!=NULL) { kfree(sg_chain_pool); sg_chain_pool = NULL; } flush_pending(); del_timer(&retry_timer); i2o_remove_handler(&i2o_scsi_handler); } return 0;}const char *i2o_scsi_info(struct Scsi_Host *SChost){ struct i2o_scsi_host *hostdata; hostdata = (struct i2o_scsi_host *)SChost->hostdata; return(&hostdata->controller->name[0]);}/* * From the wd93 driver: * Returns true if there will be a DATA_OUT phase with this command, * false otherwise. * (Thanks to Joerg Dorchain for the research and suggestion.) * */static int is_dir_out(Scsi_Cmnd *cmd){ switch (cmd->cmnd[0]) { case WRITE_6: case WRITE_10: case WRITE_12: case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: case WRITE_VERIFY: case WRITE_VERIFY_12: case COMPARE: case COPY: case COPY_VERIFY: case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: case 0xea: return 1; default: return 0; }}int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)){ int i; int tid; struct i2o_controller *c; Scsi_Cmnd *current_command; struct Scsi_Host *host; struct i2o_scsi_host *hostdata; u32 *msg, *mptr; u32 m; u32 *lenptr; int direction; int scsidir; u32 len; u32 reqlen; u32 tag; static int max_qd = 1; /* * Do the incoming paperwork */ host = SCpnt->host; hostdata = (struct i2o_scsi_host *)host->hostdata; c = hostdata->controller; prefetch(c); prefetchw(&queue_depth); SCpnt->scsi_done = done; if(SCpnt->target > 15) { printk(KERN_ERR "i2o_scsi: Wild target %d.\n", SCpnt->target); return -1; } tid = hostdata->task[SCpnt->target][SCpnt->lun]; dprintk(("qcmd: Tid = %d\n", tid)); current_command = SCpnt; /* set current command */ current_command->scsi_done = done; /* set ptr to done function */ /* We don't have such a device. Pretend we did the command and that selection timed out */ if(tid == -1) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } dprintk(("Real scsi messages.\n")); /* * Obtain an I2O message. Right now we _have_ to obtain one * until the scsi layer stuff is cleaned up. */ do { mb(); m = I2O_POST_READ32(c); } while(m==0xFFFFFFFF); msg = (u32 *)(c->mem_offset + m); /* * Put together a scsi execscb message */ len = SCpnt->request_bufflen; direction = 0x00000000; // SGL IN (osm<--iop) /* * The scsi layer should be handling this stuff */ scsidir = 0x00000000; // DATA NO XFER if(len) { if(is_dir_out(SCpnt)) { direction=0x04000000; // SGL OUT (osm-->iop) scsidir =0x80000000; // DATA OUT (iop-->dev) } else { scsidir =0x40000000; // DATA IN (iop<--dev) } } __raw_writel(I2O_CMD_SCSI_EXEC<<24|HOST_TID<<12|tid, &msg[1]); __raw_writel(scsi_context, &msg[2]); /* So the I2O layer passes to us */ /* Sorry 64bit folks. FIXME */ __raw_writel((u32)SCpnt, &msg[3]); /* We want the SCSI control block back */ /* LSI_920_PCI_QUIRK * * Intermittant observations of msg frame word data corruption * observed on msg[4] after: * WRITE, READ-MODIFY-WRITE * operations. 19990606 -sralston * * (Hence we build this word via tag. Its good practice anyway * we don't want fetches over PCI needlessly) */ tag=0; /* * Attach tags to the devices */ if(SCpnt->device->tagged_supported) { /* * Some drives are too stupid to handle fairness issues * with tagged queueing. We throw in the odd ordered * tag to stop them starving themselves. */ if((jiffies - hostdata->tagclock[SCpnt->target][SCpnt->lun]) > (5*HZ)) { tag=0x01800000; /* ORDERED! */ hostdata->tagclock[SCpnt->target][SCpnt->lun]=jiffies; } else { /* Hmmm... I always see value of 0 here, * of which {HEAD_OF, ORDERED, SIMPLE} are NOT! -sralston */ if(SCpnt->tag == HEAD_OF_QUEUE_TAG) tag=0x01000000; else if(SCpnt->tag == ORDERED_QUEUE_TAG) tag=0x01800000; } } /* Direction, disconnect ok, tag, CDBLen */ __raw_writel(scsidir|0x20000000|SCpnt->cmd_len|tag, &msg[4]); mptr=msg+5; /* * Write SCSI command into the message - always 16 byte block */ memcpy_toio(mptr, SCpnt->cmnd, 16); mptr+=4; lenptr=mptr++; /* Remember me - fill in when we know */ reqlen = 12; // SINGLE SGE /* * Now fill in the SGList and command * * FIXME: we need to set the sglist limits according to the * message size of the I2O controller. We might only have room * for 6 or so worst case */ if(SCpnt->use_sg) { struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer; int chain = 0; len = 0; if((sg_max_frags > 11) && (SCpnt->use_sg > 11)) { chain = 1; /* * Need to chain! */ __raw_writel(direction|0xB0000000|(SCpnt->use_sg*2*4), mptr++); __raw_writel(virt_to_bus(sg_chain_pool + sg_chain_tag), mptr); mptr = (u32*)(sg_chain_pool + sg_chain_tag); if (SCpnt->use_sg > max_sg_len) { max_sg_len = SCpnt->use_sg; printk("i2o_scsi: Chain SG! SCpnt=%p, SG_FragCnt=%d, SG_idx=%d\n", SCpnt, SCpnt->use_sg, sg_chain_tag); } if ( ++sg_chain_tag == SG_MAX_BUFS ) sg_chain_tag = 0; for(i = 0 ; i < SCpnt->use_sg; i++) { *mptr++=direction|0x10000000|sg->length; len+=sg->length; *mptr++=virt_to_bus(sg->address); sg++; } mptr[-2]=direction|0xD0000000|(sg-1)->length; } else { for(i = 0 ; i < SCpnt->use_sg; i++) { __raw_writel(direction|0x10000000|sg->length, mptr++); len+=sg->length; __raw_writel(virt_to_bus(sg->address), mptr++); sg++; } /* Make this an end of list. Again evade the 920 bug and unwanted PCI read traffic */ __raw_writel(direction|0xD0000000|(sg-1)->length, &mptr[-2]); } if(!chain) reqlen = mptr - msg; __raw_writel(len, lenptr); if(len != SCpnt->underflow) printk("Cmd len %08X Cmd underflow %08X\n", len, SCpnt->underflow); } else { dprintk(("non sg for %p, %d\n", SCpnt->request_buffer, SCpnt->request_bufflen)); __raw_writel(len = SCpnt->request_bufflen, lenptr); if(len == 0) { reqlen = 9; } else { __raw_writel(0xD0000000|direction|SCpnt->request_bufflen, mptr++); __raw_writel(virt_to_bus(SCpnt->request_buffer), mptr++); } } /* * Stick the headers on */ __raw_writel(reqlen<<16 | SGL_OFFSET_10, msg); /* Queue the message */ i2o_post_message(c,m); atomic_inc(&queue_depth); if(atomic_read(&queue_depth)> max_qd) { max_qd=atomic_read(&queue_depth); printk("Queue depth now %d.\n", max_qd); } mb(); dprintk(("Issued %ld\n", current_command->serial_number)); return 0;}static void internal_done(Scsi_Cmnd * SCpnt){ SCpnt->SCp.Status++;}int i2o_scsi_command(Scsi_Cmnd * SCpnt){ i2o_scsi_queuecommand(SCpnt, internal_done); SCpnt->SCp.Status = 0; while (!SCpnt->SCp.Status) barrier(); return SCpnt->result;}int i2o_scsi_abort(Scsi_Cmnd * SCpnt){ struct i2o_controller *c; struct Scsi_Host *host; struct i2o_scsi_host *hostdata; u32 *msg; u32 m; int tid; printk("i2o_scsi: Aborting command block.\n"); host = SCpnt->host; hostdata = (struct i2o_scsi_host *)host->hostdata; tid = hostdata->task[SCpnt->target][SCpnt->lun]; if(tid==-1) { printk(KERN_ERR "impossible command to abort.\n"); return SCSI_ABORT_NOT_RUNNING; } c = hostdata->controller; /* * Obtain an I2O message. Right now we _have_ to obtain one * until the scsi layer stuff is cleaned up. */ do { mb(); m = I2O_POST_READ32(c); } while(m==0xFFFFFFFF); msg = (u32 *)(c->mem_offset + m); __raw_writel(FIVE_WORD_MSG_SIZE, &msg[0]); __raw_writel(I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|tid, &msg[1]); __raw_writel(scsi_context, &msg[2]); __raw_writel(0, &msg[3]); /* Not needed for an abort */ __raw_writel((u32)SCpnt, &msg[4]); wmb(); i2o_post_message(c,m); wmb(); return SCSI_ABORT_PENDING;}int i2o_scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags){ int tid; struct i2o_controller *c; struct Scsi_Host *host; struct i2o_scsi_host *hostdata; u32 m; u32 *msg; /* * Find the TID for the bus */ printk("i2o_scsi: Attempting to reset the bus.\n"); host = SCpnt->host; hostdata = (struct i2o_scsi_host *)host->hostdata; tid = hostdata->bus_task; c = hostdata->controller; /* * Now send a SCSI reset request. Any remaining commands * will be aborted by the IOP. We need to catch the reply * possibly ? */ m = I2O_POST_READ32(c); /* * No free messages, try again next time - no big deal */ if(m == 0xFFFFFFFF) return SCSI_RESET_PUNT; msg = (u32 *)(c->mem_offset + m); __raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]); __raw_writel(I2O_CMD_SCSI_BUSRESET<<24|HOST_TID<<12|tid, &msg[1]); __raw_writel(scsi_context|0x80000000, &msg[2]); /* We use the top bit to split controller and unit transactions */ /* Now store unit,tid so we can tie the completion back to a specific device */ __raw_writel(c->unit << 16 | tid, &msg[3]); wmb(); i2o_post_message(c,m); return SCSI_RESET_PENDING;}/* * This is anyones guess quite frankly. */ int i2o_scsi_bios_param(Disk * disk, kdev_t dev, int *ip){ int size; size = disk->capacity; ip[0] = 64; /* heads */ ip[1] = 32; /* sectors */ if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */ ip[0] = 255; /* heads */ ip[1] = 63; /* sectors */ ip[2] = size / (255 * 63); /* cylinders */ } return 0;}MODULE_AUTHOR("Red Hat Software");MODULE_LICENSE("GPL");static Scsi_Host_Template driver_template = I2OSCSI;#include "../../scsi/scsi_module.c"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -