📄 gdth_proc.c
字号:
/* gdth_proc.c * $Id: gdth_proc.c,v 1.33 2001/08/10 07:54:39 achim Exp $ */#include "gdth_ioctl.h"#if LINUX_VERSION_CODE >= 0x020407#include <linux/completion.h>#endifint gdth_proc_info(char *buffer,char **start,off_t offset,int length, int hostno,int inout){ int hanum,busnum,i; TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n", length,hostno,(int)offset,inout)); for (i=0; i<gdth_ctr_vcount; ++i) { if (gdth_ctr_vtab[i]->host_no == hostno) break; } if (i==gdth_ctr_vcount) return(-EINVAL); hanum = NUMDATA(gdth_ctr_vtab[i])->hanum; busnum= NUMDATA(gdth_ctr_vtab[i])->busnum; if (inout) return(gdth_set_info(buffer,length,i,hanum,busnum)); else return(gdth_get_info(buffer,start,offset,length,i,hanum,busnum));}static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum){ int ret_val;#if LINUX_VERSION_CODE >= 0x020322 Scsi_Cmnd *scp; Scsi_Device *sdev;#else Scsi_Cmnd scp; Scsi_Device sdev;#endif gdth_iowr_str *piowr; TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); piowr = (gdth_iowr_str *)buffer;#if LINUX_VERSION_CODE >= 0x020322 sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]); scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) return -ENOMEM; scp->cmd_len = 12; scp->use_sg = 0;#else memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); sdev.host = scp.host = gdth_ctr_vtab[vh]; sdev.id = scp.target = sdev.host->this_id; scp.device = &sdev;#endif if (length >= 4) { if (strncmp(buffer,"gdth",4) == 0) { buffer += 5; length -= 5; ret_val = gdth_set_asc_info( buffer, length, hanum, scp ); } else if (piowr->magic == GDTIOCTL_MAGIC) { ret_val = gdth_set_bin_info( buffer, length, hanum, scp ); } else { printk("GDT: Wrong signature %x (%x required)!\n", piowr->magic, GDTIOCTL_MAGIC); if (piowr->magic > GDTIOCTL_MAGIC) printk("GDT: Please update your driver.\n"); else printk("GDT: Please update your tool.\n"); ret_val = -EINVAL; } } else { ret_val = -EINVAL; }#if LINUX_VERSION_CODE >= 0x020322 scsi_release_command(scp); scsi_free_host_dev(sdev);#endif return ret_val;} #if LINUX_VERSION_CODE >= 0x020322static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)#elsestatic int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)#endif{ int orig_length, drive, wb_mode; int i, found; gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, 12); memset(&gdtcmd, 0, sizeof(gdth_cmd_str)); TRACE2(("gdth_set_asc_info() ha %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); orig_length = length + 5; drive = -1; wb_mode = 0; found = FALSE; if (length >= 5 && strncmp(buffer,"flush",5)==0) { buffer += 6; length -= 6; if (length && *buffer>='0' && *buffer<='9') { drive = (int)(*buffer-'0'); ++buffer; --length; if (length && *buffer>='0' && *buffer<='9') { drive = drive*10 + (int)(*buffer-'0'); ++buffer; --length; } printk("GDT: Flushing host drive %d .. ",drive); } else { printk("GDT: Flushing all host drives .. "); } for (i = 0; i < MAX_HDRIVES; ++i) { if (ha->hdr[i].present) { if (drive != -1 && i != drive) continue; found = TRUE; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_FLUSH; gdtcmd.u.cache.DeviceNo = i; gdtcmd.u.cache.BlockNo = 1;#if LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);#else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);#endif } } if (!found) printk("\nNo host drive found !\n"); else printk("Done.\n"); return(orig_length); } if (length >= 7 && strncmp(buffer,"wbp_off",7)==0) { buffer += 8; length -= 8; printk("GDT: Disabling write back permanently .. "); wb_mode = 1; } else if (length >= 6 && strncmp(buffer,"wbp_on",6)==0) { buffer += 7; length -= 7; printk("GDT: Enabling write back permanently .. "); wb_mode = 2; } else if (length >= 6 && strncmp(buffer,"wb_off",6)==0) { buffer += 7; length -= 7; printk("GDT: Disabling write back commands .. "); if (ha->cache_feat & GDT_WR_THROUGH) { gdth_write_through = TRUE; printk("Done.\n"); } else { printk("Not supported !\n"); } return(orig_length); } else if (length >= 5 && strncmp(buffer,"wb_on",5)==0) { buffer += 6; length -= 6; printk("GDT: Enabling write back commands .. "); gdth_write_through = FALSE; printk("Done.\n"); return(orig_length); } if (wb_mode) { if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE)) return(-EBUSY); pcpar = (gdth_cpar_str *)ha->pscratch; memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) ); gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; gdtcmd.u.ioctl.p_param = virt_to_bus(pcpar); gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str); gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; gdtcmd.u.ioctl.channel = INVALID_CHANNEL; pcpar->write_back = wb_mode==1 ? 0:1;#if LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);#else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);#endif gdth_ioctl_free(hanum, ha->pscratch); printk("Done.\n"); return(orig_length); } printk("GDT: Unknown command: %s Length: %d\n",buffer,length); return(-EINVAL);}#if LINUX_VERSION_CODE >= 0x020322static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)#elsestatic int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)#endif{ unchar i, j; ushort k, hdr_cnt, status; gdth_ha_str *ha; gdth_iowr_str *piowr; gdth_iord_str *piord; gdth_cmd_str *pcmd; gdth_evt_str *pevt; ulong32 *ppadd, add_size, *ppadd2, add_size2, info; ulong flags; gdth_cmd_str gdtcmd; int drv_cyls, drv_hds, drv_secs; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, 12); memset(&gdtcmd, 0, sizeof(gdth_cmd_str)); TRACE2(("gdth_set_bin_info() ha %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); piowr = (gdth_iowr_str *)buffer; piord = NULL; pcmd = NULL; ppadd = ppadd2 = NULL; add_size = add_size2 = 0; if (length < GDTOFFSOF(gdth_iowr_str,iu)) return(-EINVAL); switch (piowr->ioctl) { case GDTIOCTL_GENERAL: if (length < GDTOFFSOF(gdth_iowr_str,iu.general.data[0])) return(-EINVAL); pcmd = (gdth_cmd_str *)piowr->iu.general.command; pcmd->Service = piowr->service; if (pcmd->OpCode == GDT_IOCTL) { ppadd = &pcmd->u.ioctl.p_param; add_size = pcmd->u.ioctl.param_size; } else if (piowr->service == CACHESERVICE) { add_size = pcmd->u.cache.BlockCnt * SECTOR_SIZE; if (ha->cache_feat & SCATTER_GATHER) { ppadd = &pcmd->u.cache.sg_lst[0].sg_ptr; pcmd->u.cache.DestAddr = 0xffffffff; pcmd->u.cache.sg_lst[0].sg_len = add_size; pcmd->u.cache.sg_canz = 1; } else { ppadd = &pcmd->u.cache.DestAddr; pcmd->u.cache.sg_canz = 0; } } else if (piowr->service == SCSIRAWSERVICE) { add_size = pcmd->u.raw.sdlen; add_size2 = pcmd->u.raw.sense_len; if (ha->raw_feat & SCATTER_GATHER) { ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr; pcmd->u.raw.sdata = 0xffffffff; pcmd->u.raw.sg_lst[0].sg_len = add_size; pcmd->u.raw.sg_ranz = 1; } else { ppadd = &pcmd->u.raw.sdata; pcmd->u.raw.sg_ranz = 0; } ppadd2 = &pcmd->u.raw.sense_data; } else { return(-EINVAL); } if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2, TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str) + add_size + add_size2; if (add_size > 0) { memcpy(piord->iu.general.data, piowr->iu.general.data, add_size); *ppadd = virt_to_bus(piord->iu.general.data); } if (add_size2 > 0) { memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2); *ppadd2 = virt_to_bus(piord->iu.general.data+add_size); } /* do IOCTL */#if LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout); piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;#else gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout); piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;#endif break; case GDTIOCTL_DRVERS: if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; piord->iu.drvers.version = (GDTH_VERSION<<8) | GDTH_SUBVERSION; break; case GDTIOCTL_CTRTYPE: if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; if (ha->type == GDT_ISA || ha->type == GDT_EISA) { piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10); } else { if (ha->type != GDT_PCIMPR) { piord->iu.ctrtype.type = (unchar)((ha->stype<<4) + 6); } else { piord->iu.ctrtype.type = (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe); if (ha->stype >= 0x300) piord->iu.ctrtype.ext_type = 0x6000 | ha->subdevice_id; else piord->iu.ctrtype.ext_type = 0x6000 | ha->stype; } piord->iu.ctrtype.device_id = ha->stype; piord->iu.ctrtype.sub_device_id = ha->subdevice_id; } piord->iu.ctrtype.info = ha->brd_phys; piord->iu.ctrtype.oem_id = ha->oem_id; break; case GDTIOCTL_CTRCNT: if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; piord->iu.ctrcnt.count = (ushort)gdth_ctr_count; break; case GDTIOCTL_OSVERS: if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); piord->status = S_OK; piord->iu.osvers.version = (unchar)(LINUX_VERSION_CODE >> 16); piord->iu.osvers.subversion = (unchar)(LINUX_VERSION_CODE >> 8); piord->iu.osvers.revision = (ushort)(LINUX_VERSION_CODE & 0xff); break; case GDTIOCTL_LOCKDRV: if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) { j = piowr->iu.lockdrv.drives[i]; if (j >= MAX_HDRIVES || !ha->hdr[j].present) continue; if (piowr->iu.lockdrv.lock) { GDTH_LOCK_HA(ha, flags); ha->hdr[j].lock = 1; GDTH_UNLOCK_HA(ha, flags); gdth_wait_completion( hanum, ha->bus_cnt, j ); gdth_stop_timeout( hanum, ha->bus_cnt, j ); } else { GDTH_LOCK_HA(ha, flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -