1 /* @(#)scsi-openserver.c 1.35 10/05/24 Copyright 1998-2010 J. Schilling, Copyright 1998,2000 Santa Cruz Operation */
2 #ifndef lint
3 static char __sccsid[] =
4 "@(#)scsi-openserver.c 1.35 10/05/24 Copyright 1998-2010 J. Schilling, Copyright 1998,2000 Santa Cruz Operation";
5 #endif
6 /*
7 * Interface for the SCO SCSI implementation.
8 *
9 * Warning: you may change this source, but if you do that
10 * you need to change the _scg_version and _scg_auth* string below.
11 * You may not return "schily" for an SCG_AUTHOR request anymore.
12 * Choose your name instead of "schily" and make clear that the version
13 * string is related to a modified source.
14 *
15 * Copyright (c) 1998-2010 J. Schilling
16 * Copyright (c) 1998,2000 Santa Cruz Operation
17 */
18 /*
19 * The contents of this file are subject to the terms of the
20 * Common Development and Distribution License, Version 1.0 only
21 * (the "License"). You may not use this file except in compliance
22 * with the License.
23 *
24 * See the file CDDL.Schily.txt in this distribution for details.
25 * A copy of the CDDL is also available via the Internet at
26 * http://www.opensource.org/licenses/cddl1.txt
27 *
28 * The following exceptions apply:
29 * CDDL �3.6 needs to be replaced by: "You may create a Larger Work by
30 * combining Covered Software with other code if all other code is governed by
31 * the terms of a license that is OSI approved (see www.opensource.org) and
32 * you may distribute the Larger Work as a single product. In such a case,
33 * You must make sure the requirements of this License are fulfilled for
34 * the Covered Software."
35 *
36 * When distributing Covered Code, include this CDDL HEADER in each
37 * file and include the License file CDDL.Schily.txt from this distribution.
38 */
39
40 #undef sense
41
42 #include <sys/scsicmd.h>
43
44 /*
45 * Warning: you may change this source, but if you do that
46 * you need to change the _scg_version and _scg_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.
50 */
51 LOCAL char _scg_trans_version[] = "scsi-openserver.c-1.35"; /* The version for this transport*/
52
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 */
56
57 #define MAX_DMA (64*1024)
58
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 */
63
64 #define DEV_DIR "/tmp"
65 #define DEV_NAME "scg.s%1dt%1dl%1d"
66
67 /*
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
72 * devices.
73 *
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!
77 */
78
79 #define DEV_ROOT "/dev/dsk/0s0"
80
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"
85
86 #define SCAN_DEV "%s%s%d%d%d%d"
87
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 */
90
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, */
94 /* but missing ! */
95
96
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 */
101
102
103 /*
104 * ---------------------------------------------------------------------
105 * Environment variables to control certain functionality
106 */
107
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 */
112
113 LOCAL int scan_all = 0; /* don't scan all devices by default */
114 LOCAL int scsiusercmd = 0; /* use SCSIUSERCMD2 ioctl by default */
115 LOCAL int enable_usb = 0; /* don't scan USB devices by default */
116 LOCAL long max_dma = MAX_DMA; /* use MAX_DMA DMA buffer by default */
117
118
119 /*
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].
123 *
124 * The SCSIUSERCMD ioctl is available on all OpenServer 5
125 *
126 * The SCSIUSERCMD2 ioctl which executes the usercmd and reads the sense
127 * in one go, is only available from 5.0.4 onwards.
128 *
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 separate
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 !!!
137 *
138 * NOTE: There are problems with the usage of AHA 154X controllers
139 * and SCSIUSERCMD2 such as nonsense (weird) output on cdrecord -scanbus
140 *
141 */
142
143
144 typedef struct scg2sdi {
145
146 int valid;
147 int open;
148 int atapi;
149 int fd;
150 int lmscsi;
151
152 } scg2sdi_t;
153
154 LOCAL scg2sdi_t sdidevs [MAX_SCG][MAX_TGT][MAX_LUN];
155
156 typedef struct amscsi {
157 char typ[MAXDRVN];
158 char drv[MAXDRVN];
159 int hba;
160 int bus;
161 int scg;
162 int tgt;
163 int lun;
164 char dev[MAXPATH];
165
166 } amscsi_t;
167
168 struct scg_local {
169 short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
170 };
171 #define scglocal(p) ((struct scg_local *)((p)->local))
172
173 LOCAL int sort_mscsi __PR((const void *l1, const void *l2));
174 LOCAL int openserver_init __PR((SCSI *scgp));
175 LOCAL void cp_scg2sco __PR((struct scsicmd2 *sco, struct scg_cmd *scg));
176 LOCAL void cp_sco2scg __PR((struct scsicmd2 *sco, struct scg_cmd *scg));
177
178 /*
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.
185 *
186 * This passthrough implementation for libscg currently allows to
187 * handle the following devices classes:
188 *
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
193 *
194 * NOTE: The libscg 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.
198 *
199 * ===============================================================
200 * RUN 'cdrecord -scanbus' TO SEE THE DEVICE ADDRESSES YOU CAN USE
201 * ===============================================================
202 *
203 */
204
205 /*
206 * Return version information for the low level SCSI transport code.
207 * This has been introduced to make it easier to trace down problems
208 * in applications.
209 */
210 LOCAL char *
scgo_version(scgp,what)211 scgo_version(scgp, what)
212 SCSI *scgp;
213 int what;
214 {
215 if (scgp != (SCSI *)0) {
216 switch (what) {
217
218 case SCG_VERSION:
219 return (_scg_trans_version);
220 /*
221 * If you changed this source, you are not allowed to
222 * return "schily" for the SCG_AUTHOR request.
223 */
224 case SCG_AUTHOR:
225 return (_scg_auth_schily);
226 case SCG_SCCS_ID:
227 return (__sccsid);
228 }
229 }
230 return ((char *)0);
231 }
232
233 LOCAL int
scgo_help(scgp,f)234 scgo_help(scgp, f)
235 SCSI *scgp;
236 FILE *f;
237 {
238 __scg_help(f, "SCSIUSERCMD/SCSIUSERCMD2", "Generic SCSI",
239 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
240 return (0);
241 }
242
243 /*
244 * ---------------------------------------------------------------
245 * This routine sorts the amscsi_t lines on the following columns
246 * in ascending order:
247 *
248 * 1. drv - driver name
249 * 2. bus - scsibus per controller
250 * 3. tgt - target id of device
251 * 4. lun - lun of the device
252 *
253 */
254
255
256 LOCAL int
sort_mscsi(l1,l2)257 sort_mscsi(l1, l2)
258 const void *l1;
259 const void *l2;
260 {
261 amscsi_t *t1 = (amscsi_t *) l1;
262 amscsi_t *t2 = (amscsi_t *) l2;
263
264 if (strcmp(t1->drv, t2->drv) == 0) {
265 if (t1->bus < t2->bus) {
266 return (-1);
267
268 } else if (t1->bus > t2->bus) {
269 return (1);
270
271 } else if (t1->tgt < t2->tgt) {
272 return (-1);
273
274 } else if (t1->tgt > t2->tgt) {
275 return (1);
276
277 } else if (t1->lun < t2->lun) {
278 return (-1);
279
280 } else if (t1->lun > t2->lun) {
281 return (1);
282 } else {
283 return (0);
284 }
285 } else {
286 return (strcmp(t1->drv, t2->drv));
287 }
288 }
289
290 /*
291 * ---------------------------------------------------------------
292 * This routine is introduced to find all scsi devices which are
293 * currently configured into the kernel. This is done by reading
294 * the dynamic kernel mscsi tables and parse the resulting lines.
295 * As the output of 'sconf' is not directly usable the information
296 * found is to be sorted and re-arranged to be used with the libscg
297 * routines.
298 *
299 * NOTE: One problem is currently still not solved ! If you don't
300 * have a media in your CD-ROM/CD-Writer we are not able to
301 * do an open() and therefore will set the drive to be not
302 * available (valid=0).
303 *
304 * This will for example cause cdrecord to not list the drive
305 * in the -scanbus output.
306 *
307 */
308
309 LOCAL int
openserver_init(scgp)310 openserver_init(scgp)
311 SCSI *scgp;
312 {
313 FILE *cmd;
314 int nscg = -1, lhba = -1, lbus = -1;
315 int nSrom = -1, nSdsk = -1, nStp = -1, nSflp = -1;
316 int atapi, fd, nopen = 0;
317 int pos = 0, len = 0, nlm = 0;
318 int s = 0, t = 0, l = 0;
319 int ide_rootdisk = 0;
320 long dma_override = 0;
321 int mscsi;
322 char sconf[MAXLINE];
323 char lines[MAXLINE];
324 char drvid[MAXDRVN];
325 amscsi_t cmtbl[MAXSCSI];
326 char dname[MAXPATH];
327 char **evsave;
328 extern char **environ;
329
330
331 for (s = 0; s < MAX_SCG; s++) {
332 for (t = 0; t < MAX_TGT; t++) {
333 for (l = 0; l < MAX_LUN; l++) {
334 sdidevs[s][t][l].valid = 0;
335 sdidevs[s][t][l].open = -1;
336 sdidevs[s][t][l].atapi = -1;
337 sdidevs[s][t][l].fd = -1;
338 sdidevs[s][t][l].lmscsi = -1;
339 }
340 }
341 }
342
343 /* Check whether we want to use the older SCSIUSERCMD ioctl() */
344
345 if (getenv(SCSI_USER_CMD) != NULL) {
346 scsiusercmd = 1;
347 }
348
349 /*
350 * Check whether we want to scan all devices
351 */
352 if (getenv(SCAN_ALL) != NULL) {
353 scan_all = 1;
354 }
355
356 /*
357 * Check whether we want to use USB devices
358 */
359 if (getenv(ENABLE_USB) != NULL) {
360 enable_usb = 1;
361 }
362
363 /*
364 * Check whether we want to override the MAX_DMA value
365 */
366 if (getenv(DMA_OVERRIDE) != NULL) {
367 dma_override = atol(getenv(DMA_OVERRIDE));
368 if ((dma_override >= 1) && (dma_override <= (256)))
369 max_dma = dma_override * 1024;
370 }
371
372
373 /* read sconf -r and get number of kernel mscsi lines ! */
374
375 evsave = environ;
376 environ = 0;
377 if ((cmd = popen(SCSI_CFG, "r")) == NULL) {
378 if (scgp->errstr)
379 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
380 "Error popen() for \"%s\"",
381 SCSI_CFG);
382 environ = evsave;
383 return (-1);
384 }
385 environ = evsave;
386
387 if (fgets(lines, MAXLINE, cmd) == NULL) {
388 errno = EIO;
389 if (scgp->errstr)
390 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
391 "Error reading popen() for \"%s\"",
392 SCSI_CFG);
393 return (-1);
394 } else
395 nlm = atoi(lines);
396
397 if (scgp->debug > 0) {
398 js_fprintf((FILE *)scgp->errfile, "-------------------- \n");
399 js_fprintf((FILE *)scgp->errfile, "mscsi lines = %d\n", nlm);
400 js_fprintf((FILE *)scgp->errfile, "-------------------- \n");
401 }
402
403 if (pclose(cmd) == -1) {
404 if (scgp->errstr)
405 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
406 "Error pclose() for \"%s\"",
407 SCSI_CFG);
408 return (-1);
409 }
410
411 for (l = 0; l < nlm; l++) {
412
413 /* initialize cmtbl entry */
414
415 cmtbl[l].hba = -1;
416 cmtbl[l].bus = -1;
417 cmtbl[l].tgt = -1;
418 cmtbl[l].lun = -1;
419 cmtbl[l].scg = -1;
420
421 memset(cmtbl[l].typ, '\0', MAXDRVN);
422 memset(cmtbl[l].drv, '\0', MAXDRVN);
423 memset(cmtbl[l].dev, '\0', MAXDRVN);
424
425 /* read sconf -g 'n' and get line of kernel mscsi table! */
426 /* the order the lines will be received in will determine */
427 /* the device name we can use to open the device */
428
429 js_snprintf(sconf, sizeof (sconf),
430 SCSI_DEV, l + 1); /* enumeration starts with 1 */
431
432 evsave = environ;
433 environ = 0;
434 if ((cmd = popen(sconf, "r")) == NULL) {
435 if (scgp->errstr)
436 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
437 "Error popen() for \"%s\"",
438 sconf);
439 environ = evsave;
440 return (-1);
441 }
442 environ = evsave;
443
444 if (fgets(lines, MAXLINE, cmd) == NULL)
445 break;
446
447 if (pclose(cmd) == -1) {
448 if (scgp->errstr)
449 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
450 "Error pclose() for \"%s\"",
451 sconf);
452 return (-1);
453 }
454
455 sscanf(lines, SCAN_DEV, cmtbl[l].typ,
456 cmtbl[l].drv,
457 &cmtbl[l].hba,
458 &cmtbl[l].bus,
459 &cmtbl[l].tgt,
460 &cmtbl[l].lun);
461
462 if (strstr(cmtbl[l].typ, T_DISK) != NULL) {
463 js_snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
464 DEV_SDSK, ++nSdsk);
465 }
466
467 if (strstr(cmtbl[l].typ, T_CDROM) != NULL) {
468 js_snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
469 DEV_SROM, ++nSrom);
470 }
471
472 if (strstr(cmtbl[l].typ, T_TAPE) != NULL) {
473 js_snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
474 DEV_STP, ++nStp);
475 }
476
477 if (strstr(cmtbl[l].typ, T_FLOPPY) != NULL) {
478 js_snprintf(cmtbl[l].dev, sizeof (cmtbl[l].dev),
479 DEV_SFLP, ++nSflp);
480 }
481
482 if (scgp->debug > 0) {
483 js_fprintf((FILE *)scgp->errfile,
484 "%-4s = %5s(%d,%d,%d,%d) -> %s\n",
485 cmtbl[l].typ,
486 cmtbl[l].drv,
487 cmtbl[l].hba,
488 cmtbl[l].bus,
489 cmtbl[l].tgt,
490 cmtbl[l].lun,
491 cmtbl[l].dev);
492 }
493
494 }
495
496 if (scgp->debug > 0) {
497 js_fprintf((FILE *)scgp->errfile, "-------------------- \n");
498 js_fprintf((FILE *)scgp->errfile, "%2d DISK \n", nSdsk + 1);
499 js_fprintf((FILE *)scgp->errfile, "%2d CD-ROM\n", nSrom + 1);
500 js_fprintf((FILE *)scgp->errfile, "%2d TAPE \n", nStp + 1);
501 js_fprintf((FILE *)scgp->errfile, "%2d FLOPPY\n", nSflp + 1);
502 js_fprintf((FILE *)scgp->errfile, "-------------------- \n");
503 }
504
505 /* ok, now let's sort this array of scsi devices */
506
507 qsort((void *) cmtbl, nlm, sizeof (amscsi_t), sort_mscsi);
508
509 if (scgp->debug > 0) {
510 for (l = 0; l < nlm; l++)
511 js_fprintf((FILE *)scgp->errfile,
512 "%-4s = %5s(%d,%d,%d,%d) -> %s\n",
513 cmtbl[l].typ,
514 cmtbl[l].drv,
515 cmtbl[l].hba,
516 cmtbl[l].bus,
517 cmtbl[l].tgt,
518 cmtbl[l].lun,
519 cmtbl[l].dev);
520 js_fprintf((FILE *)scgp->errfile, "-------------------- \n");
521 }
522
523 /* find root disk controller to make it scg 0 */
524
525 /*
526 * if we have disk(s) found in the mscsi table, we still
527 * don't know if the rootdisk is among these, there can
528 * be a IDE rootdisk as well, but it's not listed in
529 * the mscsi table.
530 */
531
532 t = 0;
533 if (nSdsk > 0) {
534 for (l = 0; l < nlm; l++)
535 if (strcmp(cmtbl[l].dev, DEV_ROOT) == 0)
536 t = l;
537 } else {
538
539 /*
540 * we haven't found a disk in mscsi, so we definitely
541 * have an IDE disk on a wd adapter as IDE disks are
542 * not listed as SCSI disks in the kernel mscsi table
543 */
544 ide_rootdisk = 1;
545
546 }
547
548 if (!(ide_rootdisk) && (scgp->debug > 0)) {
549 js_fprintf((FILE *)scgp->errfile,
550 "root = %5s(%d,%d,%d,%d) -> %s\n",
551 cmtbl[t].drv,
552 cmtbl[t].hba,
553 cmtbl[t].bus,
554 cmtbl[t].tgt,
555 cmtbl[t].lun,
556 cmtbl[t].dev);
557 js_fprintf((FILE *)scgp->errfile, "-------------------- \n");
558 }
559
560 /* calculate scg from drv, hba and bus */
561
562 strcpy(drvid, "");
563
564 for (l = 0, s = t; l < nlm; l++, s = (t + l) % nlm) {
565
566 if (strcmp(drvid, cmtbl[s].drv) != 0) {
567 strcpy(drvid, cmtbl[s].drv);
568 lhba = cmtbl[s].hba;
569 lbus = cmtbl[s].bus;
570 cmtbl[s].scg = ++nscg;
571
572 } else if (cmtbl[s].hba != lhba) {
573 lhba = cmtbl[s].hba;
574 lbus = cmtbl[s].bus;
575 cmtbl[s].scg = ++nscg;
576
577 } else if (cmtbl[s].bus != lbus) {
578 lbus = cmtbl[s].bus;
579 cmtbl[s].scg = ++nscg;
580 } else {
581 cmtbl[s].scg = nscg;
582 }
583 sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].open = 0;
584
585 /* check whether we want to open all devices or it's a CDROM */
586
587 if ((scan_all) || (strcmp(cmtbl[s].typ, T_CDROM) == 0))
588 sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].valid = 1;
589
590 /* check whether we have an IDE/ATAPI device */
591
592 if (strcmp(cmtbl[s].drv, DRV_ATAPI) == 0)
593 sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].atapi = 1;
594
595 /* don't open a USB device if enable_usb is not set */
596
597 if (strcmp(cmtbl[s].drv, DRV_USB) == 0)
598 sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].valid = enable_usb;
599
600 /* don't open a IDE/ATAPI device which is missing but configured */
601
602 if (strcmp(cmtbl[s].drv, DRV_NOHA) == 0)
603 sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].valid = 0;
604
605
606 sdidevs[cmtbl[s].scg][cmtbl[s].tgt][cmtbl[s].lun].lmscsi = s;
607
608 }
609
610
611 /* open all yet valid device nodes */
612
613 for (s = 0; s < MAX_SCG; s++) {
614 for (t = 0; t < MAX_TGT; t++) {
615 for (l = 0; l < MAX_LUN; l++) {
616
617 if (sdidevs[s][t][l].valid == 0)
618 continue;
619
620 /* Open pass-through device node */
621
622 mscsi = sdidevs[s][t][l].lmscsi;
623
624 strcpy(dname, cmtbl[mscsi].dev);
625
626 /*
627 * ------------------------------------------------------------------
628 * NOTE: If we can't open the device, we will set the device invalid!
629 * ------------------------------------------------------------------
630 */
631 errno = 0;
632 if ((fd = open(dname, (O_RDONLY | O_NONBLOCK))) < 0) {
633 sdidevs[s][t][l].valid = 0;
634 if (scgp->debug > 0) {
635 js_fprintf((FILE *)scgp->errfile,
636 "%5s(%d,%d,%d,%d) -> %s open() failed: errno = %d (%s)\n",
637 cmtbl[mscsi].drv,
638 cmtbl[mscsi].hba,
639 cmtbl[mscsi].bus,
640 cmtbl[mscsi].tgt,
641 cmtbl[mscsi].lun,
642 cmtbl[mscsi].dev,
643 errno,
644 strerror(errno));
645 }
646 continue;
647 }
648
649 if (scgp->debug > 0) {
650 js_fprintf((FILE *)scgp->errfile,
651 "%d,%d,%d => %5s(%d,%d,%d,%d) -> %d : %s \n",
652 s, t, l,
653 cmtbl[mscsi].drv,
654 cmtbl[mscsi].hba,
655 cmtbl[mscsi].bus,
656 cmtbl[mscsi].tgt,
657 cmtbl[mscsi].lun,
658 cmtbl[mscsi].scg,
659 cmtbl[mscsi].dev);
660 }
661
662 sdidevs[s][t][l].fd = fd;
663 sdidevs[s][t][l].open = 1;
664 nopen++;
665 scglocal(scgp)->scgfiles[s][t][l] = (short) fd;
666 }
667 }
668 }
669
670 if (scgp->debug > 0) {
671 js_fprintf((FILE *)scgp->errfile, "-------------------- \n");
672 js_fprintf((FILE *)scgp->errfile, "nopen = %d devices \n", nopen);
673 js_fprintf((FILE *)scgp->errfile, "-------------------- \n");
674 }
675
676 return (nopen);
677 }
678
679
680 LOCAL int
scgo_open(scgp,device)681 scgo_open(scgp, device)
682 SCSI *scgp;
683 char *device;
684 {
685 int busno = scg_scsibus(scgp);
686 int tgt = scg_target(scgp);
687 int tlun = scg_lun(scgp);
688 int f, b, t, l;
689 int nopen = 0;
690 char devname[64];
691
692 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
693 errno = EINVAL;
694 if (scgp->errstr)
695 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
696 "Illegal value for busno, target or lun '%d,%d,%d'",
697 busno, tgt, tlun);
698 return (-1);
699 }
700
701 if (scgp->local == NULL) {
702 scgp->local = malloc(sizeof (struct scg_local));
703 if (scgp->local == NULL)
704 return (0);
705
706 for (b = 0; b < MAX_SCG; b++) {
707 for (t = 0; t < MAX_TGT; t++) {
708 for (l = 0; l < MAX_LUN; l++)
709 scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
710 }
711 }
712 }
713
714 if (*device != '\0') { /* we don't allow old dev usage */
715 errno = EINVAL;
716 if (scgp->errstr)
717 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
718 "Open by 'devname' no longer supported on this OS");
719 return (-1);
720 }
721
722 return (openserver_init(scgp));
723
724 }
725
726 LOCAL int
scgo_close(scgp)727 scgo_close(scgp)
728 SCSI *scgp;
729 {
730 register int f;
731 register int b;
732 register int t;
733 register int l;
734
735 if (scgp->local == NULL)
736 return (-1);
737
738 for (b = 0; b < MAX_SCG; b++) {
739 for (t = 0; t < MAX_TGT; t++) {
740 for (l = 0; l < MAX_LUN; l++) {
741
742 f = scglocal(scgp)->scgfiles[b][t][l];
743 if (f >= 0)
744 close(f);
745
746 sdidevs[b][t][l].fd = -1;
747 sdidevs[b][t][l].open = 0;
748 sdidevs[b][t][l].valid = 0;
749
750 scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
751 }
752 }
753 }
754 return (0);
755 }
756
757 LOCAL long
scgo_maxdma(scgp,amt)758 scgo_maxdma(scgp, amt)
759 SCSI *scgp;
760 long amt;
761 {
762 return (max_dma);
763 }
764
765
766 LOCAL void *
scgo_getbuf(scgp,amt)767 scgo_getbuf(scgp, amt)
768 SCSI *scgp;
769 long amt;
770 {
771 if (scgp->debug > 0) {
772 js_fprintf((FILE *)scgp->errfile,
773 "scgo_getbuf: %ld bytes\n", amt);
774 }
775 scgp->bufbase = valloc((size_t)(amt));
776
777 return (scgp->bufbase);
778 }
779
780 LOCAL void
scgo_freebuf(scgp)781 scgo_freebuf(scgp)
782 SCSI *scgp;
783 {
784 if (scgp->bufbase)
785 free(scgp->bufbase);
786 scgp->bufbase = NULL;
787 }
788
789 LOCAL int
scgo_numbus(scgp)790 scgo_numbus(scgp)
791 SCSI *scgp;
792 {
793 return (MAX_SCG);
794 }
795
796 LOCAL BOOL
scgo_havebus(scgp,busno)797 scgo_havebus(scgp, busno)
798 SCSI *scgp;
799 int busno;
800 {
801 register int t;
802 register int l;
803
804 if (busno < 0 || busno >= MAX_SCG)
805 return (FALSE);
806
807 if (scgp->local == NULL)
808 return (FALSE);
809
810 for (t = 0; t < MAX_TGT; t++) {
811 for (l = 0; l < MAX_LUN; l++)
812 if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
813 return (TRUE);
814 }
815 return (FALSE);
816 }
817
818 LOCAL int
scgo_fileno(scgp,busno,tgt,tlun)819 scgo_fileno(scgp, busno, tgt, tlun)
820 SCSI *scgp;
821 int busno;
822 int tgt;
823 int tlun;
824 {
825 if (busno < 0 || busno >= MAX_SCG ||
826 tgt < 0 || tgt >= MAX_TGT ||
827 tlun < 0 || tlun >= MAX_LUN)
828 return (-1);
829
830 if (scgp->local == NULL)
831 return (-1);
832
833 return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
834 }
835
836 LOCAL int
scgo_initiator_id(scgp)837 scgo_initiator_id(scgp)
838 SCSI *scgp;
839 {
840 return (-1);
841
842 /*
843 * We don't know the initiator ID yet, but we can if we parse the
844 * output of the command 'cat /dev/string/cfg | grep "%adapter"'
845 *
846 * Sample line:
847 *
848 * %adapter 0xE800-0xE8FF 11 - type=alad ha=0 bus=0 id=7 fts=sto
849 *
850 * This tells us that the alad controller 0 has an id of 7 !
851 * The parsing should be done in openserver_init().
852 *
853 */
854 }
855
856 LOCAL int
scgo_isatapi(scgp)857 scgo_isatapi(scgp)
858 SCSI *scgp;
859 {
860 return (sdidevs[scg_scsibus(scgp)][scg_target(scgp)][scg_lun(scgp)].atapi);
861 }
862
863 LOCAL int
scgo_reset(scgp,what)864 scgo_reset(scgp, what)
865 SCSI *scgp;
866 int what;
867 {
868 errno = EINVAL;
869 return (-1); /* no scsi reset available */
870 }
871
872 LOCAL void
cp_scg2sco(sco,scg)873 cp_scg2sco(sco, scg)
874 struct scsicmd2 *sco;
875 struct scg_cmd *scg;
876 {
877 sco->cmd.data_ptr = (char *) scg->addr;
878 sco->cmd.data_len = scg->size;
879 sco->cmd.cdb_len = scg->cdb_len;
880
881 sco->sense_len = scg->sense_len;
882 sco->sense_ptr = scg->u_sense.cmd_sense;
883
884 if (!(scg->flags & SCG_RECV_DATA) && (scg->size > 0))
885 sco->cmd.is_write = 1;
886
887 if (scg->cdb_len == SC_G0_CDBLEN)
888 memcpy(sco->cmd.cdb, &scg->cdb.g0_cdb, scg->cdb_len);
889
890 if (scg->cdb_len == SC_G1_CDBLEN)
891 memcpy(sco->cmd.cdb, &scg->cdb.g1_cdb, scg->cdb_len);
892
893 if (scg->cdb_len == SC_G5_CDBLEN)
894 memcpy(sco->cmd.cdb, &scg->cdb.g5_cdb, scg->cdb_len);
895 }
896
897
898 LOCAL void
cp_sco2scg(sco,scg)899 cp_sco2scg(sco, scg)
900 struct scsicmd2 *sco;
901 struct scg_cmd *scg;
902 {
903 scg->size = sco->cmd.data_len;
904
905 memset(&scg->scb, 0, sizeof (scg->scb));
906
907 if (sco->sense_len > SCG_MAX_SENSE)
908 scg->sense_count = SCG_MAX_SENSE;
909 else
910 scg->sense_count = sco->sense_len;
911
912 scg->resid = 0;
913
914 scg->u_scb.cmd_scb[0] = sco->cmd.target_sts;
915
916 }
917
918
919 LOCAL int
scgo_send(scgp)920 scgo_send(scgp)
921 SCSI *scgp;
922 {
923 struct scg_cmd *sp = scgp->scmd;
924 struct scsicmd2 scsi_cmd;
925 int i;
926 Uchar sense_buf[SCG_MAX_SENSE];
927
928 if (scgp->fd < 0) {
929 sp->error = SCG_FATAL;
930 return (0);
931 }
932
933 memset(&scsi_cmd, 0, sizeof (scsi_cmd));
934 memset(sense_buf, 0, sizeof (sense_buf));
935 scsi_cmd.sense_ptr = sense_buf;
936 scsi_cmd.sense_len = sizeof (sense_buf);
937 cp_scg2sco(&scsi_cmd, sp);
938
939 errno = 0;
940 sp->ux_errno = 0;
941 sp->error = SCG_NO_ERROR;
942 for (;;) {
943 int ioctlStatus;
944 struct scsicmd s_cmd;
945
946 if (scsiusercmd) { /* Use SCSIUSERCMD ioctl() */
947 if (scgp->debug > 1) {
948 js_fprintf((FILE *)scgp->errfile, "calling SCSIUSERCMD ioctl()\n");
949 }
950
951 if ((ioctlStatus = ioctl(scgp->fd, SCSIUSERCMD, &(scsi_cmd.cmd))) < 0) {
952 if (scgp->debug > 1) {
953 js_fprintf((FILE *)scgp->errfile, "returning from SCSIUSERCMD ioctl()\n");
954 }
955 if (errno == EINTR)
956 continue;
957
958 cp_sco2scg(&scsi_cmd, sp);
959 sp->ux_errno = errno;
960 if (errno == 0)
961 sp->ux_errno = EIO;
962 sp->error = SCG_RETRYABLE;
963
964 return (0);
965 }
966
967 if (scgp->debug > 1) {
968 js_fprintf((FILE *)scgp->errfile, "returning from SCSIUSERCMD ioctl()\n");
969 }
970 cp_sco2scg(&scsi_cmd, sp);
971 sp->ux_errno = errno;
972
973 if (scsi_cmd.cmd.target_sts & 0x02) { /* Check Condition & get Sense */
974
975 if (sp->sense_len > SCG_MAX_SENSE)
976 sp->sense_len = SCG_MAX_SENSE;
977
978 memset((caddr_t)&s_cmd, 0, sizeof (s_cmd));
979
980 s_cmd.data_ptr = (caddr_t) sp->u_sense.cmd_sense;
981 s_cmd.data_len = sp->sense_len;
982 s_cmd.is_write = 0;
983 s_cmd.cdb[0] = SC_REQUEST_SENSE;
984
985 while (((ioctlStatus = ioctl(scgp->fd, SCSIUSERCMD, &s_cmd)) < 0) &&
986 (errno == EINTR))
987 ;
988
989 sp->sense_count = sp->sense_len;
990 sp->ux_errno = errno;
991
992 if (errno == 0)
993 sp->ux_errno = EIO;
994 sp->error = SCG_NO_ERROR;
995 }
996
997 if (scgp->debug > 0) {
998 if (errno != 0)
999 js_fprintf((FILE *)scgp->errfile,
1000 "ux_errno: %d (%s) \n",
1001 sp->ux_errno, strerror(sp->ux_errno));
1002 if (sp->u_scb.cmd_scb[0] != 0)
1003 js_fprintf((FILE *)scgp->errfile,
1004 "tgt_stat: %d \n",
1005 sp->u_scb.cmd_scb[0]);
1006 }
1007 break;
1008
1009 } else { /* Use SCSIUSERCMD2 ioctl() */
1010 if (scgp->debug > 1) {
1011 js_fprintf((FILE *)scgp->errfile, "calling SCSIUSERCMD2 ioctl()\n");
1012 }
1013
1014 if ((ioctlStatus = ioctl(scgp->fd, SCSIUSERCMD2, &scsi_cmd)) < 0) {
1015 if (scgp->debug > 1) {
1016 js_fprintf((FILE *)scgp->errfile, "returning from SCSIUSERCMD2 ioctl()\n");
1017 }
1018 if (errno == EINTR)
1019 continue;
1020
1021 cp_sco2scg(&scsi_cmd, sp);
1022 sp->ux_errno = errno;
1023 if (errno == 0)
1024 sp->ux_errno = EIO;
1025 sp->error = SCG_RETRYABLE;
1026
1027 return (0);
1028 }
1029 if (scgp->debug > 1) {
1030 js_fprintf((FILE *)scgp->errfile, "returning from SCSIUSERCMD2 ioctl()\n");
1031 }
1032
1033 cp_sco2scg(&scsi_cmd, sp);
1034 sp->ux_errno = errno;
1035
1036 if (scsi_cmd.cmd.target_sts & 0x02) { /* Check Condition */
1037 if (errno == 0)
1038 sp->ux_errno = EIO;
1039 sp->error = SCG_NO_ERROR;
1040 }
1041
1042 if (scgp->debug > 0) {
1043 if (errno != 0)
1044 js_fprintf((FILE *)scgp->errfile,
1045 "ux_errno: %d (%s) \n",
1046 sp->ux_errno, strerror(sp->ux_errno));
1047 if (sp->u_scb.cmd_scb[0] != 0)
1048 js_fprintf((FILE *)scgp->errfile,
1049 "tgt_stat: %d \n",
1050 sp->u_scb.cmd_scb[0]);
1051 }
1052 break;
1053
1054 }
1055 }
1056
1057 return (0);
1058 }
1059
1060 #define sense u_sense.Sense
1061