2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)scsi-openserver.c 1.31 04/01/15 Copyright 1998 J. Schilling, Santa Cruz Operation */
15 * Interface for the SCO SCSI implementation.
17 * Warning: you may change this source, but if you do that
18 * you need to change the _usal_version and _usal_auth* string below.
19 * You may not return "schily" for an SCG_AUTHOR request anymore.
20 * Choose your name instead of "schily" and make clear that the version
21 * string is related to a modified source.
23 * Copyright (c) 1998 J. Schilling, Santa Cruz Operation
26 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License version 2
28 * as published by the Free Software Foundation.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public License along with
36 * this program; see the file COPYING. If not, write to the Free Software
37 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 #include <sys/scsicmd.h>
45 * Warning: you may change this source, but if you do that
46 * you need to change the _usal_version and _usal_auth* string below.
47 * You may not return "schily" for an SCG_AUTHOR request anymore.
48 * Choose your name instead of "schily" and make clear that the version
49 * string is related to a modified source.
51 static char _usal_trans_version[] = "scsi-openserver.c-1.31"; /* The version for this transport*/
53 #define MAX_SCG 16 /* Max # of cdrom devices */
54 #define MAX_TGT 16 /* Not really needed */
55 #define MAX_LUN 8 /* Not really needed */
57 #define MAX_DMA (64*1024)
59 #define MAXPATH 256 /* max length of devicepath */
60 #define MAXLINE 80 /* max length of input line */
61 #define MAXSCSI 99 /* max number of mscsi lines */
62 #define MAXDRVN 10 /* max length of drivername */
64 #define DEV_DIR "/tmp"
65 #define DEV_NAME "usal.s%1dt%1dl%1d"
68 * ---------------------------------------------------------------------
69 * We will only deal with cdroms by default! Only if you set a specific
70 * environment variable, we will scan "all" devices !
71 * Set LIBSCG_SCAN_ALL to any value to enable access to all your SCSI
74 * The upcoming support for USB will be for USB 1.1, so as this is not
75 * tested yet, we will currently ignore drives connect to the USB stack
76 * (usbha controller) regardless of having set LIBSCG_SCAN_ALL or not!
79 #define DEV_ROOT "/dev/dsk/0s0"
81 #define DEV_SDSK "/dev/rdsk/%ds0"
82 #define DEV_SROM "/dev/rcd%d"
83 #define DEV_STP "/dev/xStp%d"
84 #define DEV_SFLP "/dev/rdsk/fp%dh"
86 #define SCAN_DEV "%s%s%d%d%d%d"
88 #define SCSI_CFG "/etc/sconf -r" /* no. of configured devices */
89 #define SCSI_DEV "/etc/sconf -g %d" /* read line 'n' of mscsi tbl */
91 #define DRV_ATAPI "wd" /* SCO OpenServer IDE driver */
92 #define DRV_USB "usbha" /* SCO OpenServer USB driver */
93 #define DRV_NOHA "noha" /* IDE/ATAPI device configured, */
97 #define T_DISK "Sdsk" /* SCO OpenServer SCSI disk */
98 #define T_CDROM "Srom" /* SCO OpenServer SCSI cdrom */
99 #define T_TAPE "Stp" /* SCO OpenServer SCSI tape */
100 #define T_FLOPPY "Sflp" /* SCO OpenServer SCSI floppy */
104 * ---------------------------------------------------------------------
105 * Environment variables to control certain functionality
108 #define SCAN_ALL "LIBSCG_SCAN_ALL" /* enable access for all devices */
109 #define SCSI_USER_CMD "LIBSCG_SCSIUSERCMD" /* use old SCSIUSERCMD ioctl() */
110 #define DMA_OVERRIDE "LIBSCG_MAX_DMA" /* override MAX_DMA value */
111 #define ENABLE_USB "LIBSCG_ENABLE_USB" /* enable access of USB devices */
113 static int scan_all = 0; /* don't scan all devices by default */
114 static int scsiusercmd = 0; /* use SCSIUSERCMD2 ioctl by default */
115 static int enable_usb = 0; /* don't scan USB devices by default */
116 static long max_dma = MAX_DMA; /* use MAX_DMA DMA buffer by default */
120 * ---------------------------------------------------------------------
121 * There are two scsi passthrough ioctl() on SCO OpenServer 5.0.[45],
122 * while there is only one available on SCO OpenServer 5.0.[02].
124 * The SCSIUSERCMD ioctl is available on all OpenServer 5
126 * The SCSIUSERCMD2 ioctl which executes the usercmd and reads the sense
127 * in one go, is only available from 5.0.4 onwards.
129 * By default we will use the SCSIUSERCMD2 ioctl(), in order to execute
130 * the SCSIUSERCMD ioctl() instead set the environment variable
131 * LIBSCG_SCSIUSERCMD to any value. Using the olderSCSIUSERCMD ioctl() will
132 * if the SCSI commands returns a CHECK CONDITION status, run a seperate
133 * REQUEST_SENSE command immediately. But we need to remember that in a
134 * multi-tasking environment, there might be other code which has accessed
135 * the device in between these two steps and therefore the sense code
136 * is no longer valid !!!
138 * NOTE: There are problems with the usage of AHA 154X controllers
139 * and SCSIUSERCMD2 such as nonsense (weird) output on cdrecord -scanbus
144 typedef struct usal2sdi {
154 static usal2sdi_t sdidevs [MAX_SCG][MAX_TGT][MAX_LUN];
156 typedef struct amscsi {
169 short usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
171 #define usallocal(p) ((struct usal_local *)((p)->local))
173 static int sort_mscsi(const void *l1, const void *l2);
174 static int openserver_init(SCSI *usalp);
175 static void cp_usal2sco(struct scsicmd2 *sco, struct usal_cmd *usal);
176 static void cp_sco2usal(struct scsicmd2 *sco, struct usal_cmd *usal);
179 * -------------------------------------------------------------------------
180 * SCO OpenServer does not have a generic scsi device driver, which can
181 * be used to access any configured scsi device. But we can use the "Sxxx"
182 * scsi peripherial drivers passthrough ioctl() (SCSIUSERCMD / SCSIUSERCMD2)
183 * to send scsi user comands to any target device controlled by the
184 * corresponding target driver.
186 * This passthrough implementation for libusal currently allows to
187 * handle the following devices classes:
189 * 1. DISK handled by Sdsk
190 * 2. CD-ROM handled by Srom
191 * 3. TAPES handled by Stp
192 * 4. FLOPPY handled by Sflp
194 * NOTE: The libusal OpenServer passthrough routines have changed with
195 * cdrecord-1.8 to enable the -scanbus option. Therefore the
196 * addressing scheme is now the same as used on many other platforms
197 * like Solaris, Linux etc.
199 * ===============================================================
200 * RUN 'cdrecord -scanbus' TO SEE THE DEVICE ADDRESSES YOU CAN USE
201 * ===============================================================
206 * Return version information for the low level SCSI transport code.
207 * This has been introduced to make it easier to trace down problems
211 usalo_version(SCSI *usalp, int what)
213 if (usalp != (SCSI *)0) {
217 return (_usal_trans_version);
219 * If you changed this source, you are not allowed to
220 * return "schily" for the SCG_AUTHOR request.
223 return (_usal_auth_cdrkit);
232 usalo_help(SCSI *usalp, FILE *f)
234 __usal_help(f, "SCSIUSERCMD/SCSIUSERCMD2", "Generic SCSI",
235 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
240 * ---------------------------------------------------------------
241 * This routine sorts the amscsi_t lines on the following columns
242 * in ascending order:
244 * 1. drv - driver name
245 * 2. bus - scsibus per controller
246 * 3. tgt - target id of device
247 * 4. lun - lun of the device
253 sort_mscsi(const void *l1, const void *l2)
255 amscsi_t *t1 = (amscsi_t *) l1;
256 amscsi_t *t2 = (amscsi_t *) l2;
258 if (strcmp(t1->drv, t2->drv) == 0) {
259 if (t1->bus < t2->bus) {
262 } else if (t1->bus > t2->bus) {
265 } else if (t1->tgt < t2->tgt) {
268 } else if (t1->tgt > t2->tgt) {
271 } else if (t1->lun < t2->lun) {
274 } else if (t1->lun > t2->lun) {
280 return (strcmp(t1->drv, t2->drv));
285 * ---------------------------------------------------------------
286 * This routine is introduced to find all scsi devices which are
287 * currently configured into the kernel. This is done by reading
288 * the dynamic kernel mscsi tables and parse the resulting lines.
289 * As the output of 'sconf' is not directly usable the information
290 * found is to be sorted and re-arranged to be used with the libusal
293 * NOTE: One problem is currently still not solved ! If you don't
294 * have a media in your CD-ROM/CD-Writer we are not able to
295 * do an open() and therefore will set the drive to be not
296 * available (valid=0).
298 * This will for example cause cdrecord to not list the drive
299 * in the -scanbus output.
304 openserver_init(SCSI *usalp)
307 int nusal = -1, lhba = -1, lbus = -1;
308 int nSrom = -1, nSdsk = -1, nStp = -1, nSflp = -1;
309 int atapi, fd, nopen = 0;
310 int pos = 0, len = 0, nlm = 0;
311 int s = 0, t = 0, l = 0;
312 int ide_rootdisk = 0;
313 long dma_override = 0;
318 amscsi_t cmtbl[MAXSCSI];
321 extern char **environ;
324 for (s = 0; s < MAX_SCG; s++) {
325 for (t = 0; t < MAX_TGT; t++) {
326 for (l = 0; l < MAX_LUN; l++) {
327 sdidevs[s][t][l].valid = 0;
328 sdidevs[s][t][l].open = -1;
329 sdidevs[s][t][l].atapi = -1;
330 sdidevs[s][t][l].fd = -1;
331 sdidevs[s][t][l].lmscsi = -1;
336 /* Check whether we want to use the older SCSIUSERCMD ioctl() */
338 if (getenv(SCSI_USER_CMD) != NULL) {
343 * Check whether we want to scan all devices
345 if (getenv(SCAN_ALL) != NULL) {
350 * Check whether we want to use USB devices
352 if (getenv(ENABLE_USB) != NULL) {
357 * Check whether we want to override the MAX_DMA value
359 if (getenv(DMA_OVERRIDE) != NULL) {
360 dma_override = atol(getenv(DMA_OVERRIDE));
361 if ((dma_override >= 1) && (dma_override <= (256)))
362 max_dma = dma_override * 1024;
366 /* read sconf -r and get number of kernel mscsi lines ! */
370 if ((cmd = popen(SCSI_CFG, "r")) == NULL) {
372 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
373 "Error popen() for \"%s\"",
380 if (fgets(lines, MAXLINE, cmd) == NULL) {
383 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
384 "Error reading popen() for \"%s\"",
390 if (usalp->debug > 0) {
391 fprintf((FILE *)usalp->errfile, "-------------------- \n");
392 fprintf((FILE *)usalp->errfile, "mscsi lines = %d\n", nlm);
393 fprintf((FILE *)usalp->errfile, "-------------------- \n");
396 if (pclose(cmd) == -1) {
398 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
399 "Error pclose() for \"%s\"",
404 for (l = 0; l < nlm; l++) {
406 /* initialize cmtbl entry */
414 memset(cmtbl[l].typ, '\0', MAXDRVN);
415 memset(cmtbl[l].drv, '\0', MAXDRVN);
416 memset(cmtbl[l].dev, '\0', MAXDRVN);
418 /* read sconf -g 'n' and get line of kernel mscsi table! */
419 /* the order the lines will be received in will determine */
420 /* the device name we can use to open the device */
422 snprintf(sconf, sizeof (sconf),
423 SCSI_DEV, l + 1); /* enumeration starts with 1 */
427 if ((cmd = popen(sconf, "r")) == NULL) {
429 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
430 "Error popen() for \"%s\"",
437 if (fgets(lines, MAXLINE, cmd) == NULL)
440 if (pclose(cmd) == -1) {
442 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
443 "Error pclose() for \"%s\"",
448 sscanf(lines, SCAN_DEV, cmtbl[l].typ,
455 if (strstr(cmtbl[l].typ, T_DISK) != NULL) {
456 snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
460 if (strstr(cmtbl[l].typ, T_CDROM) != NULL) {
461 snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
465 if (strstr(cmtbl[l].typ, T_TAPE) != NULL) {
466 snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
470 if (strstr(cmtbl[l].typ, T_FLOPPY) != NULL) {
471 snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
475 if (usalp->debug > 0) {
476 fprintf((FILE *)usalp->errfile,
477 "%-4s = %5s(%d,%d,%d,%d) -> %s\n",
489 if (usalp->debug > 0) {
490 fprintf((FILE *)usalp->errfile, "-------------------- \n");
491 fprintf((FILE *)usalp->errfile, "%2d DISK \n", nSdsk + 1);
492 fprintf((FILE *)usalp->errfile, "%2d CD-ROM\n", nSrom + 1);
493 fprintf((FILE *)usalp->errfile, "%2d TAPE \n", nStp + 1);
494 fprintf((FILE *)usalp->errfile, "%2d FLOPPY\n", nSflp + 1);
495 fprintf((FILE *)usalp->errfile, "-------------------- \n");
498 /* ok, now let's sort this array of scsi devices */
500 qsort((void *) cmtbl, nlm, sizeof (amscsi_t), sort_mscsi);
502 if (usalp->debug > 0) {
503 for (l = 0; l < nlm; l++)
504 fprintf((FILE *)usalp->errfile,
505 "%-4s = %5s(%d,%d,%d,%d) -> %s\n",
513 fprintf((FILE *)usalp->errfile, "-------------------- \n");
516 /* find root disk controller to make it usal 0 */
519 * if we have disk(s) found in the mscsi table, we still
520 * don't know if the rootdisk is among these, there can
521 * be a IDE rootdisk as well, but it's not listed in
527 for (l = 0; l < nlm; l++)
528 if (strcmp(cmtbl[l].dev, DEV_ROOT) == 0)
533 * we haven't found a disk in mscsi, so we definitely
534 * have an IDE disk on a wd adapter as IDE disks are
535 * not listed as SCSI disks in the kernel mscsi table
541 if (!(ide_rootdisk) && (usalp->debug > 0)) {
542 fprintf((FILE *)usalp->errfile,
543 "root = %5s(%d,%d,%d,%d) -> %s\n",
550 fprintf((FILE *)usalp->errfile, "-------------------- \n");
553 /* calculate usal from drv, hba and bus */
557 for (l = 0, s = t; l < nlm; l++, s = (t + l) % nlm) {
559 if (strcmp(drvid, cmtbl[s].drv) != 0) {
560 strcpy(drvid, cmtbl[s].drv);
563 cmtbl[s].usal = ++nusal;
565 } else if (cmtbl[s].hba != lhba) {
568 cmtbl[s].usal = ++nusal;
570 } else if (cmtbl[s].bus != lbus) {
572 cmtbl[s].usal = ++nusal;
574 cmtbl[s].usal = nusal;
576 sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].open = 0;
578 /* check whether we want to open all devices or it's a CDROM */
580 if ((scan_all) || (strcmp(cmtbl[s].typ, T_CDROM) == 0))
581 sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].valid = 1;
583 /* check whether we have an IDE/ATAPI device */
585 if (strcmp(cmtbl[s].drv, DRV_ATAPI) == 0)
586 sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].atapi = 1;
588 /* don't open a USB device if enable_usb is not set */
590 if (strcmp(cmtbl[s].drv, DRV_USB) == 0)
591 sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].valid = enable_usb;
593 /* don't open a IDE/ATAPI device which is missing but configured */
595 if (strcmp(cmtbl[s].drv, DRV_NOHA) == 0)
596 sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].valid = 0;
599 sdidevs[cmtbl[s].usal][cmtbl[s].tgt][cmtbl[s].lun].lmscsi = s;
604 /* open all yet valid device nodes */
606 for (s = 0; s < MAX_SCG; s++) {
607 for (t = 0; t < MAX_TGT; t++) {
608 for (l = 0; l < MAX_LUN; l++) {
610 if (sdidevs[s][t][l].valid == 0)
613 /* Open pass-through device node */
615 mscsi = sdidevs[s][t][l].lmscsi;
617 strcpy(dname, cmtbl[mscsi].dev);
620 * ------------------------------------------------------------------
621 * NOTE: If we can't open the device, we will set the device invalid!
622 * ------------------------------------------------------------------
625 if ((fd = open(dname, (O_RDONLY | O_NONBLOCK))) < 0) {
626 sdidevs[s][t][l].valid = 0;
627 if (usalp->debug > 0) {
628 fprintf((FILE *)usalp->errfile,
629 "%5s(%d,%d,%d,%d) -> %s open() failed: errno = %d (%s)\n",
642 if (usalp->debug > 0) {
643 fprintf((FILE *)usalp->errfile,
644 "%d,%d,%d => %5s(%d,%d,%d,%d) -> %d : %s \n",
655 sdidevs[s][t][l].fd = fd;
656 sdidevs[s][t][l].open = 1;
658 usallocal(usalp)->usalfiles[s][t][l] = (short) fd;
663 if (usalp->debug > 0) {
664 fprintf((FILE *)usalp->errfile, "-------------------- \n");
665 fprintf((FILE *)usalp->errfile, "nopen = %d devices \n", nopen);
666 fprintf((FILE *)usalp->errfile, "-------------------- \n");
674 usalo_open(SCSI *usalp, char *device)
676 int busno = usal_scsibus(usalp);
677 int tgt = usal_target(usalp);
678 int tlun = usal_lun(usalp);
683 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
686 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
687 "Illegal value for busno, target or lun '%d,%d,%d'",
692 if (usalp->local == NULL) {
693 usalp->local = malloc(sizeof (struct usal_local));
694 if (usalp->local == NULL)
697 for (b = 0; b < MAX_SCG; b++) {
698 for (t = 0; t < MAX_TGT; t++) {
699 for (l = 0; l < MAX_LUN; l++)
700 usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
705 if (*device != '\0') { /* we don't allow old dev usage */
708 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
709 "Open by 'devname' no longer supported on this OS");
713 return (openserver_init(usalp));
718 usalo_close(SCSI *usalp)
725 if (usalp->local == NULL)
728 for (b = 0; b < MAX_SCG; b++) {
729 for (t = 0; t < MAX_TGT; t++) {
730 for (l = 0; l < MAX_LUN; l++) {
732 f = usallocal(usalp)->usalfiles[b][t][l];
736 sdidevs[b][t][l].fd = -1;
737 sdidevs[b][t][l].open = 0;
738 sdidevs[b][t][l].valid = 0;
740 usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
748 usalo_maxdma(SCSI *usalp, long amt)
755 usalo_getbuf(SCSI *usalp, long amt)
757 if (usalp->debug > 0) {
758 fprintf((FILE *)usalp->errfile,
759 "usalo_getbuf: %ld bytes\n", amt);
761 usalp->bufbase = valloc((size_t)(amt));
763 return (usalp->bufbase);
767 usalo_freebuf(SCSI *usalp)
770 free(usalp->bufbase);
771 usalp->bufbase = NULL;
775 usalo_havebus(SCSI *usalp, int busno)
780 if (busno < 0 || busno >= MAX_SCG)
783 if (usalp->local == NULL)
786 for (t = 0; t < MAX_TGT; t++) {
787 for (l = 0; l < MAX_LUN; l++)
788 if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
795 usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
797 if (busno < 0 || busno >= MAX_SCG ||
798 tgt < 0 || tgt >= MAX_TGT ||
799 tlun < 0 || tlun >= MAX_LUN)
802 if (usalp->local == NULL)
805 return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
809 usalo_initiator_id(SCSI *usalp)
814 * We don't know the initiator ID yet, but we can if we parse the
815 * output of the command 'cat /dev/string/cfg | grep "%adapter"'
819 * %adapter 0xE800-0xE8FF 11 - type=alad ha=0 bus=0 id=7 fts=sto
821 * This tells us that the alad controller 0 has an id of 7 !
822 * The parsing should be done in openserver_init().
828 usalo_isatapi(SCSI *usalp)
830 return (sdidevs[usal_scsibus(usalp)][usal_target(usalp)][usal_lun(usalp)].atapi);
834 usalo_reset(SCSI *usalp, int what)
837 return (-1); /* no scsi reset available */
841 cp_usal2sco(struct scsicmd2 *sco, struct usal_cmd *usal)
843 sco->cmd.data_ptr = (char *) usal->addr;
844 sco->cmd.data_len = usal->size;
845 sco->cmd.cdb_len = usal->cdb_len;
847 sco->sense_len = usal->sense_len;
848 sco->sense_ptr = usal->u_sense.cmd_sense;
850 if (!(usal->flags & SCG_RECV_DATA) && (usal->size > 0))
851 sco->cmd.is_write = 1;
853 if (usal->cdb_len == SC_G0_CDBLEN)
854 memcpy(sco->cmd.cdb, &usal->cdb.g0_cdb, usal->cdb_len);
856 if (usal->cdb_len == SC_G1_CDBLEN)
857 memcpy(sco->cmd.cdb, &usal->cdb.g1_cdb, usal->cdb_len);
859 if (usal->cdb_len == SC_G5_CDBLEN)
860 memcpy(sco->cmd.cdb, &usal->cdb.g5_cdb, usal->cdb_len);
865 cp_sco2usal(struct scsicmd2 *sco, struct usal_cmd *usal)
867 usal->size = sco->cmd.data_len;
869 memset(&usal->scb, 0, sizeof (usal->scb));
871 if (sco->sense_len > SCG_MAX_SENSE)
872 usal->sense_count = SCG_MAX_SENSE;
874 usal->sense_count = sco->sense_len;
878 usal->u_scb.cmd_scb[0] = sco->cmd.target_sts;
884 usalo_send(SCSI *usalp)
886 struct usal_cmd *sp = usalp->scmd;
887 struct scsicmd2 scsi_cmd;
889 Uchar sense_buf[SCG_MAX_SENSE];
892 sp->error = SCG_FATAL;
896 memset(&scsi_cmd, 0, sizeof (scsi_cmd));
897 memset(sense_buf, 0, sizeof (sense_buf));
898 scsi_cmd.sense_ptr = sense_buf;
899 scsi_cmd.sense_len = sizeof (sense_buf);
900 cp_usal2sco(&scsi_cmd, sp);
904 sp->error = SCG_NO_ERROR;
907 struct scsicmd s_cmd;
909 if (scsiusercmd) { /* Use SCSIUSERCMD ioctl() */
910 if (usalp->debug > 1) {
911 fprintf((FILE *)usalp->errfile, "calling SCSIUSERCMD ioctl()\n");
914 if ((ioctlStatus = ioctl(usalp->fd, SCSIUSERCMD, &(scsi_cmd.cmd))) < 0) {
915 if (usalp->debug > 1) {
916 fprintf((FILE *)usalp->errfile, "returning from SCSIUSERCMD ioctl()\n");
921 cp_sco2usal(&scsi_cmd, sp);
922 sp->ux_errno = errno;
925 sp->error = SCG_RETRYABLE;
930 if (usalp->debug > 1) {
931 fprintf((FILE *)usalp->errfile, "returning from SCSIUSERCMD ioctl()\n");
933 cp_sco2usal(&scsi_cmd, sp);
934 sp->ux_errno = errno;
936 if (scsi_cmd.cmd.target_sts & 0x02) { /* Check Condition & get Sense */
938 if (sp->sense_len > SCG_MAX_SENSE)
939 sp->sense_len = SCG_MAX_SENSE;
941 memset((caddr_t)&s_cmd, 0, sizeof (s_cmd));
943 s_cmd.data_ptr = (caddr_t) sp->u_sense.cmd_sense;
944 s_cmd.data_len = sp->sense_len;
946 s_cmd.cdb[0] = SC_REQUEST_SENSE;
948 while (((ioctlStatus = ioctl(usalp->fd, SCSIUSERCMD, &s_cmd)) < 0) &&
952 sp->sense_count = sp->sense_len;
953 sp->ux_errno = errno;
957 sp->error = SCG_NO_ERROR;
960 if (usalp->debug > 0) {
962 fprintf((FILE *)usalp->errfile, "ux_errno: %d (%s) \n", sp->ux_errno, strerror(sp->ux_errno));
963 if (sp->u_scb.cmd_scb[0] != 0)
964 fprintf((FILE *)usalp->errfile, "tgt_stat: %d \n", sp->u_scb.cmd_scb[0]);
968 } else { /* Use SCSIUSERCMD2 ioctl() */
969 if (usalp->debug > 1) {
970 fprintf((FILE *)usalp->errfile, "calling SCSIUSERCMD2 ioctl()\n");
973 if ((ioctlStatus = ioctl(usalp->fd, SCSIUSERCMD2, &scsi_cmd)) < 0) {
974 if (usalp->debug > 1) {
975 fprintf((FILE *)usalp->errfile, "returning from SCSIUSERCMD2 ioctl()\n");
980 cp_sco2usal(&scsi_cmd, sp);
981 sp->ux_errno = errno;
984 sp->error = SCG_RETRYABLE;
988 if (usalp->debug > 1) {
989 fprintf((FILE *)usalp->errfile, "returning from SCSIUSERCMD2 ioctl()\n");
992 cp_sco2usal(&scsi_cmd, sp);
993 sp->ux_errno = errno;
995 if (scsi_cmd.cmd.target_sts & 0x02) { /* Check Condition */
998 sp->error = SCG_NO_ERROR;
1001 if (usalp->debug > 0) {
1003 fprintf((FILE *)usalp->errfile, "ux_errno: %d (%s) \n", sp->ux_errno, strerror(sp->ux_errno));
1004 if (sp->u_scb.cmd_scb[0] != 0)
1005 fprintf((FILE *)usalp->errfile, "tgt_stat: %d \n", sp->u_scb.cmd_scb[0]);
1015 #define sense u_sense.Sense