📄 gdth.c
字号:
for (b=0,t=0; b<ha->bus_cnt; ++b) { for (t=0; t<MAXID; ++t) { if (ha->id[b][t].type == EMPTY_DTYP) { pos_found = TRUE; break; } } if (pos_found) break; } TRACE(("gdth_search_dr() drive %d free pos at bus/id %d/%d\n", i,b,t)); ha->id[b][t].type = CACHE_DTYP; ha->id[b][t].devtype = 0; ha->id[b][t].size = ha->info; ha->id[b][t].hostdrive = i; /* evaluate mapping (sectors per head, heads per cylinder) */ ha->id[b][t].size &= ~SECS32; if (ha->info2 == 0) { drv_cyls = ha->id[b][t].size /HEADS/SECS; if (drv_cyls <= MAXCYLS) { drv_hds = HEADS; drv_secs= SECS; } else { /* too high for 64*32 */ drv_cyls = ha->id[b][t].size /MEDHEADS/MEDSECS; if (drv_cyls <= MAXCYLS) { drv_hds = MEDHEADS; drv_secs= MEDSECS; } else { /* too high for 127*63 */ drv_cyls = ha->id[b][t].size /BIGHEADS/BIGSECS; drv_hds = BIGHEADS; drv_secs= BIGSECS; } } } else { drv_hds = ha->info2 & 0xff; drv_secs = (ha->info2 >> 8) & 0xff; drv_cyls = ha->id[b][t].size /drv_hds/drv_secs; } ha->id[b][t].heads = (unchar)drv_hds; ha->id[b][t].secs = (unchar)drv_secs; /* round size */ ha->id[b][t].size = drv_cyls * drv_hds * drv_secs; TRACE2(("gdth_search_dr() cdr. %d size %ld hds %ld scs %ld\n", i,ha->id[b][t].size,drv_hds,drv_secs)); /* get informations about device */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,i, 0,0)) { TRACE(("gdth_search_dr() cache drive %d devtype %ld\n", i,ha->info)); ha->id[b][t].devtype = (ushort)ha->info; } } } TRACE(("gdth_search_drives() OK\n")); return 1;}/* command queueing/sending functions */static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority){ register gdth_ha_str *ha; register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; ulong flags; unchar b, t; TRACE(("gdth_putq() priority %d\n",priority)); save_flags(flags); cli(); ha = HADATA(gdth_ctr_tab[hanum]); scp->SCp.this_residual = (int)priority; gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);#if LINUX_VERSION_CODE >= 0x020000 b = scp->channel;#else b = NUMDATA(nscp->host)->busnum;#endif t = scp->target;#if LINUX_VERSION_CODE >= 0x010300 if (priority >= DEFAULT_PRI && ha->id[b][t].lock) { TRACE2(("gdth_putq(): locked IO -> update_timeout()\n")); scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); }#endif if (ha->req_first==NULL) { ha->req_first = scp; /* queue was empty */ scp->SCp.ptr = NULL; } else { /* queue not empty */ pscp = ha->req_first; nscp = (Scsi_Cmnd *)pscp->SCp.ptr; /* priority: 0-highest,..,0xff-lowest */ while (nscp && (unchar)nscp->SCp.this_residual <= priority) { pscp = nscp; nscp = (Scsi_Cmnd *)pscp->SCp.ptr; } pscp->SCp.ptr = (char *)scp; scp->SCp.ptr = (char *)nscp; } restore_flags(flags);#ifdef GDTH_STATISTICS flags = 0; for (nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr) ++flags; if (max_rq < flags) { max_rq = flags; TRACE3(("GDT: max_rq = %d\n",(ushort)max_rq)); }#endif}static void gdth_next(int hanum){ register gdth_ha_str *ha; register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; unchar b, t, next_cmd, firsttime; ushort hdrive; ulong flags; int cmd_index; TRACE(("gdth_next() hanum %d\n",hanum)); save_flags(flags); cli(); ha = HADATA(gdth_ctr_tab[hanum]); ha->cmd_cnt = ha->cmd_offs_dpmem = 0; next_cmd = firsttime = TRUE; cmd_index = 0; for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) pscp = (Scsi_Cmnd *)pscp->SCp.ptr;#if LINUX_VERSION_CODE >= 0x020000 b = nscp->channel;#else b = NUMDATA(nscp->host)->busnum;#endif t = nscp->target; if (nscp->SCp.this_residual < DEFAULT_PRI || !ha->id[b][t].lock) { if (firsttime) { if (gdth_test_busy(hanum)) { /* controller busy ? */ TRACE(("gdth_next() controller %d busy !\n",hanum)); if (!gdth_polling) { restore_flags(flags); return; } while (gdth_test_busy(hanum)) gdth_delay(1); } firsttime = FALSE; }#if LINUX_VERSION_CODE >= 0x010300 if (nscp->done == gdth_scsi_done) { if (!(cmd_index=gdth_special_cmd(hanum,nscp,b))) next_cmd = FALSE; } else#endif if (ha->id[b][t].type != CACHE_DTYP) { if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b))) next_cmd = FALSE; } else { hdrive = ha->id[b][t].hostdrive; switch (nscp->cmnd[0]) { case TEST_UNIT_READY: case INQUIRY: case REQUEST_SENSE: case READ_CAPACITY: case VERIFY: case START_STOP: case MODE_SENSE: TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); gdth_internal_cache_cmd(hanum,nscp,b,&flags); break; case ALLOW_MEDIUM_REMOVAL: TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); if ( (nscp->cmnd[4]&1) && !(ha->id[b][t].devtype&1) ) { TRACE2(("Prevent r. nonremov. drive->do nothing\n")); nscp->result = DID_OK << 16; restore_flags( flags ); if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else nscp->scsi_done(nscp); save_flags( flags ); cli(); } else { nscp->cmnd[3] = (ha->id[b][t].devtype&1) ? 1:0; TRACE2(("Prevent/allow r. %d rem. drive %d\n", nscp->cmnd[4],nscp->cmnd[3])); if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive))) next_cmd = FALSE; } break; case READ_6: case WRITE_6: case READ_10: case WRITE_10: if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive))) next_cmd = FALSE; break; default: TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); printk("GDT: Unknown SCSI command 0x%x to cache service !\n", nscp->cmnd[0]); nscp->result = DID_ABORT << 16; restore_flags( flags ); if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else nscp->scsi_done(nscp); save_flags( flags ); cli(); break; } } if (!next_cmd) break; if (nscp == ha->req_first) ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr; else pscp->SCp.ptr = nscp->SCp.ptr; if (gdth_polling) break; } } if (ha->cmd_cnt > 0) { gdth_release_event(hanum); } restore_flags(flags); if (gdth_polling && ha->cmd_cnt > 0) { if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) printk("GDT: Controller %d: Command %d timed out !\n", hanum,cmd_index); }} static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count){ ushort cpcount,i; ushort cpsum,cpnow; struct scatterlist *sl; cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; if (scp->use_sg) { sl = (struct scatterlist *)scp->request_buffer; for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) { cpnow = (ushort)sl->length; TRACE(("copy_internal() now %d sum %d count %d %d\n", cpnow,cpsum,cpcount,(ushort)scp->bufflen)); if (cpsum+cpnow > cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; memcpy((char*)sl->address,buffer,cpnow); if (cpsum == cpcount) break; buffer += cpnow; } } else { TRACE(("copy_internal() count %d\n",cpcount)); memcpy((char*)scp->request_buffer,buffer,cpcount); }}static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp, unchar b,ulong *flags){ register gdth_ha_str *ha; ushort hdrive; unchar t; gdth_inq_data inq; gdth_rdcap_data rdc; gdth_sense_data sd; gdth_modep_data mpd; ha = HADATA(gdth_ctr_tab[hanum]); t = scp->target; hdrive = ha->id[b][t].hostdrive; TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n", scp->cmnd[0],hdrive)); if (scp->lun !=0) scp->result = DID_BAD_TARGET << 16; else { switch (scp->cmnd[0]) { case TEST_UNIT_READY: case VERIFY: case START_STOP: TRACE2(("Test/Verify/Start hdrive %d\n",hdrive)); break; case INQUIRY: TRACE2(("Inquiry hdrive %d devtype %d\n", hdrive,ha->id[b][t].devtype)); inq.type_qual = (ha->id[b][t].devtype&4) ? TYPE_ROM:TYPE_DISK; /* you can here set all disks to removable, if you want to do a flush using the ALLOW_MEDIUM_REMOVAL command */ inq.modif_rmb = ha->id[b][t].devtype&1 ? 0x80:0x00; inq.version = 2; inq.resp_aenc = 2; inq.add_length= 32; strcpy(inq.vendor,"ICP "); sprintf(inq.product,"Host Drive #%02d",hdrive); strcpy(inq.revision," "); gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data)); break; case REQUEST_SENSE: TRACE2(("Request sense hdrive %d\n",hdrive)); sd.errorcode = 0x70; sd.segno = 0x00; sd.key = NO_SENSE; sd.info = 0; sd.add_length= 0; gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data)); break; case MODE_SENSE: TRACE2(("Mode sense hdrive %d\n",hdrive)); memset((char*)&mpd,0,sizeof(gdth_modep_data)); mpd.hd.data_length = sizeof(gdth_modep_data); mpd.hd.dev_par = (ha->id[b][t].devtype&2) ? 0x80:0; mpd.hd.bd_length = sizeof(mpd.bd); mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data)); break; case READ_CAPACITY: TRACE2(("Read capacity hdrive %d\n",hdrive)); rdc.last_block_no = ntohl(ha->id[b][t].size-1); rdc.block_length = ntohl(SECTOR_SIZE); gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data)); break; default: TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0])); break; } scp->result = DID_OK << 16; } restore_flags(*flags); if (!scp->SCp.have_data_in) scp->SCp.have_data_in++; else scp->scsi_done(scp); save_flags(*flags); cli(); return 1;} static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive){ register gdth_ha_str *ha; register gdth_cmd_str *cmdp; struct scatterlist *sl; ushort i; int cmd_in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -