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-sgi.c 1.36 04/01/15 Copyright 1997 J. Schilling */
15 * Interface for the SGI generic SCSI implementation.
17 * First Hacky implementation
18 * (needed libds, did not support bus scanning and had no error checking)
19 * from "Frank van Beek" <frank@neogeo.nl>
21 * Actual implementation supports all usal features.
23 * Warning: you may change this source, but if you do that
24 * you need to change the _usal_version and _usal_auth* string below.
25 * You may not return "schily" for an SCG_AUTHOR request anymore.
26 * Choose your name instead of "schily" and make clear that the version
27 * string is related to a modified source.
29 * Copyright (c) 1997 J. Schilling
32 * This program is free software; you can redistribute it and/or modify
33 * it under the terms of the GNU General Public License version 2
34 * as published by the Free Software Foundation.
36 * This program is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
41 * You should have received a copy of the GNU General Public License along with
42 * this program; see the file COPYING. If not, write to the Free Software
43 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
49 * Warning: you may change this source, but if you do that
50 * you need to change the _usal_version and _usal_auth* string below.
51 * You may not return "schily" for an SCG_AUTHOR request anymore.
52 * Choose your name instead of "schily" and make clear that the version
53 * string is related to a modified source.
55 static char _usal_trans_version[] = "scsi-sgi.c-1.36"; /* The version for this transport*/
59 struct dsreq * dsp = 0;
60 #define MAX_SCG 1 /* Max # of SCSI controllers */
64 #define MAX_SCG 16 /* Max # of SCSI controllers */
69 short usalfiles[MAX_SCG][MAX_TGT][MAX_LUN];
71 #define usallocal(p) ((struct usal_local *)((p)->local))
75 #define MAX_DMA_SGI (256*1024) /* Check if this is not too big */
79 static int usal_sendreq(SCSI *usalp, struct usal_cmd *sp, struct dsreq *dsp);
84 * Return version information for the low level SCSI transport code.
85 * This has been introduced to make it easier to trace down problems
89 usalo_version(SCSI *usalp, int what)
91 if (usalp != (SCSI *)0) {
95 return (_usal_trans_version);
97 * If you changed this source, you are not allowed to
98 * return "schily" for the SCG_AUTHOR request.
101 return (_usal_auth_cdrkit);
110 usalo_help(SCSI *usalp, FILE *f)
112 __usal_help(f, "DS", "Generic SCSI",
113 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
118 usalo_open(SCSI *usalp, char *device)
120 int busno = usal_scsibus(usalp);
121 int tgt = usal_target(usalp);
122 int tlun = usal_lun(usalp);
127 register int nopen = 0;
130 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
133 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
134 "Illegal value for busno, target or lun '%d,%d,%d'",
139 if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
142 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
143 "Open by 'devname' not supported on this OS");
147 if (usalp->local == NULL) {
148 usalp->local = malloc(sizeof (struct usal_local));
149 if (usalp->local == NULL)
152 for (b = 0; b < MAX_SCG; b++) {
153 for (t = 0; t < MAX_TGT; t++) {
154 for (l = 0; l < MAX_LUN; l++)
155 usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
160 if (busno >= 0 && tgt >= 0 && tlun >= 0) {
162 snprintf(devname, sizeof (devname),
163 "/dev/scsi/sc%dd%dl%d", busno, tgt, tlun);
165 dsp = dsopen(devname, O_RDWR);
169 f = open(devname, O_RDWR);
172 snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
177 usallocal(usalp)->usalfiles[busno][tgt][tlun] = f;
184 for (b = 0; b < MAX_SCG; b++) {
185 for (t = 0; t < MAX_TGT; t++) {
186 /* for (l = 0; l < MAX_LUN; l++) {*/
187 for (l = 0; l < 1; l++) {
188 snprintf(devname, sizeof (devname),
189 "/dev/scsi/sc%dd%dl%d", b, t, l);
190 f = open(devname, O_RDWR);
192 usallocal(usalp)->usalfiles[b][t][l] = (short)f;
204 usalo_close(SCSI *usalp)
212 if (usalp->local == NULL)
215 for (b = 0; b < MAX_SCG; b++) {
216 for (t = 0; t < MAX_TGT; t++) {
217 for (l = 0; l < MAX_LUN; l++) {
218 f = usallocal(usalp)->usalfiles[b][t][l];
221 usallocal(usalp)->usalfiles[b][t][l] = (short)-1;
232 usalo_maxdma(SCSI *usalp, long amt)
234 return (MAX_DMA_SGI);
238 usalo_getbuf(SCSI *usalp, long amt)
240 if (usalp->debug > 0) {
241 fprintf((FILE *)usalp->errfile,
242 "usalo_getbuf: %ld bytes\n", amt);
244 usalp->bufbase = valloc((size_t)(amt));
245 return (usalp->bufbase);
249 usalo_freebuf(SCSI *usalp)
252 free(usalp->bufbase);
253 usalp->bufbase = NULL;
257 usalo_havebus(SCSI *usalp, int busno)
262 if (busno < 0 || busno >= MAX_SCG)
265 if (usalp->local == NULL)
268 for (t = 0; t < MAX_TGT; t++) {
269 for (l = 0; l < MAX_LUN; l++)
270 if (usallocal(usalp)->usalfiles[busno][t][l] >= 0)
277 usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
284 if (busno < 0 || busno >= MAX_SCG ||
285 tgt < 0 || tgt >= MAX_TGT ||
286 tlun < 0 || tlun >= MAX_LUN)
289 if (usalp->local == NULL)
292 return ((int)usallocal(usalp)->usalfiles[busno][tgt][tlun]);
297 usalo_initiator_id(SCSI *usalp)
303 usalo_isatapi(SCSI *usalp)
309 usalo_reset(SCSI *usalp, int what)
312 * Do we have a SCSI reset on SGI?
315 if (what == SCG_RESET_NOP)
317 if (what != SCG_RESET_BUS) {
322 * XXX Does this reset TGT or BUS ???
324 return (ioctl(usalp->fd, DS_RESET, 0));
332 usal_sendreq(SCSI *usalp, struct usal_cmd *sp, struct dsreq *dsp)
338 /* if ((sp->flags & SCG_CMD_RETRY) == 0)*/
341 while (--retries > 0) {
342 ret = ioctl(usalp->fd, DS_ENTER, dsp);
344 RET(dsp) = DSRT_DEVSCSI;
348 * SGI implementattion botch!!!
349 * If a target does not select the bus,
350 * the return code is DSRT_TIMEOUT
352 if (RET(dsp) == DSRT_TIMEOUT) {
355 to.tv_sec = TIME(dsp)/1000;
356 to.tv_usec = TIME(dsp)%1000;
359 if (sp->cdb.g0_cdb.cmd == SC_TEST_UNIT_READY &&
360 usalp->cmdstop->tv_sec < to.tv_sec ||
361 (usalp->cmdstop->tv_sec == to.tv_sec &&
362 usalp->cmdstop->tv_usec < to.tv_usec)) {
364 RET(dsp) = DSRT_NOSEL;
368 if (RET(dsp) == DSRT_NOSEL)
369 continue; /* retry noselect 3X */
371 status = STATUS(dsp);
374 case 0x08: /* BUSY */
375 case 0x18: /* RESERV CONFLICT */
379 case 0x00: /* GOOD */
380 case 0x02: /* CHECK CONDITION */
381 case 0x10: /* INTERM/GOOD */
386 return (-1); /* failed retry limit */
391 usalo_send(SCSI *usalp)
393 struct usal_cmd *sp = usalp->scmd;
396 int amt = sp->cdb_len;
400 struct dsreq *dsp = &ds;
407 sp->error = SCG_FATAL;
412 if (sp->flags & SCG_RECV_DATA)
414 else if (sp->size > 0)
417 dsp->ds_flags = flags;
422 DATABUF(dsp) = sp->addr;
423 DATALEN(dsp) = sp->size;
424 CMDBUF(dsp) = (void *) &sp->cdb;
425 CMDLEN(dsp) = sp->cdb_len;
426 SENSEBUF(dsp) = (caddr_t)sp->u_sense.cmd_sense;
427 SENSELEN(dsp) = sizeof (sp->u_sense.cmd_sense);
428 TIME(dsp) = (sp->timeout * 1000) + 100;
435 ret = doscsireq(usalp->fd, dsp);
437 ret = usal_sendreq(usalp, sp, dsp);
440 if (RET(dsp) != DSRT_DEVSCSI)
444 if (RET(dsp) == DSRT_SHORT) {
445 sp->resid = DATALEN(dsp)- DATASENT(dsp);
447 sp->ux_errno = errno;
452 sp->u_scb.cmd_scb[0] = STATUS(dsp);
454 sp->sense_count = SENSESENT(dsp);
455 if (sp->sense_count > SCG_MAX_SENSE)
456 sp->sense_count = SCG_MAX_SENSE;
462 sp->error = SCG_RETRYABLE; break;
465 case DSRT_SHORT: /* not implemented */
466 sp->error = SCG_NO_ERROR; break;
468 case DSRT_UNIMPL: /* not implemented */
469 case DSRT_REVCODE: /* software obsolete must recompile */
471 sp->u_scb.cmd_scb[0] = 0;
472 sp->error = SCG_FATAL; break;
475 sp->u_scb.cmd_scb[0] = 0;
476 sp->error = SCG_TIMEOUT; break;