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-sun.c 1.83 05/11/20 Copyright 1988,1995,2000-2004 J. Schilling */
15 * SCSI user level command transport routines for
16 * the SCSI general driver 'usal'.
18 * Warning: you may change this source, but if you do that
19 * you need to change the _usal_version and _usal_auth* string below.
20 * You may not return "schily" for an SCG_AUTHOR request anymore.
21 * Choose your name instead of "schily" and make clear that the version
22 * string is related to a modified source.
24 * Copyright (c) 1988,1995,2000-2004 J. Schilling
27 * This program is free software; you can redistribute it and/or modify
28 * it under the terms of the GNU General Public License version 2
29 * as published by the Free Software Foundation.
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public License along with
37 * this program; see the file COPYING. If not, write to the Free Software
38 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #include <usal/usalio.h>
43 #include <libport.h> /* Needed for gethostid() */
44 #ifdef HAVE_SUN_DKIO_H
45 # include <sun/dkio.h>
47 # define dk_cinfo dk_conf
48 # define dki_slave dkc_slave
49 # define DKIO_GETCINFO DKIOCGCONF
51 #ifdef HAVE_SYS_DKIO_H
52 # include <sys/dkio.h>
54 # define DKIO_GETCINFO DKIOCINFO
57 #define TARGET(slave) ((slave) >> 3)
58 #define LUN(slave) ((slave) & 07)
61 * Tht USCSI ioctl() is not usable on SunOS 4.x
64 /*#define VOLMGT_DEBUG*/
70 static char _usal_trans_version[] = "usal-1.83"; /* The version for /dev/usal */
71 static char _usal_utrans_version[] = "uscsi-1.83"; /* The version for USCSI */
74 static int usalo_uhelp(SCSI *usalp, FILE *f);
75 static int usalo_uopen(SCSI *usalp, char *device);
76 static int usalo_volopen(SCSI *usalp, char *devname);
77 static int usalo_openmedia(SCSI *usalp, char *mname);
78 static int usalo_uclose(SCSI *usalp);
79 static int usalo_ucinfo(int f, struct dk_cinfo *cp, int debug);
80 static int usalo_ugettlun(int f, int *tgtp, int *lunp);
81 static long usalo_umaxdma(SCSI *usalp, long amt);
82 static int usalo_openide(void);
83 static BOOL usalo_uhavebus(SCSI *usalp, int);
84 static int usalo_ufileno(SCSI *usalp, int, int, int);
85 static int usalo_uinitiator_id(SCSI *usalp);
86 static int usalo_uisatapi(SCSI *usalp);
87 static int usalo_ureset(SCSI *usalp, int what);
88 static int usalo_usend(SCSI *usalp);
90 static int have_volmgt = -1;
92 static usal_ops_t sun_uscsi_ops = {
94 usalo_version, /* Shared with SCG driver */
99 usalo_getbuf, /* Shared with SCG driver */
100 usalo_freebuf, /* Shared with SCG driver */
110 * Need to move this into an usal driver ioctl.
112 /*#define MAX_DMA_SUN4M (1024*1024)*/
113 #define MAX_DMA_SUN4M (124*1024) /* Currently max working size */
114 /*#define MAX_DMA_SUN4C (126*1024)*/
115 #define MAX_DMA_SUN4C (124*1024) /* Currently max working size */
116 #define MAX_DMA_SUN3 (63*1024)
117 #define MAX_DMA_SUN386 (56*1024)
118 #define MAX_DMA_OTHER (32*1024)
120 #define ARCH_MASK 0xF0
121 #define ARCH_SUN2 0x00
122 #define ARCH_SUN3 0x10
123 #define ARCH_SUN4 0x20
124 #define ARCH_SUN386 0x30
125 #define ARCH_SUN3X 0x40
126 #define ARCH_SUN4C 0x50
127 #define ARCH_SUN4E 0x60
128 #define ARCH_SUN4M 0x70
129 #define ARCH_SUNX 0x80
132 * We are using a "real" /dev/usal?
134 #define scsi_xsend(usalp) ioctl((usalp)->fd, SCGIO_CMD, (usalp)->scmd)
135 #define MAX_SCG 16 /* Max # of SCSI controllers */
141 int SCG_files[MAX_SCG];
143 short usal_files[MAX_SCG][MAX_TGT][MAX_LUN];
147 #define usallocal(p) ((struct usal_local *)((p)->local))
148 #define usalfiles(p) (usallocal(p)->u.SCG_files)
151 * Return version information for the low level SCSI transport code.
152 * This has been introduced to make it easier to trace down problems
156 usalo_version(SCSI *usalp, int what)
158 if (usalp != (SCSI *)0) {
163 if (usalp->ops == &sun_uscsi_ops)
164 return (_usal_utrans_version);
166 return (_usal_trans_version);
168 * If you changed this source, you are not allowed to
169 * return "schily" for the SCG_AUTHOR request.
172 return (_usal_auth_cdrkit);
181 usalo_help(SCSI *usalp, FILE *f)
183 __usal_help(f, "usal", "Generic transport independent SCSI",
184 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
186 usalo_uhelp(usalp, f);
192 usalo_open(SCSI *usalp, char *device)
194 int busno = usal_scsibus(usalp);
195 int tgt = usal_target(usalp);
196 /* int tlun = usal_lun(usalp);*/
199 register int nopen = 0;
202 if (busno >= MAX_SCG) {
205 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
206 "Illegal value for busno '%d'", busno);
210 if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
212 usalp->ops = &sun_uscsi_ops;
213 return (SCGO_OPEN(usalp, device));
217 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
218 "Open by 'devname' not supported on this OS");
223 if (usalp->local == NULL) {
224 usalp->local = malloc(sizeof (struct usal_local));
225 if (usalp->local == NULL) {
227 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE, "No memory for usal_local");
231 for (i = 0; i < MAX_SCG; i++) {
232 usalfiles(usalp)[i] = -1;
237 for (i = 0; i < MAX_SCG; i++) {
239 * Skip unneeded devices if not in SCSI Bus scan open mode
241 if (busno >= 0 && busno != i)
243 snprintf(devname, sizeof (devname), "/dev/usal%d", i);
244 f = open(devname, O_RDWR);
246 if (errno != ENOENT && errno != ENXIO) {
248 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
249 "Cannot open '%s'", devname);
255 usalfiles(usalp)[i] = f;
259 if (usalp->local != NULL) {
263 usalp->ops = &sun_uscsi_ops;
264 return (SCGO_OPEN(usalp, device));
271 usalo_close(SCSI *usalp)
275 if (usalp->local == NULL)
278 for (i = 0; i < MAX_SCG; i++) {
279 if (usalfiles(usalp)[i] >= 0)
280 close(usalfiles(usalp)[i]);
281 usalfiles(usalp)[i] = -1;
287 usalo_maxdma(SCSI *usalp, long amt)
289 long maxdma = MAX_DMA_OTHER;
290 #if !defined(__i386_) && !defined(i386)
294 #if defined(__i386_) || defined(i386)
295 maxdma = MAX_DMA_SUN386;
297 cpu_type = gethostid() >> 24;
299 switch (cpu_type & ARCH_MASK) {
303 maxdma = MAX_DMA_SUN4C;
308 maxdma = MAX_DMA_SUN4M;
312 maxdma = MAX_DMA_SUN3;
318 * SunOS 4.x allows esp hardware on VME boards and thus
319 * limits DMA on esp to 64k-1
321 if (maxdma > MAX_DMA_SUN3)
322 maxdma = MAX_DMA_SUN3;
328 usalo_havebus(SCSI *usalp, int busno)
330 if (usalp->local == NULL)
333 return (busno < 0 || busno >= MAX_SCG) ? FALSE : (usalfiles(usalp)[busno] >= 0);
337 usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
339 if (usalp->local == NULL)
342 return ((busno < 0 || busno >= MAX_SCG) ? -1 : usalfiles(usalp)[busno]);
346 usalo_initiator_id(SCSI *usalp)
350 struct dk_cinfo conf;
356 if (ioctl(usalp->fd, DKIO_GETCINFO, &conf) < 0)
358 if (TARGET(conf.dki_slave) != -1)
359 id = TARGET(conf.dki_slave);
365 usalo_isatapi(SCSI *usalp)
371 usalo_reset(SCSI *usalp, int what)
373 if (what == SCG_RESET_NOP)
375 if (what != SCG_RESET_BUS) {
379 return (ioctl(usalp->fd, SCGIORESET, 0));
383 usalo_getbuf(SCSI *usalp, long amt)
385 usalp->bufbase = (void *)valloc((size_t)amt);
386 return (usalp->bufbase);
390 usalo_freebuf(SCSI *usalp)
393 free(usalp->bufbase);
394 usalp->bufbase = NULL;
398 usalo_send(SCSI *usalp)
400 usalp->scmd->target = usal_target(usalp);
401 return (ioctl(usalp->fd, SCGIO_CMD, usalp->scmd));
404 /*--------------------------------------------------------------------------*/
406 * This is Sun USCSI interface code ...
409 #include <sys/scsi/impl/uscsi.h>
412 * Bit Mask definitions, for use accessing the status as a byte.
414 #define STATUS_MASK 0x3E
415 #define STATUS_GOOD 0x00
416 #define STATUS_CHECK 0x02
418 #define STATUS_RESERVATION_CONFLICT 0x18
419 #define STATUS_TERMINATED 0x22
422 #define STATUS_MASK 0x3E
423 #define STATUS_GOOD 0x00
424 #define STATUS_CHECK 0x02
426 #define STATUS_MET 0x04
427 #define STATUS_BUSY 0x08
428 #define STATUS_INTERMEDIATE 0x10
429 #define STATUS_SCSI2 0x20
430 #define STATUS_INTERMEDIATE_MET 0x14
431 #define STATUS_RESERVATION_CONFLICT 0x18
432 #define STATUS_TERMINATED 0x22
433 #define STATUS_QFULL 0x28
434 #define STATUS_ACA_ACTIVE 0x30
438 usalo_uhelp(SCSI *usalp, FILE *f)
440 __usal_help(f, "USCSI", "SCSI transport for targets known by Solaris drivers",
441 "USCSI:", "bus,target,lun", "USCSI:1,2,0", TRUE, TRUE);
446 usalo_uopen(SCSI *usalp, char *device)
448 int busno = usal_scsibus(usalp);
449 int tgt = usal_target(usalp);
450 int tlun = usal_lun(usalp);
455 register int nopen = 0;
459 have_volmgt = volmgt_running();
461 if (usalp->overbose) {
462 fprintf((FILE *)usalp->errfile,
463 "Warning: Using USCSI interface.\n");
467 * SEEK_HOLE first appears in Solaris 11 Build 14, volmgt supports
468 * medialess drives since Build 21. Using SEEK_HOLD as indicator
469 * seems to be the best guess.
471 if (usalp->overbose > 0 && have_volmgt) {
472 fprintf((FILE *)usalp->errfile,
473 "Warning: Volume management is running, medialess managed drives are invisible.\n");
477 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
480 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
481 "Illegal value for busno, target or lun '%d,%d,%d'",
486 if (usalp->local == NULL) {
487 usalp->local = malloc(sizeof (struct usal_local));
488 if (usalp->local == NULL) {
490 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE, "No memory for usal_local");
494 for (b = 0; b < MAX_SCG; b++) {
495 for (t = 0; t < MAX_TGT; t++) {
496 for (l = 0; l < MAX_LUN; l++)
497 usallocal(usalp)->u.usal_files[b][t][l] = (short)-1;
502 if (device != NULL && strcmp(device, "USCSI") == 0)
505 if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2))
509 if (busno >= 0 && tgt >= 0 && tlun >= 0) {
511 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN)
514 snprintf(devname, sizeof (devname), "/dev/rdsk/c%dt%dd%ds2",
516 f = open(devname, O_RDONLY | O_NDELAY);
517 if (f < 0 && geterrno() == EBUSY)
518 f = usalo_volopen(usalp, devname);
520 snprintf(usalp->errstr,
522 "Cannot open '%s'", devname);
525 usallocal(usalp)->u.usal_files[busno][tgt][tlun] = f;
529 for (b = 0; b < MAX_SCG; b++) {
530 for (t = 0; t < MAX_TGT; t++) {
531 for (l = 0; l < MAX_LUN; l++) {
532 snprintf(devname, sizeof (devname),
533 "/dev/rdsk/c%dt%dd%ds2",
535 f = open(devname, O_RDONLY | O_NDELAY);
536 if (f < 0 && geterrno() == EBUSY) {
537 f = usalo_volopen(usalp, devname);
539 * Hack to mark inaccessible
540 * drives with fd == -2
543 usallocal(usalp)->u.usal_files[b][t][l] < 0)
544 usallocal(usalp)->u.usal_files[b][t][l] = f;
546 if (f < 0 && errno != ENOENT &&
550 snprintf(usalp->errstr,
552 "Cannot open '%s'", devname);
558 if (usallocal(usalp)->u.usal_files[b][t][l] == -1)
559 usallocal(usalp)->u.usal_files[b][t][l] = f;
572 if (device != NULL && strncmp(device, "USCSI:", 6) == 0)
574 if (device == NULL || device[0] == '\0')
577 f = open(device, O_RDONLY | O_NDELAY);
579 f = usalo_volopen(usalp, device);
581 snprintf(usalp->errstr,
583 "Cannot open '%s'", device);
588 busno = 0; /* Use Fake number if not specified */
590 if (usalo_ugettlun(f, &target, &lun) >= 0) {
591 if (tgt >= 0 && tlun >= 0) {
592 if (tgt != target || tlun != lun) {
600 if (tgt < 0 || tlun < 0) {
606 if (usallocal(usalp)->u.usal_files[busno][tgt][tlun] == -1)
607 usallocal(usalp)->u.usal_files[busno][tgt][tlun] = f;
608 usal_settarget(usalp, busno, tgt, tlun);
616 usalo_volopen(SCSI *usalp, char *devname)
618 int oerr = geterrno();
620 char *name = NULL; /* Volume symbolic device name */
621 char *symdev = NULL; /* /dev/... name based on "name" */
622 char *mname = NULL; /* Volume media name based on "name" */
630 if (usalp->debug > 0) {
631 fprintf((FILE *)usalp->errfile,
632 "usalo_volopen(%s)\n", devname);
636 * We come here because trying to open "devname" did not work.
637 * First try to translate between a symbolic name and a /dev/...
638 * based device name. Then translate back to a symbolic name.
640 symdev = volmgt_symdev(devname);
642 name = volmgt_symname(symdev);
643 if (usalp->debug > 0) {
644 fprintf((FILE *)usalp->errfile,
645 "volmgt_symdev(%s)=%s -> %s\n", devname, symdev, name);
649 * If "devname" is not a symbolic device name, then it must be
650 * a /dev/... based device name. Try to translate it into a
651 * symbolic name. Then translate back to a /dev/... name.
654 name = volmgt_symname(devname);
656 symdev = volmgt_symdev(name);
658 if (usalp->debug > 0) {
659 fprintf((FILE *)usalp->errfile,
660 "volmgt_symdev(%s)=%s -> %s\n", devname, symdev, name);
664 * If we have been able to translate to a symbolic device name,
665 * translate this name into a volume management media name that
666 * may be used for opening.
669 mname = media_findname(name);
670 if (usalp->debug > 0) {
671 fprintf((FILE *)usalp->errfile,
672 "symdev %s name %s mname %s\n", symdev, name, mname);
676 * Das scheint nur mit dem normierten /dev/rdsk/ *s2 Namen zu gehen.
678 if (usalp->debug > 0) {
679 fprintf((FILE *)usalp->errfile,
680 "volmgt_inuse(%s) %d\n", symdev, volmgt_inuse(symdev));
683 f = usalo_openmedia(usalp, mname);
685 f = -2; /* Mark inaccessible drives with fd == -2 */
688 * Besonderen Fehlertext oder fprintf/errfile bei non-scanbus Open und
689 * wenn errrno == EBUSY && kein Mapping?
705 usalo_openmedia(SCSI *usalp, char *mname)
715 * Check whether the media name refers to a directory.
716 * In this case, the medium is partitioned and we need to
717 * check all partitions.
719 if (stat(mname, &sb) >= 0) {
720 if (S_ISDIR(sb.st_mode)) {
725 * First check partition '2', the whole disk.
727 snprintf(name, sizeof (name), "%s/s2", mname);
728 f = open(name, O_RDONLY | O_NDELAY);
732 * Now try all other partitions.
734 for (i = 0; i < 16; i++) {
737 snprintf(name, sizeof (name),
739 if (stat(name, &sb) >= 0)
750 f = open(device, O_RDONLY | O_NDELAY);
755 usalo_uclose(SCSI *usalp)
762 if (usalp->local == NULL)
765 for (b = 0; b < MAX_SCG; b++) {
766 for (t = 0; t < MAX_TGT; t++) {
767 for (l = 0; l < MAX_LUN; l++) {
768 f = usallocal(usalp)->u.usal_files[b][t][l];
771 usallocal(usalp)->u.usal_files[b][t][l] = (short)-1;
779 usalo_ucinfo(int f, struct dk_cinfo *cp, int debug)
781 fillbytes(cp, sizeof (*cp), '\0');
783 if (ioctl(f, DKIOCINFO, cp) < 0)
789 fprintf(stderr, "cname: '%s'\n", cp->dki_cname);
790 fprintf(stderr, "ctype: 0x%04hX %hd\n", cp->dki_ctype, cp->dki_ctype);
791 fprintf(stderr, "cflags: 0x%04hX\n", cp->dki_flags);
792 fprintf(stderr, "cnum: %hd\n", cp->dki_cnum);
794 fprintf(stderr, "addr: %d\n", cp->dki_addr);
795 fprintf(stderr, "space: %d\n", cp->dki_space);
796 fprintf(stderr, "prio: %d\n", cp->dki_prio);
797 fprintf(stderr, "vec: %d\n", cp->dki_vec);
799 fprintf(stderr, "dname: '%s'\n", cp->dki_dname);
800 fprintf(stderr, "unit: %d\n", cp->dki_unit);
801 fprintf(stderr, "slave: %d %04o Tgt: %d Lun: %d\n",
802 cp->dki_slave, cp->dki_slave,
803 TARGET(cp->dki_slave), LUN(cp->dki_slave));
804 fprintf(stderr, "partition: %hd\n", cp->dki_partition);
805 fprintf(stderr, "maxtransfer: %d (%d)\n",
807 cp->dki_maxtransfer * DEV_BSIZE);
812 usalo_ugettlun(int f, int *tgtp, int *lunp)
816 if (usalo_ucinfo(f, &ci, 0) < 0)
819 *tgtp = TARGET(ci.dki_slave);
821 *lunp = LUN(ci.dki_slave);
826 usalo_umaxdma(SCSI *usalp, long amt)
834 BOOL found_ide = FALSE;
836 if (usalp->local == NULL)
839 for (b = 0; b < MAX_SCG; b++) {
840 for (t = 0; t < MAX_TGT; t++) {
841 for (l = 0; l < MAX_LUN; l++) {
842 if ((f = usallocal(usalp)->u.usal_files[b][t][l]) < 0)
844 if (usalo_ucinfo(f, &ci, usalp->debug) < 0)
847 maxdma = (long)(ci.dki_maxtransfer * DEV_BSIZE);
848 if (maxdma > (long)(ci.dki_maxtransfer * DEV_BSIZE))
849 maxdma = (long)(ci.dki_maxtransfer * DEV_BSIZE);
850 if (streql(ci.dki_cname, "ide"))
856 #if defined(__i386_) || defined(i386)
858 * At least on Solaris 9 x86, DKIOCINFO returns a wrong value
859 * for dki_maxtransfer if the target is an ATAPI drive.
860 * Without DMA, it seems to work if we use 256 kB DMA size for ATAPI,
861 * but if we allow DMA, only 68 kB will work (for more we get a silent
862 * DMA residual count == DMA transfer count).
863 * For this reason, we try to figure out the correct value for 'ide'
864 * by retrieving the (correct) value from a ide hard disk.
867 if ((f = usalo_openide()) >= 0) {
869 long omaxdma = maxdma;
872 if (usalo_ucinfo(f, &ci, usalp->debug) >= 0) {
874 maxdma = (long)(ci.dki_maxtransfer * DEV_BSIZE);
875 if (maxdma > (long)(ci.dki_maxtransfer * DEV_BSIZE))
876 maxdma = (long)(ci.dki_maxtransfer * DEV_BSIZE);
881 * The kernel returns 56 kB but we tested that 68 kB works.
883 if (omaxdma > maxdma && maxdma == (112 * DEV_BSIZE))
884 maxdma = 136 * DEV_BSIZE;
888 * No IDE disk on this system?
890 if (maxdma == (512 * DEV_BSIZE))
891 maxdma = MAX_DMA_SUN386;
896 * The Sun tape driver does not support to retrieve the max DMA count.
897 * Use the knwoledge about default DMA sizes in this case.
900 maxdma = usalo_maxdma(usalp, amt);
905 #if defined(__i386_) || defined(i386)
914 for (b = 0; b < 5; b++) {
915 for (t = 0; t < 2; t++) {
916 snprintf(buf, sizeof (buf),
917 "/dev/rdsk/c%dd%dp0", b, t);
918 if ((f = open(buf, O_RDONLY | O_NDELAY)) >= 0)
928 usalo_uhavebus(SCSI *usalp, int busno)
933 if (usalp->local == NULL || busno < 0 || busno >= MAX_SCG)
936 for (t = 0; t < MAX_TGT; t++) {
937 for (l = 0; l < MAX_LUN; l++)
938 if (usallocal(usalp)->u.usal_files[busno][t][l] >= 0)
945 usalo_ufileno(SCSI *usalp, int busno, int tgt, int tlun)
947 if (usalp->local == NULL ||
948 busno < 0 || busno >= MAX_SCG ||
949 tgt < 0 || tgt >= MAX_TGT ||
950 tlun < 0 || tlun >= MAX_LUN)
953 return ((int)usallocal(usalp)->u.usal_files[busno][tgt][tlun]);
957 usalo_uinitiator_id(SCSI *usalp)
963 usalo_uisatapi(SCSI *usalp)
966 char symlinkname[MAXPATHLEN];
970 if (ioctl(usalp->fd, DKIOCINFO, &ci) < 0)
973 snprintf(devname, sizeof (devname), "/dev/rdsk/c%dt%dd%ds2",
974 usal_scsibus(usalp), usal_target(usalp), usal_lun(usalp));
976 symlinkname[0] = '\0';
977 len = readlink(devname, symlinkname, sizeof (symlinkname));
979 symlinkname[len] = '\0';
981 if (len >= 0 && strstr(symlinkname, "ide") != NULL)
988 usalo_ureset(SCSI *usalp, int what)
990 struct uscsi_cmd req;
992 if (what == SCG_RESET_NOP)
995 fillbytes(&req, sizeof (req), '\0');
997 if (what == SCG_RESET_TGT) {
998 req.uscsi_flags = USCSI_RESET | USCSI_SILENT; /* reset target */
999 } else if (what != SCG_RESET_BUS) {
1000 req.uscsi_flags = USCSI_RESET_ALL | USCSI_SILENT; /* reset bus */
1006 return (ioctl(usalp->fd, USCSICMD, &req));
1010 usalo_usend(SCSI *usalp)
1012 struct usal_cmd *sp = usalp->scmd;
1013 struct uscsi_cmd req;
1015 static uid_t cureuid = 0; /* XXX Hack until we have uid management */
1017 if (usalp->fd < 0) {
1018 sp->error = SCG_FATAL;
1022 fillbytes(&req, sizeof (req), '\0');
1024 req.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_RQENABLE;
1026 if (sp->flags & SCG_RECV_DATA) {
1027 req.uscsi_flags |= USCSI_READ;
1028 } else if (sp->size > 0) {
1029 req.uscsi_flags |= USCSI_WRITE;
1031 req.uscsi_buflen = sp->size;
1032 req.uscsi_bufaddr = sp->addr;
1033 req.uscsi_timeout = sp->timeout;
1034 req.uscsi_cdblen = sp->cdb_len;
1035 req.uscsi_rqbuf = (caddr_t) sp->u_sense.cmd_sense;
1036 req.uscsi_rqlen = sp->sense_len;
1037 req.uscsi_cdb = (caddr_t) &sp->cdb;
1043 ret = ioctl(usalp->fd, USCSICMD, &req);
1045 if (ret < 0 && geterrno() == EPERM) { /* XXX Hack until we have uid management */
1046 cureuid = geteuid();
1047 if (seteuid(0) >= 0)
1053 if (usalp->debug > 0) {
1054 fprintf((FILE *)usalp->errfile, "ret: %d errno: %d (%s)\n", ret, errno, errmsgstr(errno));
1055 fprintf((FILE *)usalp->errfile, "uscsi_flags: 0x%x\n", req.uscsi_flags);
1056 fprintf((FILE *)usalp->errfile, "uscsi_status: 0x%x\n", req.uscsi_status);
1057 fprintf((FILE *)usalp->errfile, "uscsi_timeout: %d\n", req.uscsi_timeout);
1058 fprintf((FILE *)usalp->errfile, "uscsi_bufaddr: 0x%lx\n", (long)req.uscsi_bufaddr);
1060 * Cast auf int OK solange sp->size
1061 * auch ein int bleibt.
1063 fprintf((FILE *)usalp->errfile, "uscsi_buflen: %d\n", (int)req.uscsi_buflen);
1064 fprintf((FILE *)usalp->errfile, "uscsi_resid: %d\n", (int)req.uscsi_resid);
1065 fprintf((FILE *)usalp->errfile, "uscsi_rqlen: %d\n", req.uscsi_rqlen);
1066 fprintf((FILE *)usalp->errfile, "uscsi_rqstatus: 0x%x\n", req.uscsi_rqstatus);
1067 fprintf((FILE *)usalp->errfile, "uscsi_rqresid: %d\n", req.uscsi_rqresid);
1068 fprintf((FILE *)usalp->errfile, "uscsi_rqbuf ptr: 0x%lx\n", (long)req.uscsi_rqbuf);
1069 fprintf((FILE *)usalp->errfile, "uscsi_rqbuf: ");
1070 if (req.uscsi_rqbuf != NULL && req.uscsi_rqlen > req.uscsi_rqresid) {
1072 int len = req.uscsi_rqlen - req.uscsi_rqresid;
1074 for (i = 0; i < len; i++) {
1075 fprintf((FILE *)usalp->errfile, "0x%02X ", ((char *)req.uscsi_rqbuf)[i]);
1077 fprintf((FILE *)usalp->errfile, "\n");
1079 fprintf((FILE *)usalp->errfile, "<data not available>\n");
1083 sp->ux_errno = geterrno();
1085 * Check if SCSI command cound not be send at all.
1087 if (sp->ux_errno == ENOTTY && usalo_uisatapi(usalp) == TRUE) {
1088 if (usalp->debug > 0) {
1089 fprintf((FILE *)usalp->errfile,
1090 "ENOTTY atapi: %d\n", usalo_uisatapi(usalp));
1092 sp->error = SCG_FATAL;
1095 if (errno == ENXIO) {
1096 sp->error = SCG_FATAL;
1099 if (errno == ENOTTY || errno == EINVAL || errno == EACCES) {
1106 sp->sense_count = req.uscsi_rqlen - req.uscsi_rqresid;
1107 sp->resid = req.uscsi_resid;
1108 sp->u_scb.cmd_scb[0] = req.uscsi_status;
1110 if ((req.uscsi_status & STATUS_MASK) == STATUS_GOOD) {
1111 sp->error = SCG_NO_ERROR;
1114 if (req.uscsi_rqstatus == 0 &&
1115 ((req.uscsi_status & STATUS_MASK) == STATUS_CHECK)) {
1116 sp->error = SCG_NO_ERROR;
1119 if (req.uscsi_status & (STATUS_TERMINATED |
1120 STATUS_RESERVATION_CONFLICT)) {
1121 sp->error = SCG_FATAL;
1123 if (req.uscsi_status != 0) {
1125 * This is most likely wrong. There seems to be no way
1126 * to produce SCG_RETRYABLE with USCSI.
1128 sp->error = SCG_RETRYABLE;
1133 #endif /* USE_USCSI */