📄 gdth.c
字号:
return 0; } TRACE2(("gdth_search_drives() CACHES. init. after mountall\n")); cdev_cnt = (ushort)ha->info; /* detect number of buses - try new IOCTL */ iocr = (gdth_raw_iochan_str *)ha->pscratch; iocr->hdr.version = 0xffffffff; iocr->hdr.list_entries = MAXBUS; iocr->hdr.first_chan = 0; iocr->hdr.last_chan = MAXBUS-1; iocr->hdr.list_offset = GDTOFFSOF(gdth_raw_iochan_str, list[0]); if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_RAW_DESC, INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) { TRACE2(("IOCHAN_RAW_DESC supported!\n")); ha->bus_cnt = iocr->hdr.chan_count; for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) { if (iocr->list[bus_no].proc_id < MAXID) ha->bus_id[bus_no] = iocr->list[bus_no].proc_id; else ha->bus_id[bus_no] = 0xff; } } else { /* old method */ chn = (gdth_getch_str *)ha->pscratch; for (bus_no = 0; bus_no < MAXBUS; ++bus_no) { chn->channel_no = bus_no; if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, SCSI_CHAN_CNT | L_CTRL_PATTERN, IO_CHANNEL | INVALID_CHANNEL, sizeof(gdth_getch_str))) { if (bus_no == 0) { printk("GDT: Error detecting channel count (0x%x)\n", ha->status); return 0; } break; } if (chn->siop_id < MAXID) ha->bus_id[bus_no] = chn->siop_id; else ha->bus_id[bus_no] = 0xff; } ha->bus_cnt = (unchar)bus_no; } TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt)); /* read cache configuration */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO, INVALID_CHANNEL,sizeof(gdth_cinfo_str))) { printk("GDT: Initialization error cache service (code %d)\n", ha->status); return 0; } ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar; TRACE2(("gdth_search_drives() cinfo: vs %x sta %d str %d dw %d b %d\n", ha->cpar.version,ha->cpar.state,ha->cpar.strategy, ha->cpar.write_back,ha->cpar.block_size)); /* read board info and features */ ha->more_proc = FALSE; if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO, INVALID_CHANNEL,sizeof(gdth_binfo_str))) { memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch, sizeof(gdth_binfo_str)); if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES, INVALID_CHANNEL,sizeof(gdth_bfeat_str))) { TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n")); ha->bfeat = *(gdth_bfeat_str *)ha->pscratch; ha->more_proc = TRUE; } } else { TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n")); strcpy(ha->binfo.type_string, gdth_ctr_name(hanum)); } TRACE2(("Controller name: %s\n",ha->binfo.type_string)); /* read more informations */ if (ha->more_proc) { /* physical drives, channel addresses */ ioc = (gdth_iochan_str *)ha->pscratch; ioc->hdr.version = 0xffffffff; ioc->hdr.list_entries = MAXBUS; ioc->hdr.first_chan = 0; ioc->hdr.last_chan = MAXBUS-1; ioc->hdr.list_offset = GDTOFFSOF(gdth_iochan_str, list[0]); if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_DESC, INVALID_CHANNEL,sizeof(gdth_iochan_str))) { for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) { ha->raw[bus_no].address = ioc->list[bus_no].address; ha->raw[bus_no].local_no = ioc->list[bus_no].local_no; } } else { for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) { ha->raw[bus_no].address = IO_CHANNEL; ha->raw[bus_no].local_no = bus_no; } } for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) { chn = (gdth_getch_str *)ha->pscratch; chn->channel_no = ha->raw[bus_no].local_no; if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, SCSI_CHAN_CNT | L_CTRL_PATTERN, ha->raw[bus_no].address | INVALID_CHANNEL, sizeof(gdth_getch_str))) { ha->raw[bus_no].pdev_cnt = chn->drive_cnt; TRACE2(("Channel %d: %d phys. drives\n", bus_no,chn->drive_cnt)); } if (ha->raw[bus_no].pdev_cnt > 0) { drl = (gdth_drlist_str *)ha->pscratch; drl->sc_no = ha->raw[bus_no].local_no; drl->sc_cnt = ha->raw[bus_no].pdev_cnt; if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, SCSI_DR_LIST | L_CTRL_PATTERN, ha->raw[bus_no].address | INVALID_CHANNEL, sizeof(gdth_drlist_str))) { for (j = 0; j < ha->raw[bus_no].pdev_cnt; ++j) ha->raw[bus_no].id_list[j] = drl->sc_list[j]; } else { ha->raw[bus_no].pdev_cnt = 0; } } } /* logical drives */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_CNT, INVALID_CHANNEL,sizeof(ulong32))) { drv_cnt = *(ulong32 *)ha->pscratch; if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_LIST, INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) { for (j = 0; j < drv_cnt; ++j) { drv_no = ((ulong32 *)ha->pscratch)[j]; if (drv_no < MAX_HDRIVES) { ha->hdr[drv_no].is_logdrv = TRUE; TRACE2(("Drive %d is log. drive\n",drv_no)); } } } if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, ARRAY_DRV_LIST | LA_CTRL_PATTERN, 0, 35 * sizeof(gdth_arraylist_str))) { for (j = 0; j < 35; ++j) { alst = &((gdth_arraylist_str *)ha->pscratch)[j]; ha->hdr[j].is_arraydrv = alst->is_arrayd; ha->hdr[j].is_master = alst->is_master; ha->hdr[j].is_parity = alst->is_parity; ha->hdr[j].is_hotfix = alst->is_hotfix; ha->hdr[j].master_no = alst->cd_handle; } } } } /* initialize raw service */ if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) { printk("GDT: Initialization error raw service (code %d)\n", ha->status); return 0; } TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n")); /* set/get features raw service (scatter/gather) */ ha->raw_feat = 0; if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER, 0,0)) { TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n")); if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n", ha->info)); ha->raw_feat = (ushort)ha->info; } } /* set/get features cache service (equal to raw service) */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_SET_FEAT,0, SCATTER_GATHER,0)) { TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n")); if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n", ha->info)); ha->cache_feat = (ushort)ha->info; } } /* reserve drives for raw service */ if (reserve_mode != 0) { gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE_ALL, reserve_mode == 1 ? 1 : 3, 0, 0); TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n", ha->status)); } for (i = 0; i < MAX_RES_ARGS; i += 4) { if (reserve_list[i] == hanum && reserve_list[i+1] < ha->bus_cnt && reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) { TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n", reserve_list[i], reserve_list[i+1], reserve_list[i+2], reserve_list[i+3])); if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0, reserve_list[i+1], reserve_list[i+2] | (reserve_list[i+3] << 8))) { printk("GDT: Error raw service (RESERVE, code %d)\n", ha->status); } } } /* scanning for cache devices */ for (i=0; i<cdev_cnt && i<MAX_HDRIVES; ++i) { TRACE(("gdth_search_drives() cachedev. %d\n",i)); if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,i,0,0)) { /* static relation between host drive number and Bus/ID */ TRACE(("gdth_search_dr() drive %d mapped to bus/id %d/%d\n", i,ha->bus_cnt,i)); ha->hdr[i].present = TRUE; ha->hdr[i].size = ha->info; /* evaluate mapping (sectors per head, heads per cylinder) */ ha->hdr[i].size &= ~SECS32; if (ha->info2 == 0) { gdth_eval_mapping(ha->hdr[i].size,&drv_cyls,&drv_hds,&drv_secs); } else { drv_hds = ha->info2 & 0xff; drv_secs = (ha->info2 >> 8) & 0xff; drv_cyls = ha->hdr[i].size /drv_hds/drv_secs; } ha->hdr[i].heads = (unchar)drv_hds; ha->hdr[i].secs = (unchar)drv_secs; /* round size */ ha->hdr[i].size = drv_cyls * drv_hds * drv_secs; TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n", i,ha->hdr[i].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 %d\n", i,ha->info)); ha->hdr[i].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)); ha = HADATA(gdth_ctr_tab[hanum]); GDTH_LOCK_HA(ha, flags); scp->SCp.this_residual = (int)priority; b = scp->channel; t = scp->target; if (priority >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) { TRACE2(("gdth_putq(): locked IO -> update_timeout()\n")); scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); } } 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; } GDTH_UNLOCK_HA(ha, 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, firsttime; unchar this_cmd, next_cmd; ulong flags; int cmd_index; TRACE(("gdth_next() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); GDTH_LOCK_HA(ha, flags); ha->cmd_cnt = ha->cmd_offs_dpmem = 0; this_cmd = firsttime = TRUE; next_cmd = gdth_polling ? FALSE: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; b = nscp->channel; t = nscp->target; if (nscp->SCp.this_residual >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) continue; } if (firsttime) { if (gdth_test_busy(hanum)) { /* controller busy ? */ TRACE(("gdth_next() controller %d busy !\n",hanum)); if (!gdth_polling) { GDTH_UNLOCK_HA(ha, flags); return; } while (gdth_test_busy(hanum)) gdth_delay(1); } firsttime = FALSE; } if (nscp->done != gdth_scsi_done) { if (nscp->SCp.phase == -1) { nscp->SCp.phase = SCSIRAWSERVICE; /* default: raw svc. */ if (nscp->cmnd[0] == TEST_UNIT_READY) { TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", b, t, nscp->lun)); /* TEST_UNIT_READY -> set scan mode */ if ((ha->scan_mode & 0x0f) == 0) { if (b == 0 && t == 0 && nscp->lun == 0) { ha->scan_mode |= 1; TRACE2(("Scan mode: 0x%x\n", ha->scan_mode)); } } els
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -