📄 libscsi.c
字号:
#include "libscsi.h"/* ioctl */struct megascsi_adapter *mega_scsi_adapter;unsigned char megascsi_adapt_no;int megascsi_ioctl_initialized = 0;char dv_xname[] = "PERCSCSI"; unsigned int USCSICMD = 0x80; voidmegascsi_copyhds(scsi_adapter, sizes, props, stats) struct megascsi_adapter *scsi_adapter; const unsigned int *sizes; const unsigned char *props, *stats;{ int i; for (i = 0; i < scsi_adapter->adapter_nunits; i++) { scsi_adapter->adapter_hdr[i].hd_present = 1; scsi_adapter->adapter_hdr[i].hd_is_logdrv = 1; scsi_adapter->adapter_hdr[i].hd_size = letoh32(sizes[i]); scsi_adapter->adapter_hdr[i].hd_prop = props[i]; scsi_adapter->adapter_hdr[i].hd_stat = stats[i]; if (scsi_adapter->adapter_hdr[i].hd_size > 0x200000) { scsi_adapter->adapter_hdr[i].hd_heads = 255; scsi_adapter->adapter_hdr[i].hd_secs = 63; } else { scsi_adapter->adapter_hdr[i].hd_heads = 64; scsi_adapter->adapter_hdr[i].hd_secs = 32; } }}intmegascsi_ioctl_init(){ int error = 0; struct utsname uname_buf; char delimiters[] = ".-"; char *token, cp[128], *tail; if ( uname(&uname_buf) )return EINVAL; strncpy(cp, uname_buf.release, 128); token = strtok(cp, delimiters); if ( strtol(token, &tail, 0) != 2 ) return EINVAL; token = strtok(NULL, delimiters); if ( strtol(token, &tail, 0) == 4 ) USCSICMD = 0xe0; /* kernel 2.4.x */ else if (strtol(token, &tail, 0) == 6 ) USCSICMD = 0x80; /* kernel 2.6.x */ else { printf("This program not supported on %s\n", uname_buf.release); return EINVAL; } if (!megascsi_ioctl_initialized) { /* Initialize mega_scsi_adapter structure */ mega_scsi_adapter = malloc(sizeof(struct megascsi_adapter)); if ( mega_scsi_adapter == NULL ) { printf("MEGA Init Failture: No memory allocation\n"); return EINVAL; } memset(mega_scsi_adapter, sizeof(struct megascsi_adapter), 0); mega_scsi_adapter->adapter_handle = open("/dev/megadev0", O_RDONLY); if (mega_scsi_adapter->adapter_handle == (uint)-1) { printf("MEGA Init failture: Can not open device file /dev/megadev0\n"); return EINVAL; } megascsi_adapt_no = 0; mega_scsi_adapter->adapter_adapt_no = megascsi_adapt_no; megascsi_ioctl_initialized = 1; } megascsi_query_adapt(mega_scsi_adapter); return (error); }intmegascsi_query_adapt(scsi_adapter)struct megascsi_adapter *scsi_adapter;{ int error = 0, i; char *p=NULL; struct megascsi_fc_einquiry *einq; struct megascsi_fc_prodinfo *pi; if ( !scsi_adapter ) return EINVAL; /* try FC inquiry first */ p = malloc(sizeof(struct megascsi_fc_einquiry)+sizeof(struct megascsi_fc_prodinfo)); if (!p) { printf("%s: No memory for adapter information\n",scsi_adapter->adapter_dev.dv_xname); return EINVAL; } einq = (struct megascsi_fc_einquiry *)p; pi = (struct megascsi_fc_prodinfo *)(p + sizeof(struct megascsi_fc_einquiry)); memset(einq, 0, sizeof(struct megascsi_fc_einquiry)); memset(pi, 0, sizeof(struct megascsi_fc_prodinfo)); if (megascsi_mgmt(scsi_adapter, MEGASCSI_FCOP, MEGASCSI_FC_EINQ3_SOLICITED_FULL, 0, 0, sizeof (struct megascsi_fc_einquiry), einq)==0) { scsi_adapter->adapter_nunits = einq->ain_nlogdrv; megascsi_copyhds(scsi_adapter, einq->ain_ldsize, einq->ain_ldprop, einq->ain_ldstat); if (megascsi_mgmt(scsi_adapter, MEGASCSI_FCOP, MEGASCSI_FC_PRODINF, 0, 0, sizeof (struct megascsi_fc_prodinfo), pi)==0) { scsi_adapter->adapter_maxunits = MEGASCSI_BIG_MAX_LDRIVES; memcpy(scsi_adapter->adapter_fwver, pi->api_fwver, 16); scsi_adapter->adapter_fwver[15] = '\0'; memcpy(scsi_adapter->adapter_biosver, pi->api_biosver, 16); scsi_adapter->adapter_biosver[15] = '\0'; scsi_adapter->adapter_channels = pi->api_channels; scsi_adapter->adapter_targets = pi->api_fcloops; scsi_adapter->adapter_memory = letoh16(pi->api_ramsize); scsi_adapter->adapter_maxcmds = pi->api_maxcmd;// p = "FC loop"; } else { error = EINVAL; goto bail2; } if (scsi_adapter->adapter_maxunits == 0) { struct megascsi_inquiry *inq = (struct megascsi_inquiry *)einq; if (megascsi_mgmt(scsi_adapter, MEGASCSI_EINQUIRY, 0, 0, 0, sizeof(struct megascsi_inquiry) , inq)!=0){ if (megascsi_mgmt(scsi_adapter, MEGASCSI_INQUIRY, 0, 0, 0, sizeof(struct megascsi_inquiry), inq)!=0){ error = EINVAL; goto bail2; } } scsi_adapter->adapter_maxunits = MEGASCSI_MAX_LDRIVES; scsi_adapter->adapter_nunits = inq->ain_nlogdrv; megascsi_copyhds(scsi_adapter, inq->ain_ldsize, inq->ain_ldprop, inq->ain_ldstat); memcpy (scsi_adapter->adapter_fwver, inq->ain_fwver, 4); scsi_adapter->adapter_fwver[4] = '\0'; memcpy (scsi_adapter->adapter_biosver, inq->ain_biosver, 4); scsi_adapter->adapter_biosver[4] = '\0'; scsi_adapter->adapter_channels = inq->ain_channels; scsi_adapter->adapter_targets = inq->ain_targets; scsi_adapter->adapter_memory = inq->ain_ramsize; scsi_adapter->adapter_maxcmds = inq->ain_maxcmd;// p = "target"; } } else { error = EINVAL; goto bail2; }/* #ifdef MEGASCSI_DEBUG printf(": FW %s, BIOS v%s, %dMB RAM\n" "%s: %d channels, %d %ss, %d logical drives, " "openings %d, max commands %d, quirks: %04x\n", scsi_adapter->adapter_fwver, scsi_adapter->adapter_biosver, scsi_adapter->adapter_memory, scsi_adapter->adapter_dev.dv_xname, scsi_adapter->adapter_channels, scsi_adapter->adapter_targets, p, scsi_adapter->adapter_nunits, scsi_adapter->adapter_link.openings, scsi_adapter->adapter_maxcmds, scsi_adapter->adapter_flags);#else printf(": FW %s, BIOS v%s, %dMB RAM\n" "%s: %d channels, %d %ss, %d logical drives\n", scsi_adapter->adapter_fwver, scsi_adapter->adapter_biosver, scsi_adapter->adapter_memory, scsi_adapter->adapter_dev.dv_xname, scsi_adapter->adapter_channels, scsi_adapter->adapter_targets, p, scsi_adapter->adapter_nunits);#endif MEGASCSI_DEBUG */ memcpy(scsi_adapter->adapter_dev.dv_xname, dv_xname, 16); scsi_adapter->adapter_flags |= MEGASCSI_QUARTZ; for(i = 0; i < ((scsi_adapter->adapter_flags & MEGASCSI_QUARTZ) ? MEGASCSI_BIG_MAX_PDRIVES : MEGASCSI_MAX_PDRIVES); i++) { memcpy(scsi_adapter->adapter_hdr[i].dev, scsi_adapter->adapter_dev.dv_xname, 16); } for(i = 0; i < MEGASCSI_MAX_CHANNEL; i++) { memcpy(scsi_adapter->adapter_rawadapters[i].adapter_procdev, scsi_adapter->adapter_dev.dv_xname, 16); }bail2: if (p) free(p); return (error);}intmegascsi_ioctl_end(){ int error = 0; if (mega_scsi_adapter) { if (mega_scsi_adapter->adapter_handle) close(mega_scsi_adapter->adapter_handle); free(mega_scsi_adapter); megascsi_ioctl_initialized = 0; } else error = EINVAL; return error;}int megascsi_ioctl_sel_adapt(new_adapt_no) unsigned char new_adapt_no;{ int old_adapt_no = 0; if (!mega_scsi_adapter) return EINVAL; old_adapt_no = mega_scsi_adapter->adapter_adapt_no; if ( old_adapt_no != new_adapt_no) { mega_scsi_adapter->adapter_adapt_no = new_adapt_no; megascsi_query_adapt(mega_scsi_adapter); } megascsi_adapt_no = mega_scsi_adapter->adapter_adapt_no; return old_adapt_no;}intmegascsi_ioctl(cmd, addr)/* struct megascsi_adapter *scsi_adapter;*/ unsigned int cmd; char * addr;{// struct megascsi_adapter *scsi_adapter = (struct megascsi_adapter *)dev; int error = 0; switch (cmd) { case MIOC_INQ: error = megascsi_ioctl_inq(mega_scsi_adapter, (struct mioc_inq *)addr); break; case MIOC_VOL: error = megascsi_ioctl_vol(mega_scsi_adapter, (struct mioc_vol *)addr); break; case MIOC_DISK: error = megascsi_ioctl_disk(mega_scsi_adapter, (struct mioc_disk *)addr); break; default: error = EINVAL; } return (error);}intmegascsi_drv_inq(scsi_adapter, ch, tg, page, inqbuf) struct megascsi_adapter *scsi_adapter; unsigned char ch; unsigned char tg; unsigned char page; void *inqbuf;{ mimd_t *mimd; struct megascsi_iocmd *cmd; struct megascsi_passthrough *ps; struct scsi_inquiry_data *pp; void *idata; int error = 0; if (!(idata = malloc(sizeof(mimd_t) + sizeof(struct scsi_inquiry_data)))) { return (ENOMEM); } mimd = (mimd_t *) idata; memset(mimd, 0, sizeof *mimd); ps = (struct megascsi_passthrough *)&(mimd->pthru); pp = idata + sizeof *mimd; memset(pp, 0, sizeof *pp); mimd->ui.fcs.opcode = 0x80; mimd->ui.fcs.adapno = 0x6d00 + scsi_adapter->adapter_adapt_no; mimd->outlen = sizeof(struct scsi_inquiry_data); mimd->data = (char *)htole(pp); cmd = (struct megascsi_iocmd *)&(mimd->mbox); cmd->acc_cmd = MEGASCSI_PASSTHRU; cmd->acc_passthru.apt_data = (unsigned int)htole(pp); ps->apt_channel = ch; ps->apt_target = tg; ps->apt_ncdb = sizeof(struct scsi_inquiry); ps->apt_nsense = sizeof(struct scsi_sense_data); ps->apt_cdb[0] = INQUIRY; ps->apt_cdb[1] = 0; ps->apt_cdb[2] = 0; ps->apt_cdb[3] = 0; ps->apt_cdb[4] = sizeof(struct scsi_inquiry_data); /* INQUIRY length */ ps->apt_cdb[5] = 0; if (page != 0) { ps->apt_cdb[1] = SI_EVPD; ps->apt_cdb[2] = page; } ps->apt_data = (unsigned int)htole(pp); ps->apt_datalen = sizeof(struct scsi_inquiry_data); if (ioctl(scsi_adapter->adapter_handle, USCSICMD, mimd) == 0) { if (ps->apt_scsistat == 0x00) { memcpy(inqbuf, pp, sizeof(struct scsi_inquiry_data)); if (pp->device != T_DIRECT) error = EINVAL; goto bail; } error = EINVAL; } else error = EINVAL;bail: free(idata); return (error);}intmegascsi_mgmt(scsi_adapter, opcode, par1, par2, par3, size, buffer) struct megascsi_adapter *scsi_adapter; unsigned char opcode; unsigned char par1; unsigned char par2; unsigned char par3; size_t size; void *buffer;{ mimd_t *mimd; struct megascsi_iocmd *cmd; void *idata; void *pa; int error = 0; if (!buffer) return (ENOMEM); if (!(idata = malloc(sizeof(mimd_t)))) { return (ENOMEM); } mimd = (mimd_t *)idata; memset(mimd, 0, sizeof(mimd_t)); pa = buffer; mimd->ui.fcs.opcode = 0x80; mimd->ui.fcs.adapno = 0x6d00 + scsi_adapter->adapter_adapt_no; mimd->outlen = size; mimd->data = htole(pa); cmd = (struct megascsi_iocmd *)&(mimd->mbox); cmd->acc_cmd = opcode; /* * some commands require data to be written to idata before sending * command to fw */ switch (opcode) { case MEGASCSI_SPEAKER: *((char *)pa) = par1; break; default: cmd->acc_io.aio_channel = par1; cmd->acc_io.aio_param = par2; cmd->acc_io.aio_pad[0] = par3; }; cmd->acc_io.aio_data = (unsigned int)htole(pa); if (ioctl(scsi_adapter->adapter_handle, USCSICMD, mimd) == 0) { /* XXX how do commands fail? */ /* buffer = pa */ /* if (buffer) memcpy(buffer, pa, size);*/ } else error = EINVAL; if (idata) free(idata); return (error);}intmegascsi_ioctl_inq(scsi_adapter, bi) struct megascsi_adapter *scsi_adapter; struct mioc_inq *bi;{ struct megascsi_big_diskarray *p; /* struct too large for stack */ char *plist; int i, s, t; int off; int error = 0; struct scsi_inquiry_data inqbuf; unsigned char ch, tg; p = malloc(sizeof(struct megascsi_big_diskarray)); if (!p) { printf("%s: no memory for disk array\n",scsi_adapter->adapter_dev.dv_xname); return (ENOMEM); } memset(p, 0, sizeof(struct megascsi_big_diskarray)); plist = malloc(MEGASCSI_BIG_MAX_PDRIVES); if (!plist) { printf("%s: no memory for disk list\n", scsi_adapter->adapter_dev.dv_xname); error = ENOMEM; goto bail; } if (megascsi_mgmt(scsi_adapter, MEGASCSI_FCOP, MEGASCSI_FC_RDCONF, 0, 0, sizeof *p, p)) { error = EINVAL; goto bail2; } memset(plist, 0, MEGASCSI_BIG_MAX_PDRIVES); bi->bi_novol = p->ada_nld; bi->bi_nodisk = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -