📄 scsi-unixware.c
字号:
/* @(#)scsi-unixware.c 1.14 00/07/01 Copyright 1998 J. Schilling, Santa Cruz Operation */#ifndef lintstatic char __sccsid[] = "@(#)scsi-unixware.c 1.14 00/07/01 Copyright 1998 J. Schilling, Santa Cruz Operation";#endif/* * Interface for the SCO UnixWare 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#undef SC_PARITY#undef scb#include <sys/sysmacros.h>#include <sys/scsi.h>#include <sys/sdi_edt.h>#include <sys/sdi.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-unixware.c-1.14"; /* The version for this transport*//* Max. number of scg scsibusses. The real limit would be *//* MAX_HBA * MAX_BUS (which would be 32 * 8 on UnixWare 2.1/7.x), *//* but given that we will hardly see such a beast, lets take 32 */#define MAX_SCG 32 /* maximum defines for UnixWare 2.x/7.x from <sys/sdi_edt.h> */#define MAX_TGT MAX_EXTCS /* Max # of target id's */#define MAX_LUN MAX_EXLUS /* Max # of lun's */#define MAX_DMA (32*1024)#define MAXLINE 80#define MAXPATH 256#define DEV_DIR "/tmp"#define DEV_NAME "scg.s%1dt%1dl%1d"#define SCAN_HBA "%d:%d,%d,%d:%7s : %n"#define SCAN_DEV "%d,%d,%d:%7s : %n"#define PRIM_HBA "/dev/hba/hba1"#define SCSI_CFG "LC_ALL=C /etc/scsi/pdiconfig -l"typedef struct scg2sdi { int valid; int open; int atapi; int initiator; int hba; int bus; int tgt; int lun; int fd; dev_t node; dev_t major; dev_t minor; char type[20]; char vend[40]; char devn[32];} scg2sdi_t;LOCAL scg2sdi_t sdidevs [MAX_SCG][MAX_TGT][MAX_LUN];struct scg_local { short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];};#define scglocal(p) ((struct scg_local *)((p)->local)) LOCAL int unixware_init __PR((SCSI *scgp));LOCAL int do_scsi_cmd __PR((SCSI *scgp, int fd, struct scg_cmd *sp));LOCAL int do_scsi_sense __PR((SCSI *scgp, int fd, struct scg_cmd *sp));/* -------------------------------------------------------------------------** SCO UnixWare 2.1.x / UnixWare 7 provides a scsi pass-through mechanism, ** which can be used to access any configured scsi device. **** NOTE: The libscg UnixWare passthrough routines have changed with ** cdrecord-1.8 to enable the -scanbus, -load, -eject option ** regardless of the status of media and 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 is introduced to create all device nodes necessary** to access any detected scsi device. It parses the output of** /etc/scsi/pdiconfig -l and creates passthru device node for each** found scsi device apart from the listed hba's.***/LOCAL int unixware_init(scgp) SCSI *scgp;{ FILE *cmd; int hba = 0, bus = 0, scg = 0, tgt = 0, lun = 0; int nscg = -1, lhba = -1, lbus = 0; int atapi, fd, nopen = 0, pos = 0, len = 0; int s, t, l; char lines[MAXLINE]; char class[MAXLINE]; char ident[MAXLINE]; char dname[MAXPATH]; struct stat stbuf; dev_t ptdev, major, minor, node; char **evsave;extern char **environ; /* Check for validity of primary hostbus adapter node */ if (stat(PRIM_HBA, &stbuf) < 0) { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "Can not stat() primary hba (%s)", PRIM_HBA); return (-1); } if (!S_ISCHR(stbuf.st_mode)) { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "Primary hba (%s) not a character device", PRIM_HBA); return (-1); } major = getmajor(stbuf.st_rdev); /* read pdiconfig output and get all attached scsi devices ! */ 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; for (;;) { if (fgets(lines, MAXLINE, cmd) == NULL) break; memset( class, '\0', sizeof(class)); memset( ident, '\0', sizeof(ident)); if (lines[0] == ' ' ) { sscanf(lines, SCAN_DEV, &bus, &tgt, &lun, class, &pos); hba = lhba; } else { sscanf(lines, SCAN_HBA, &hba, &bus, &tgt, &lun, class, &pos); nscg++; lhba = hba; atapi = 0; } /* We can't sscanf() the ident string of the device */ /* as it may contain characters sscanf() will */ /* recognize as a delimiter. So do a strcpy() instead ! */ len = strlen(lines) - pos - 1; /* don't copy the '\n' */ strncpy(ident, &lines[pos], len); if (scgp->debug) { printf("SDI -> %d:%d,%d,%d: %-7s : %s\n", hba, bus, tgt, lun, class, ident); } if ( bus != lbus ) { nscg++; lbus = bus; } scg = nscg; /* check whether we have a HBA or a SCSI device, don't */ /* let HBA's be valid device for cdrecord, but mark */ /* them as a controller (initiator = 1). */ if ( strstr(class, "HBA") == NULL ){ sdidevs[scg][tgt][lun].valid = 1; } else { sdidevs[scg][tgt][lun].initiator = 1; } /* There is no real flag that shows a HBA as an ATAPI */ /* controller, so as we know the driver is called 'ide' */ /* we can check the ident string for the occurence of it*/ if ( strstr(ident, "(ide,") != NULL ){ atapi = 1; } /* fill the sdidevs array with all we know now */ sdidevs[scg][tgt][lun].open = 0; sdidevs[scg][tgt][lun].atapi = atapi; sdidevs[scg][tgt][lun].hba = hba; sdidevs[scg][tgt][lun].bus = bus; sdidevs[scg][tgt][lun].tgt = tgt; sdidevs[scg][tgt][lun].lun = lun; strcpy(sdidevs[scg][tgt][lun].type, class); strcpy(sdidevs[scg][tgt][lun].vend, ident); sprintf(sdidevs[scg][tgt][lun].devn, DEV_NAME, scg, tgt, lun); minor = SDI_MINOR(hba, tgt, lun, bus); node = makedevice(major, minor); sdidevs[scg][tgt][lun].major = major; sdidevs[scg][tgt][lun].minor = minor; sdidevs[scg][tgt][lun].node = node; if (scgp->debug) { printf("h = %d; b = %d, s = %d, t = %d, l = %d, a = %d, ma = %d, mi = %2d, dev = %s, id = %s\n", hba, bus, scg, tgt, lun, sdidevs[scg][tgt][lun].atapi, sdidevs[scg][tgt][lun].major, sdidevs[scg][tgt][lun].minor, sdidevs[scg][tgt][lun].devn, sdidevs[scg][tgt][lun].vend ); } } if (pclose(cmd) == -1) { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "Error pclose() for \"%s\"", SCSI_CFG); return (-1); } /* create all temporary device nodes */ for (s = 0; s < MAX_SCG; s++) { for (t = 0; t < MAX_TGT; t++) { for (l = 0; l < MAX_LUN ; l++) { if ( sdidevs[s][t][l].valid == 0) { sdidevs[s][t][l].fd = -1; continue; } /* Make pass-through interface device node */ sprintf(dname, "%s/%s", DEV_DIR, sdidevs[s][t][l].devn); ptdev = sdidevs[s][t][l].node; if (mknod(dname, S_IFCHR | 0700, ptdev) < 0) { if (errno == EEXIST) { unlink(dname); if (mknod(dname, S_IFCHR | 0700, ptdev) < 0) { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "mknod() error for \"%s\"", dname); return (-1); } } else { if (scgp->errstr) js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE, "mknod() error for \"%s\"", dname); return (-1); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -