📄 gdth.c
字号:
ha->pccb->CommandIndex = (ulong)i+2; return (i+2); } } return 0;}static void gdth_set_sema0(int hanum){ register gdth_ha_str *ha; TRACE(("gdth_set_sema0() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); if (ha->type == GDT_EISA) outb(1, ha->bmic + SEMA0REG); else if (ha->type == GDT_ISA) writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCI) writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCINEW) outb(1, PTR2USHORT(&ha->plx->sema0_reg)); else if (ha->type == GDT_PCIMPR) writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg); }static void gdth_copy_command(int hanum){ register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; register gdt6m_dpram_str *dp6m_ptr; register gdt6c_dpram_str *dp6c_ptr; gdt6_dpram_str *dp6_ptr; gdt2_dpram_str *dp2_ptr; ushort cp_count,dp_offset,cmd_no; TRACE(("gdth_copy_command() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); cp_count = ha->cmd_len; dp_offset= ha->cmd_offs_dpmem; cmd_no = ha->cmd_cnt; cmd_ptr = ha->pccb; ++ha->cmd_cnt; if (ha->type == GDT_EISA) return; /* no DPMEM, no copy */ /* set cpcount dword aligned */ if (cp_count & 3) cp_count += (4 - (cp_count & 3)); ha->cmd_offs_dpmem += cp_count; /* set offset and service, copy command to DPMEM */ if (ha->type == GDT_ISA) { dp2_ptr = (gdt2_dpram_str *)ha->brd; writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp2_ptr->u.ic.comm_queue[cmd_no].offset); writew((ushort)cmd_ptr->Service, &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCI) { dp6_ptr = (gdt6_dpram_str *)ha->brd; writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6_ptr->u.ic.comm_queue[cmd_no].offset); writew((ushort)cmd_ptr->Service, &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCINEW) { dp6c_ptr = (gdt6c_dpram_str *)ha->brd; writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6c_ptr->u.ic.comm_queue[cmd_no].offset); writew((ushort)cmd_ptr->Service, &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCIMPR) { dp6m_ptr = (gdt6m_dpram_str *)ha->brd; writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6m_ptr->u.ic.comm_queue[cmd_no].offset); writew((ushort)cmd_ptr->Service, &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); }}static void gdth_release_event(int hanum){ register gdth_ha_str *ha;#ifdef GDTH_STATISTICS ulong i,j; for (i=0,j=0; j<GDTH_MAXCMDS; ++j) { if (gdth_cmd_tab[j][hanum].cmnd != UNUSED_CMND) ++i; } if (max_index < i) { max_index = i; TRACE3(("GDT: max_index = %d\n",(ushort)i)); }#endif TRACE(("gdth_release_event() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); if (ha->pccb->OpCode == GDT_INIT) ha->pccb->Service |= 0x80; if (ha->type == GDT_EISA) { outb(ha->pccb->Service, ha->bmic + LDOORREG); if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */ outl((ulong)ha->pccb, ha->bmic + MAILBOXREG); } else if (ha->type == GDT_ISA) writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event); else if (ha->type == GDT_PCI) writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event); else if (ha->type == GDT_PCINEW) outb(1, PTR2USHORT(&ha->plx->ldoor_reg)); else if (ha->type == GDT_PCIMPR) writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);} static int gdth_wait(int hanum,int index,ulong time){ gdth_ha_str *ha; int answer_found = FALSE; TRACE(("gdth_wait() hanum %d index %d time %ld\n",hanum,index,time)); ha = HADATA(gdth_ctr_tab[hanum]); if (index == 0) return 1; /* no wait required */ gdth_from_wait = TRUE; do {#if LINUX_VERSION_CODE >= 0x010346 gdth_interrupt((int)ha->irq,NULL,NULL);#else gdth_interrupt((int)ha->irq,NULL);#endif if (wait_hanum==hanum && wait_index==index) { answer_found = TRUE; break; } gdth_delay(1); } while (--time); gdth_from_wait = FALSE; while (gdth_test_busy(hanum)) gdth_delay(0); return (answer_found);}static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1, ulong p2,ulong p3){ register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; int retries,index; TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode)); ha = HADATA(gdth_ctr_tab[hanum]); cmd_ptr = ha->pccb; memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str)); /* make command */ for (retries = INIT_RETRIES;;) { cmd_ptr->Service = service; cmd_ptr->RequestBuffer = INTERNAL_CMND; if (!(index=gdth_get_cmd_index(hanum))) { TRACE(("GDT: No free command index found\n")); return 0; } gdth_set_sema0(hanum); cmd_ptr->OpCode = opcode; cmd_ptr->BoardNode = LOCALBOARD; if (service == CACHESERVICE) { if (opcode == GDT_IOCTL) { cmd_ptr->u.ioctl.subfunc = p1; cmd_ptr->u.ioctl.channel = p2; cmd_ptr->u.ioctl.param_size = (ushort)p3; cmd_ptr->u.ioctl.p_param = virt_to_bus(ha->pscratch); } else { cmd_ptr->u.cache.DeviceNo = (ushort)p1; cmd_ptr->u.cache.BlockNo = p2; } } else if (service == SCSIRAWSERVICE) { cmd_ptr->u.raw.direction = p1; cmd_ptr->u.raw.bus = (unchar)p2; cmd_ptr->u.raw.target = (unchar)p3; cmd_ptr->u.raw.lun = 0; } ha->cmd_len = sizeof(gdth_cmd_str); ha->cmd_offs_dpmem = 0; ha->cmd_cnt = 0; gdth_copy_command(hanum); gdth_release_event(hanum); gdth_delay(20); if (!gdth_wait(hanum,index,INIT_TIMEOUT)) { printk("GDT: Initialization error (timeout service %d)\n",service); return 0; } if (ha->status != S_BSY || --retries == 0) break; gdth_delay(1); } return (ha->status != S_OK ? 0:1);} /* search for devices */__initfunc (static int gdth_search_drives(int hanum)){ register gdth_ha_str *ha; ushort cdev_cnt,i; unchar b,t,pos_found; ulong drv_cyls, drv_hds, drv_secs; ulong bus_no; gdth_getch_str *chn; gdth_iochan_str *ioc; TRACE(("gdth_search_drives() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); /* initialize controller services, at first: screen service */ if (!gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0)) { printk("GDT: Initialization error screen service (code %d)\n", ha->status); return 0; } TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n")); /* initialize cache service */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) { printk("GDT: Initialization error cache service (code %d)\n", ha->status); return 0; } TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n")); cdev_cnt = (ushort)ha->info; /* mount all cache devices */ gdth_internal_cmd(hanum,CACHESERVICE,GDT_MOUNT,0xffff,1,0); TRACE2(("gdth_search_drives(): mountall CACHESERVICE OK\n")); /* initialize cache service after mountall */ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) { printk("GDT: Initialization error cache service (code %d)\n", ha->status); return 0; } TRACE2(("gdth_search_drives() CACHES. init. after mountall\n")); cdev_cnt = (ushort)ha->info; /* detect number of SCSI buses - try new IOCTL */ ioc = (gdth_iochan_str *)DMADATA(gdth_ctr_tab[hanum]); ioc->version = -1UL; ioc->list_entries = MAXBUS; ioc->first_chan = 0; ioc->last_chan = MAXBUS-1; ioc->list_offset = GDTOFFSOF(gdth_iochan_str, list[0]); if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,GET_IOCHAN_DESC, INVALID_CHANNEL,sizeof(gdth_iochan_str))) { TRACE2(("GET_IOCHAN_DESC supported!\n")); ha->bus_cnt = ioc->chan_count; for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) if (ioc->list[bus_no].proc_id < MAXID) ha->id[bus_no][ioc->list[bus_no].proc_id].type = SIOP_DTYP; } else { /* old method */ chn = (gdth_getch_str *)DMADATA(gdth_ctr_tab[hanum]); 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 SCSI channel count (0x%x)\n", ha->status); return 0; } break; } if (chn->siop_id < MAXID) ha->id[bus_no][chn->siop_id].type = SIOP_DTYP; } ha->bus_cnt = (unchar)bus_no; } TRACE2(("gdth_search_drives() %d SCSI 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 *)DMADATA(gdth_ctr_tab[hanum]))->cpar; TRACE2(("gdth_search_drives() cinfo: vs %lx 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, fill ctr_name[] */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO, INVALID_CHANNEL,sizeof(gdth_binfo_str))) { TRACE2(("BOARD_INFO supported!\n")); strcpy(ha->ctr_name, ((gdth_binfo_str *)DMADATA(gdth_ctr_tab[hanum]))->type_string); } else { strcpy(ha->ctr_name, gdth_ctr_name(hanum)); } TRACE2(("Controller name: %s\n",ha->ctr_name)); /* 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 %ld\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. %ld\n", ha->info)); ha->cache_feat = (ushort)ha->info; } } /* reserve drives for raw service */ for (i = 0; reserve_list[i].hanum != 0xff; ++i) { if (reserve_list[i].hanum < MAXHA && reserve_list[i].hanum == hanum && reserve_list[i].bus < MAXBUS && reserve_list[i].id < MAXID) { TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d\n", reserve_list[i].hanum, reserve_list[i].bus, reserve_list[i].id)); if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0, reserve_list[i].bus, reserve_list[i].id)) { printk("GDT: Error raw service (RESERVE, code %d)\n", ha->status); } } } /* scanning for raw devices */ for (b=0; b<ha->bus_cnt; ++b) { for (t=0; t<MAXID; ++t) { TRACE(("gdth_search_drives() rawd. bus %d id %d\n",b,t)); if (ha->id[b][t].type != SIOP_DTYP && gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INFO,0,b,t)) { ha->id[b][t].type = RAW_DTYP; } } } /* 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)) { /* dynamic relation between host drive number and Bus/ID */ /* search free position */ pos_found = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -