📄 scsi-openserver.c
字号:
/* @(#)scsi-openserver.c 1.19 00/07/01 Copyright 1998 J. Schilling, Santa Cruz Operation */#ifndef lintstatic char __sccsid[] = "@(#)scsi-openserver.c 1.19 00/07/01 Copyright 1998 J. Schilling, Santa Cruz Operation";#endif/* * Interface for the SCO SCSI implementation. * * Warning: you may change this source, but if you do that * you need to change the _scg_version and _scg_auth* string below. * You may not return "schily" for an SCG_AUTHOR request anymore. * Choose your name instead of "schily" and make clear that the version * string is related to a modified source. * * Copyright (c) 1998 J. Schilling, Santa Cruz Operation *//* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#undef sense#include <sys/scsicmd.h>/* * Warning: you may change this source, but if you do that * you need to change the _scg_version and _scg_auth* string below. * You may not return "schily" for an SCG_AUTHOR request anymore. * Choose your name instead of "schily" and make clear that the version * string is related to a modified source. */LOCAL char _scg_trans_version[] = "scsi-openserver.c-1.19"; /* The version for this transport*/#define MAX_SCG 16 /* Max # of cdrom devices */#define MAX_TGT 16 /* Not really needed */#define MAX_LUN 8 /* Not really needed */#define MAX_DMA (32*1024) /* Maybe even more ??? */#define MAXPATH 256 /* max length of devicepath */#define MAXLINE 80 /* max length of input line */#define MAXSCSI 99 /* max number of mscsi lines */#define MAXDRVN 10 /* max length of drivername */#define DEV_DIR "/tmp"#define DEV_NAME "scg.s%1dt%1dl%1d" /* We will only deal with disks, cdroms and tapes ! */ /* Sflp devices (floptical) 21Mb scsi floppy devices */ /* will be ignored. Hmm, I can't remember that I ever */ /* have seen one ;^) */#define DEV_ROOT "/dev/rdsk/0s0"#define DEV_SDSK "/dev/rdsk/%ds0"#define DEV_SROM "/dev/rcd%d"#define DEV_STP "/dev/xStp%d"#define SCAN_DEV "%s%s%d%d%d%d"#define SCSI_CFG "/etc/sconf -r" /* no. of configured devices */#define SCSI_DEV "/etc/sconf -g %d" /* read line 'n' of mscsi tbl */#define DRV_ATAPI "wd"typedef struct scg2sdi { int valid; int open; int atapi; int fd; int lmscsi;} scg2sdi_t;LOCAL scg2sdi_t sdidevs [MAX_SCG][MAX_TGT][MAX_LUN];typedef struct amscsi { char typ[MAXDRVN]; char drv[MAXDRVN]; int hba; int bus; int scg; int tgt; int lun; char dev[MAXPATH];} amscsi_t;struct scg_local { short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];};#define scglocal(p) ((struct scg_local *)((p)->local)) LOCAL int sort_mscsi __PR((const void *l1, const void *l2));LOCAL int openserver_init __PR((SCSI *scgp));LOCAL void cp_scg2sco __PR((struct scsicmd2 *sco, struct scg_cmd *scg));LOCAL void cp_sco2scg __PR((struct scsicmd2 *sco, struct scg_cmd *scg));/* -------------------------------------------------------------------------** SCO OpenServer does not have a generic scsi device driver, which can** be used to access any configured scsi device. **** But we can use the "Srom" scsi peripherial driver (for CD-ROM devices) ** etc. to send SCSIUSERCMD2's to any target device controlled by the ** corresponding target driver.**** This pass-through implementation for libscg currently allows to ** handle the following devices classes:**** 1. DISK handled by Sdsk** 2. CD-ROM handled by Srom** 3. TAPES handled by Stp**** NOTE: The libscg OpenServer passthrough routines have changed with ** cdrecord-1.8 to enable the -scanbus option. Therefore the** addressing scheme is now the same as used on many other platforms** like Solaris, Linux etc.**** ===============================================================** RUN 'cdrecord -scanbus' TO SEE THE DEVICE ADDRESSES YOU CAN USE** ===============================================================***//* * Return version information for the low level SCSI transport code. * This has been introduced to make it easier to trace down problems * in applications. */EXPORT char *scg__version(scgp, what) SCSI *scgp; int what;{ if (scgp != (SCSI *)0) { switch (what) { case SCG_VERSION: return (_scg_trans_version); /* * If you changed this source, you are not allowed to * return "schily" for the SCG_AUTHOR request. */ case SCG_AUTHOR: return (_scg_auth_schily); case SCG_SCCS_ID: return (__sccsid); } } return ((char *)0);}/* ---------------------------------------------------------------** This routine sorts the amscsi_t lines on the following columns** in ascending order:**** 1. drv - driver name** 2. bus - scsibus per controller** 3. tgt - target id of device** 4. lun - lun of the device***/LOCAL intsort_mscsi(l1, l2) const void *l1; const void *l2;{ amscsi_t *t1 = (amscsi_t *) l1; amscsi_t *t2 = (amscsi_t *) l2; if ( strcmp(t1->drv, t2->drv) == 0 ) { if (t1->bus < t2->bus) { return (-1); } else if (t1->bus > t2->bus) { return (1); } else if (t1->tgt < t2->tgt) { return (-1); } else if (t1->tgt > t2->tgt) { return (1); } else if (t1->lun < t2->lun) { return (-1); } else if (t1->lun > t2->lun) { return (1); } else { return (0); } } else { return (strcmp(t1->drv, t2->drv)); }}/* ---------------------------------------------------------------** This routine is introduced to find all scsi devices which are** currently configured into the kernel. This is done by reading** the dynamic kernel mscsi tables and parse the resulting lines.** As the output of 'sconf' is not directly usable the information** found is to be sorted and re-arranged to be used with the libscg** routines.**** NOTE: One problem is currently still not solved ! If you don't** have a media in your CD-ROM/CD-Writer we are not able to ** do an open() and therefore will set the drive to be not ** available (valid=0).**** This will for example cause cdrecord to not list the drive ** in the -scanbus output.***/LOCAL int openserver_init(scgp) SCSI *scgp;{ FILE *cmd; int nscg = -1, lhba = -1, lbus = -1; int nSrom = -1, nSdsk = -1, nStp = -1; int atapi, fd, nopen = 0; int pos = 0, len = 0, nlm = 0; int s = 0, t = 0, l = 0; int mscsi; char sconf[MAXLINE]; char lines[MAXLINE]; char drvid[MAXDRVN]; amscsi_t cmtbl[MAXSCSI]; char dname[MAXPATH]; char **evsave;extern char **environ; for (s = 0; s < MAX_SCG; s++) { for (t = 0; t < MAX_TGT; t++) { for (l = 0; l < MAX_LUN ; l++) { sdidevs[s][t][l].valid = 0; sdidevs[s][t][l].open = -1; sdidevs[s][t][l].atapi = -1; sdidevs[s][t][l].fd = -1; sdidevs[s][t][l].lmscsi = -1; } } } /* read sconf -r and get number of kernel mscsi lines ! */ evsave = environ; environ = 0; if ((cmd = popen(SCSI_CFG,"r")) == NULL) { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "Error popen() for \"%s\"", SCSI_CFG); environ = evsave; return (-1); } environ = evsave; if (fgets(lines, MAXLINE, cmd) == NULL) { errno = EIO; if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "Error reading popen() for \"%s\"", SCSI_CFG); return (-1); } else nlm = atoi(lines); if (scgp->debug) { printf("-------------------- \n"); printf("mscsi lines = %d\n", nlm); printf("-------------------- \n"); } if (pclose(cmd) == -1) { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "Error pclose() for \"%s\"", SCSI_CFG); return (-1); } for (l = 0; l < nlm; l++) { /* initialize cmtbl entry */ cmtbl[l].hba = -1; cmtbl[l].bus = -1; cmtbl[l].tgt = -1; cmtbl[l].lun = -1; cmtbl[l].scg = -1; memset( cmtbl[l].typ, '\0', MAXDRVN); memset( cmtbl[l].drv, '\0', MAXDRVN); memset( cmtbl[l].dev, '\0', MAXDRVN); /* read sconf -g 'n' and get line of kernel mscsi table! */ /* the order the lines will be received in will determine */ /* the device name we can use to open the device */ sprintf(sconf, SCSI_DEV, l + 1); /* enumeration starts with 1 */ evsave = environ; environ = 0; if ((cmd = popen(sconf,"r")) == NULL) { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "Error popen() for \"%s\"", sconf); environ = evsave; return (-1); } environ = evsave; if (fgets(lines, MAXLINE, cmd) == NULL) break; if (pclose(cmd) == -1) { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "Error pclose() for \"%s\"", sconf); return (-1); } sscanf(lines, SCAN_DEV, cmtbl[l].typ, cmtbl[l].drv, &cmtbl[l].hba, &cmtbl[l].bus, &cmtbl[l].tgt, &cmtbl[l].lun); if ( strstr(cmtbl[l].typ, "Sdsk") != NULL ){ sprintf(cmtbl[l].dev, DEV_SDSK, ++nSdsk); } if ( strstr(cmtbl[l].typ, "Srom") != NULL ){ sprintf(cmtbl[l].dev, DEV_SROM, ++nSrom); } if ( strstr(cmtbl[l].typ, "Stp") != NULL ){ sprintf(cmtbl[l].dev, DEV_STP, ++nStp); } if (scgp->debug) { printf("%-4s = %5s(%d,%d,%d,%d) -> %s\n", cmtbl[l].typ, cmtbl[l].drv, cmtbl[l].hba, cmtbl[l].bus, cmtbl[l].tgt, cmtbl[l].lun, cmtbl[l].dev); } } if (scgp->debug) { printf("-------------------- \n"); printf("%2d DISK \n", nSdsk + 1); printf("%2d CD-ROM\n", nSrom + 1); printf("%2d TAPE \n", nStp + 1); printf("-------------------- \n"); } /* ok, now let's sort this array of scsi devices */ qsort((void *) cmtbl, nlm, sizeof(amscsi_t), sort_mscsi); if (scgp->debug) { for (l = 0; l < nlm; l++) printf("%-4s = %5s(%d,%d,%d,%d) -> %s\n", cmtbl[l].typ, cmtbl[l].drv, cmtbl[l].hba, cmtbl[l].bus, cmtbl[l].tgt, cmtbl[l].lun, cmtbl[l].dev); printf("-------------------- \n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -