1 /* @(#)scsi-hpux.c 1.34 09/10/09 Copyright 1997 J. Schilling */
2 #ifndef lint
3 static char __sccsid[] =
4 "@(#)scsi-hpux.c 1.34 09/10/09 Copyright 1997 J. Schilling";
5 #endif
6 /*
7 * Interface for the HP-UX generic 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) 1997 J. Schilling
16 */
17 /*
18 * The contents of this file are subject to the terms of the
19 * Common Development and Distribution License, Version 1.0 only
20 * (the "License"). You may not use this file except in compliance
21 * with the License.
22 *
23 * See the file CDDL.Schily.txt in this distribution for details.
24 * A copy of the CDDL is also available via the Internet at
25 * http://www.opensource.org/licenses/cddl1.txt
26 *
27 * The following exceptions apply:
28 * CDDL �3.6 needs to be replaced by: "You may create a Larger Work by
29 * combining Covered Software with other code if all other code is governed by
30 * the terms of a license that is OSI approved (see www.opensource.org) and
31 * you may distribute the Larger Work as a single product. In such a case,
32 * You must make sure the requirements of this License are fulfilled for
33 * the Covered Software."
34 *
35 * When distributing Covered Code, include this CDDL HEADER in each
36 * file and include the License file CDDL.Schily.txt from this distribution.
37 */
38
39 #undef sense
40 #include <sys/scsi.h>
41
42 /*
43 * Warning: you may change this source, but if you do that
44 * you need to change the _scg_version and _scg_auth* string below.
45 * You may not return "schily" for an SCG_AUTHOR request anymore.
46 * Choose your name instead of "schily" and make clear that the version
47 * string is related to a modified source.
48 */
49 LOCAL char _scg_trans_version[] = "scsi-hpux.c-1.34"; /* The version for this transport*/
50
51 #define MAX_SCG 16 /* Max # of SCSI controllers */
52 #define MAX_TGT 16
53 #define MAX_LUN 8
54
55 struct scg_local {
56 short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
57 };
58 #define scglocal(p) ((struct scg_local *)((p)->local))
59
60 #ifdef SCSI_MAXPHYS
61 #define MAX_DMA_HP SCSI_MAXPHYS
62 #else
63 #define MAX_DMA_HP (63*1024) /* Check if this is not too big */
64 #endif
65
66
67 /*
68 * Return version information for the low level SCSI transport code.
69 * This has been introduced to make it easier to trace down problems
70 * in applications.
71 */
72 LOCAL char *
scgo_version(scgp,what)73 scgo_version(scgp, what)
74 SCSI *scgp;
75 int what;
76 {
77 if (scgp != (SCSI *)0) {
78 switch (what) {
79
80 case SCG_VERSION:
81 return (_scg_trans_version);
82 /*
83 * If you changed this source, you are not allowed to
84 * return "schily" for the SCG_AUTHOR request.
85 */
86 case SCG_AUTHOR:
87 return (_scg_auth_schily);
88 case SCG_SCCS_ID:
89 return (__sccsid);
90 }
91 }
92 return ((char *)0);
93 }
94
95 LOCAL int
scgo_help(scgp,f)96 scgo_help(scgp, f)
97 SCSI *scgp;
98 FILE *f;
99 {
100 __scg_help(f, "SIOC", "Generic SCSI",
101 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
102 return (0);
103 }
104
105 LOCAL int
scgo_open(scgp,device)106 scgo_open(scgp, device)
107 SCSI *scgp;
108 char *device;
109 {
110 int busno = scg_scsibus(scgp);
111 int tgt = scg_target(scgp);
112 int tlun = scg_lun(scgp);
113 register int f;
114 register int b;
115 register int t;
116 register int l;
117 register int nopen = 0;
118 char devname[64];
119
120 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
121 errno = EINVAL;
122 if (scgp->errstr)
123 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
124 "Illegal value for busno, target or lun '%d,%d,%d'",
125 busno, tgt, tlun);
126 return (-1);
127 }
128
129 if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
130 errno = EINVAL;
131 if (scgp->errstr)
132 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
133 "Open by 'devname' not supported on this OS");
134 return (-1);
135 }
136
137 if (scgp->local == NULL) {
138 scgp->local = malloc(sizeof (struct scg_local));
139 if (scgp->local == NULL)
140 return (0);
141
142 for (b = 0; b < MAX_SCG; b++) {
143 for (t = 0; t < MAX_TGT; t++) {
144 for (l = 0; l < MAX_LUN; l++)
145 scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
146 }
147 }
148 }
149
150 if (busno >= 0 && tgt >= 0 && tlun >= 0) {
151
152 js_snprintf(devname, sizeof (devname),
153 "/dev/rscsi/c%xt%xl%x", busno, tgt, tlun);
154 f = open(devname, O_RDWR);
155 if (f < 0)
156 return (-1);
157 scglocal(scgp)->scgfiles[busno][tgt][tlun] = f;
158 return (1);
159 } else {
160 for (b = 0; b < MAX_SCG; b++) {
161 for (t = 0; t < MAX_TGT; t++) {
162 /* for (l = 0; l < MAX_LUN; l++) {*/
163 for (l = 0; l < 1; l++) {
164 js_snprintf(devname, sizeof (devname),
165 "/dev/rscsi/c%xt%xl%x", b, t, l);
166 /*error("name: '%s'\n", devname);*/
167 f = open(devname, O_RDWR);
168 if (f >= 0) {
169 scglocal(scgp)->scgfiles[b][t][l] = (short)f;
170 nopen++;
171 } else if (scgp->debug > 0) {
172 errmsg("open '%s'\n", devname);
173 }
174 }
175 }
176 }
177 }
178 return (nopen);
179 }
180
181 LOCAL int
scgo_close(scgp)182 scgo_close(scgp)
183 SCSI *scgp;
184 {
185 register int f;
186 register int b;
187 register int t;
188 register int l;
189
190 if (scgp->local == NULL)
191 return (-1);
192
193 for (b = 0; b < MAX_SCG; b++) {
194 for (t = 0; t < MAX_TGT; t++) {
195 for (l = 0; l < MAX_LUN; l++) {
196 f = scglocal(scgp)->scgfiles[b][t][l];
197 if (f >= 0)
198 close(f);
199 scglocal(scgp)->scgfiles[b][t][l] = (short)-1;
200 }
201 }
202 }
203 return (0);
204 }
205
206 LOCAL long
scgo_maxdma(scgp,amt)207 scgo_maxdma(scgp, amt)
208 SCSI *scgp;
209 long amt;
210 {
211 return (MAX_DMA_HP);
212 }
213
214 LOCAL void *
scgo_getbuf(scgp,amt)215 scgo_getbuf(scgp, amt)
216 SCSI *scgp;
217 long amt;
218 {
219 if (scgp->debug > 0) {
220 js_fprintf((FILE *)scgp->errfile,
221 "scgo_getbuf: %ld bytes\n", amt);
222 }
223 scgp->bufbase = valloc((size_t)(amt));
224 return (scgp->bufbase);
225 }
226
227 LOCAL void
scgo_freebuf(scgp)228 scgo_freebuf(scgp)
229 SCSI *scgp;
230 {
231 if (scgp->bufbase)
232 free(scgp->bufbase);
233 scgp->bufbase = NULL;
234 }
235
236 LOCAL int
scgo_numbus(scgp)237 scgo_numbus(scgp)
238 SCSI *scgp;
239 {
240 return (MAX_SCG);
241 }
242
243 LOCAL BOOL
scgo_havebus(scgp,busno)244 scgo_havebus(scgp, busno)
245 SCSI *scgp;
246 int busno;
247 {
248 register int t;
249 register int l;
250
251 if (busno < 0 || busno >= MAX_SCG)
252 return (FALSE);
253
254 if (scgp->local == NULL)
255 return (FALSE);
256
257 for (t = 0; t < MAX_TGT; t++) {
258 for (l = 0; l < MAX_LUN; l++)
259 if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
260 return (TRUE);
261 }
262 return (FALSE);
263 }
264
265 LOCAL int
scgo_fileno(scgp,busno,tgt,tlun)266 scgo_fileno(scgp, busno, tgt, tlun)
267 SCSI *scgp;
268 int busno;
269 int tgt;
270 int tlun;
271 {
272 if (busno < 0 || busno >= MAX_SCG ||
273 tgt < 0 || tgt >= MAX_TGT ||
274 tlun < 0 || tlun >= MAX_LUN)
275 return (-1);
276
277 if (scgp->local == NULL)
278 return (-1);
279
280 return ((int)scglocal(scgp)->scgfiles[busno][tgt][tlun]);
281 }
282
283 LOCAL int
scgo_initiator_id(scgp)284 scgo_initiator_id(scgp)
285 SCSI *scgp;
286 {
287 return (-1);
288 }
289
290 LOCAL int
scgo_isatapi(scgp)291 scgo_isatapi(scgp)
292 SCSI *scgp;
293 {
294 return (FALSE);
295 }
296
297 LOCAL int
scgo_reset(scgp,what)298 scgo_reset(scgp, what)
299 SCSI *scgp;
300 int what;
301 {
302 if (what == SCG_RESET_NOP)
303 return (0);
304 if (what != SCG_RESET_BUS) {
305 errno = EINVAL;
306 return (-1);
307 }
308 return (ioctl(scgp->fd, SIOC_RESET_BUS, 0));
309 }
310
311 LOCAL int
scgo_send(scgp)312 scgo_send(scgp)
313 SCSI *scgp;
314 {
315 struct scg_cmd *sp = scgp->scmd;
316 int ret;
317 int flags;
318 struct sctl_io sctl_io;
319
320 if ((scgp->fd < 0) || (sp->cdb_len > sizeof (sctl_io.cdb))) {
321 sp->error = SCG_FATAL;
322 return (0);
323 }
324
325 fillbytes((caddr_t)&sctl_io, sizeof (sctl_io), '\0');
326
327 flags = 0;
328 /* flags = SCTL_INIT_WDTR|SCTL_INIT_SDTR;*/
329 if (sp->flags & SCG_RECV_DATA)
330 flags |= SCTL_READ;
331 if ((sp->flags & SCG_DISRE_ENA) == 0)
332 flags |= SCTL_NO_ATN;
333
334 sctl_io.flags = flags;
335
336 movebytes(&sp->cdb, sctl_io.cdb, sp->cdb_len);
337 sctl_io.cdb_length = sp->cdb_len;
338
339 sctl_io.data_length = sp->size;
340 sctl_io.data = sp->addr;
341
342 if (sp->timeout == 0)
343 sctl_io.max_msecs = 0;
344 else
345 sctl_io.max_msecs = (sp->timeout * 1000) + 500;
346
347 errno = 0;
348 sp->error = SCG_NO_ERROR;
349 sp->sense_count = 0;
350 sp->u_scb.cmd_scb[0] = 0;
351 sp->resid = 0;
352
353 ret = ioctl(scgp->fd, SIOC_IO, &sctl_io);
354 if (ret < 0) {
355 sp->error = SCG_FATAL;
356 sp->ux_errno = errno;
357 return (ret);
358 }
359 if (scgp->debug > 0)
360 error("cdb_status: %X, size: %d xfer: %d senselen: %d sensexfer: %d\n",
361 sctl_io.cdb_status, sctl_io.data_length, sctl_io.data_xfer, sp->sense_len, sctl_io.sense_xfer);
362
363 if (sctl_io.cdb_status == 0 || sctl_io.cdb_status == 0x02)
364 sp->resid = sp->size - sctl_io.data_xfer;
365
366 if (sctl_io.cdb_status & SCTL_SELECT_TIMEOUT ||
367 sctl_io.cdb_status & SCTL_INVALID_REQUEST) {
368 sp->error = SCG_FATAL;
369 #ifdef SCTL_POWERFAIL
370 } else if (sctl_io.cdb_status & SCTL_POWERFAIL) { /* Cannot select ATA */
371 sp->error = SCG_FATAL;
372 #endif
373 } else if (sctl_io.cdb_status & SCTL_INCOMPLETE) {
374 sp->error = SCG_TIMEOUT;
375 } else if (sctl_io.cdb_status > 0xFF) {
376 errmsgno(EX_BAD, "SCSI problems: cdb_status: %X\n", sctl_io.cdb_status);
377
378 } else if ((sctl_io.cdb_status & 0xFF) != 0) {
379 /* sp->error = SCG_RETRYABLE;*/
380 sp->ux_errno = EIO;
381
382 sp->u_scb.cmd_scb[0] = sctl_io.cdb_status & 0xFF;
383
384 sp->sense_count = sctl_io.sense_xfer;
385 if (sp->sense_count > SCG_MAX_SENSE)
386 sp->sense_count = SCG_MAX_SENSE;
387
388 if (sctl_io.sense_status != S_GOOD) {
389 sp->sense_count = 0;
390 } else {
391 movebytes(sctl_io.sense, sp->u_sense.cmd_sense, sp->sense_count);
392 }
393
394 }
395 return (ret);
396 }
397 #define sense u_sense.Sense
398