/[debburn]/nonameyet/branches/cleanup/libscg/scsi-osf.c
ViewVC logotype

Contents of /nonameyet/branches/cleanup/libscg/scsi-osf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 238 - (show annotations) (download)
Wed Sep 6 20:02:07 2006 UTC (6 years, 8 months ago) by joerg
File MIME type: text/plain
File size: 11285 byte(s)
Create a cleanup branch so people can start with that part outside of trunk
1 /*
2 * This file has been modified for the cdrkit suite.
3 *
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).
6 *
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.
10 *
11 */
12
13 /* @(#)scsi-osf.c 1.26 04/01/15 Copyright 1998 J. Schilling */
14 #ifndef lint
15 static char __sccsid[] =
16 "@(#)scsi-osf.c 1.26 04/01/15 Copyright 1998 J. Schilling";
17 #endif
18 /*
19 * Interface for Digital UNIX (OSF/1 generic SCSI implementation (/dev/cam).
20 *
21 * Created out of the hacks from:
22 * Stefan Traby <stefan@sime.com> and
23 * Bruno Achauer <bruno@tk.uni-linz.ac.at>
24 *
25 * Warning: you may change this source, but if you do that
26 * you need to change the _scg_version and _scg_auth* string below.
27 * You may not return "schily" for an SCG_AUTHOR request anymore.
28 * Choose your name instead of "schily" and make clear that the version
29 * string is related to a modified source.
30 *
31 * Copyright (c) 1998 J. Schilling
32 */
33 /*
34 * This program is free software; you can redistribute it and/or modify
35 * it under the terms of the GNU General Public License version 2
36 * as published by the Free Software Foundation.
37 *
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
42 *
43 * You should have received a copy of the GNU General Public License along with
44 * this program; see the file COPYING. If not, write to the Free Software
45 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 */
47
48 #include <sys/types.h>
49 #include <io/common/iotypes.h>
50 #include <io/cam/cam.h>
51 #include <io/cam/uagt.h>
52
53 /*
54 * Warning: you may change this source, but if you do that
55 * you need to change the _scg_version and _scg_auth* string below.
56 * You may not return "schily" for an SCG_AUTHOR request anymore.
57 * Choose your name instead of "schily" and make clear that the version
58 * string is related to a modified source.
59 */
60 LOCAL char _scg_trans_version[] = "scsi-osf.c-1.26"; /* The version for this transport*/
61
62 #define MAX_SCG 16 /* Max # of SCSI controllers */
63 #define MAX_TGT 16
64 #define MAX_LUN 8
65
66 struct scg_local {
67 int scgfile; /* Used for ioctl() */
68 short scgfiles[MAX_SCG][MAX_TGT][MAX_LUN];
69 };
70 #define scglocal(p) ((struct scg_local *)((p)->local))
71
72 LOCAL BOOL scsi_checktgt __PR((SCSI *scgp, int f, int busno, int tgt, int tlun));
73
74 /*
75 * I don't have any documentation about CAM
76 */
77 #define MAX_DMA_OSF_CAM (64*1024)
78
79 #ifndef AUTO_SENSE_LEN
80 # define AUTO_SENSE_LEN 32 /* SCG_MAX_SENSE */
81 #endif
82
83 /*
84 * Return version information for the low level SCSI transport code.
85 * This has been introduced to make it easier to trace down problems
86 * in applications.
87 */
88 LOCAL char *
89 scgo_version(scgp, what)
90 SCSI *scgp;
91 int what;
92 {
93 if (scgp != (SCSI *)0) {
94 switch (what) {
95
96 case SCG_VERSION:
97 return (_scg_trans_version);
98 /*
99 * If you changed this source, you are not allowed to
100 * return "schily" for the SCG_AUTHOR request.
101 */
102 case SCG_AUTHOR:
103 return (_scg_auth_cdrkit);
104 case SCG_SCCS_ID:
105 return (__sccsid);
106 }
107 }
108 return ((char *)0);
109 }
110
111 LOCAL int
112 scgo_help(scgp, f)
113 SCSI *scgp;
114 FILE *f;
115 {
116 __scg_help(f, "CAM", "Generic transport independent SCSI (Common Access Method)",
117 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
118 return (0);
119 }
120
121 LOCAL int
122 scgo_open(scgp, device)
123 SCSI *scgp;
124 char *device;
125 {
126 int busno = scg_scsibus(scgp);
127 int tgt = scg_target(scgp);
128 int tlun = scg_lun(scgp);
129 register int b;
130 register int t;
131 register int l;
132
133 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
134 errno = EINVAL;
135 if (scgp->errstr)
136 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
137 "Illegal value for busno, target or lun '%d,%d,%d'",
138 busno, tgt, tlun);
139 return (-1);
140 }
141
142 if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
143 errno = EINVAL;
144 if (scgp->errstr)
145 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
146 "Open by 'devname' not supported on this OS");
147 return (-1);
148 }
149
150 if (scgp->local == NULL) {
151 scgp->local = malloc(sizeof (struct scg_local));
152 if (scgp->local == NULL)
153 return (0);
154 scglocal(scgp)->scgfile = -1;
155
156 for (b = 0; b < MAX_SCG; b++) {
157 for (t = 0; t < MAX_TGT; t++) {
158 for (l = 0; l < MAX_LUN; l++)
159 scglocal(scgp)->scgfiles[b][t][l] = 0;
160 }
161 }
162 }
163
164 if (scglocal(scgp)->scgfile != -1) /* multiple opens ??? */
165 return (1); /* not yet ready .... */
166
167 if ((scglocal(scgp)->scgfile = open("/dev/cam", O_RDWR, 0)) < 0) {
168 if (scgp->errstr)
169 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
170 "Cannot open '/dev/cam'");
171 return (-1);
172 }
173
174 if (busno >= 0 && tgt >= 0 && tlun >= 0) {
175 /* scsi_checktgt() ??? */
176 for (l = 0; l < MAX_LUN; l++)
177 scglocal(scgp)->scgfiles[b][t][l] = 1;
178 return (1);
179 }
180 /*
181 * There seems to be no clean way to check whether
182 * a SCSI bus is present in the current system.
183 * scsi_checktgt() is used as a workaround for this problem.
184 */
185 for (b = 0; b < MAX_SCG; b++) {
186 for (t = 0; t < MAX_TGT; t++) {
187 if (scsi_checktgt(scgp, scglocal(scgp)->scgfile, b, t, 0)) {
188 for (l = 0; l < MAX_LUN; l++)
189 scglocal(scgp)->scgfiles[b][t][l] = 1;
190 /*
191 * Found a target on this bus.
192 * Comment the 'break' for a complete scan.
193 */
194 break;
195 }
196 }
197 }
198 return (1);
199 }
200
201 LOCAL int
202 scgo_close(scgp)
203 SCSI *scgp;
204 {
205 if (scgp->local == NULL)
206 return (-1);
207
208 if (scglocal(scgp)->scgfile >= 0)
209 close(scglocal(scgp)->scgfile);
210 scglocal(scgp)->scgfile = -1;
211 return (0);
212 }
213
214 /*
215 * We send a test unit ready command to the target to check whether the
216 * OS is considering this target to be valid.
217 * XXX Is this really needed? We should rather let the cmd fail later.
218 */
219 LOCAL BOOL
220 scsi_checktgt(scgp, f, busno, tgt, tlun)
221 SCSI *scgp;
222 int f;
223 int busno;
224 int tgt;
225 int tlun;
226 {
227 struct scg_cmd *sp = scgp->scmd;
228 struct scg_cmd sc;
229 int ret;
230 int ofd = scgp->fd;
231 int obus = scg_scsibus(scgp);
232 int otgt = scg_target(scgp);
233 int olun = scg_lun(scgp);
234
235 scg_settarget(scgp, busno, tgt, tlun);
236 scgp->fd = f;
237
238 sc = *sp;
239 fillbytes((caddr_t)sp, sizeof (*sp), '\0');
240 sp->addr = (caddr_t)0;
241 sp->size = 0;
242 sp->flags = SCG_DISRE_ENA | SCG_SILENT;
243 sp->cdb_len = SC_G0_CDBLEN;
244 sp->sense_len = CCS_SENSE_LEN;
245 sp->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
246 sp->cdb.g0_cdb.lun = scg_lun(scgp);
247
248 scgo_send(scgp);
249 scg_settarget(scgp, obus, otgt, olun);
250 scgp->fd = ofd;
251
252 if (sp->error != SCG_FATAL)
253 return (TRUE);
254 ret = sp->ux_errno != EINVAL;
255 *sp = sc;
256 return (ret);
257 }
258
259
260 LOCAL long
261 scgo_maxdma(scgp, amt)
262 SCSI *scgp;
263 long amt;
264 {
265 long maxdma = MAX_DMA_OSF_CAM;
266
267 return (maxdma);
268 }
269
270 LOCAL void *
271 scgo_getbuf(scgp, amt)
272 SCSI *scgp;
273 long amt;
274 {
275 if (scgp->debug > 0) {
276 js_fprintf((FILE *)scgp->errfile,
277 "scgo_getbuf: %ld bytes\n", amt);
278 }
279 scgp->bufbase = valloc((size_t)(amt));
280 return (scgp->bufbase);
281 }
282
283 LOCAL void
284 scgo_freebuf(scgp)
285 SCSI *scgp;
286 {
287 if (scgp->bufbase)
288 free(scgp->bufbase);
289 scgp->bufbase = NULL;
290 }
291
292 LOCAL BOOL
293 scgo_havebus(scgp, busno)
294 SCSI *scgp;
295 int busno;
296 {
297 register int t;
298
299 if (busno < 0 || busno >= MAX_SCG)
300 return (FALSE);
301
302 if (scgp->local == NULL)
303 return (FALSE);
304
305 for (t = 0; t < MAX_TGT; t++) {
306 if (scglocal(scgp)->scgfiles[busno][t][0] != 0)
307 return (TRUE);
308 }
309 return (FALSE);
310 }
311
312
313 LOCAL int
314 scgo_fileno(scgp, busno, tgt, tlun)
315 SCSI *scgp;
316 int busno;
317 int tgt;
318 int tlun;
319 {
320 if (scgp->local == NULL)
321 return (-1);
322
323 return ((busno < 0 || busno >= MAX_SCG) ? -1 : scglocal(scgp)->scgfile);
324 }
325
326 LOCAL int
327 scgo_initiator_id(scgp)
328 SCSI *scgp;
329 {
330 return (-1);
331 }
332
333 LOCAL int
334 scgo_isatapi(scgp)
335 SCSI *scgp;
336 {
337 return (FALSE);
338 }
339
340 LOCAL int
341 scgo_reset(scgp, what)
342 SCSI *scgp;
343 int what;
344 {
345 errno = EINVAL;
346 return (-1);
347 }
348
349 LOCAL int
350 scgo_send(scgp)
351 SCSI *scgp;
352 {
353 struct scg_cmd *sp = scgp->scmd;
354 CCB_SCSIIO ccb;
355 UAGT_CAM_CCB ua;
356 unsigned char *cdb;
357 CCB_RELSIM relsim;
358 UAGT_CAM_CCB relua;
359 int i;
360
361 if (scgp->fd < 0) {
362 sp->error = SCG_FATAL;
363 return (0);
364 }
365
366 fillbytes(&ua, sizeof (UAGT_CAM_CCB), 0);
367 fillbytes(&ccb, sizeof (CCB_SCSIIO), 0);
368
369 ua.uagt_ccb = (CCB_HEADER *) &ccb;
370 ua.uagt_ccblen = sizeof (CCB_SCSIIO);
371 ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb;
372 ccb.cam_ch.cam_ccb_len = sizeof (CCB_SCSIIO);
373
374 ua.uagt_snsbuf = ccb.cam_sense_ptr = sp->u_sense.cmd_sense;
375 ua.uagt_snslen = ccb.cam_sense_len = AUTO_SENSE_LEN;
376
377 cdb = (unsigned char *) ccb.cam_cdb_io.cam_cdb_bytes;
378
379 ccb.cam_timeout = sp->timeout;
380
381 ccb.cam_data_ptr = ua.uagt_buffer = (Uchar *) sp->addr;
382 ccb.cam_dxfer_len = ua.uagt_buflen = sp->size;
383 ccb.cam_ch.cam_func_code = XPT_SCSI_IO;
384 ccb.cam_ch.cam_flags = 0; /* CAM_DIS_CALLBACK; */
385
386 if (sp->size == 0) {
387 ccb.cam_data_ptr = ua.uagt_buffer = (Uchar *) NULL;
388 ccb.cam_ch.cam_flags |= CAM_DIR_NONE;
389 } else {
390 if (sp->flags & SCG_RECV_DATA) {
391 ccb.cam_ch.cam_flags |= CAM_DIR_IN;
392 } else {
393 ccb.cam_ch.cam_flags |= CAM_DIR_OUT;
394 }
395 }
396
397 ccb.cam_cdb_len = sp->cdb_len;
398 for (i = 0; i < sp->cdb_len; i++)
399 cdb[i] = sp->cdb.cmd_cdb[i];
400
401 ccb.cam_ch.cam_path_id = scg_scsibus(scgp);
402 ccb.cam_ch.cam_target_id = scg_target(scgp);
403 ccb.cam_ch.cam_target_lun = scg_lun(scgp);
404
405 sp->sense_count = 0;
406 sp->ux_errno = 0;
407 sp->error = SCG_NO_ERROR;
408
409
410 if (ioctl(scgp->fd, UAGT_CAM_IO, (caddr_t) &ua) < 0) {
411 sp->ux_errno = geterrno();
412 sp->error = SCG_FATAL;
413 if (scgp->debug > 0) {
414 errmsg("ioctl(fd, UAGT_CAM_IO, dev=%d,%d,%d) failed.\n",
415 scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
416 }
417 return (0);
418 }
419 if (scgp->debug > 0) {
420 errmsgno(EX_BAD, "cam_status = 0x%.2X scsi_status = 0x%.2X dev=%d,%d,%d\n",
421 ccb.cam_ch.cam_status,
422 ccb.cam_scsi_status,
423 scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
424 fflush(stderr);
425 }
426 switch (ccb.cam_ch.cam_status & CAM_STATUS_MASK) {
427
428 case CAM_REQ_CMP: break;
429
430 case CAM_SEL_TIMEOUT: sp->error = SCG_FATAL;
431 sp->ux_errno = EIO;
432 break;
433
434 case CAM_CMD_TIMEOUT: sp->error = SCG_TIMEOUT;
435 sp->ux_errno = EIO;
436 break;
437
438 default: sp->error = SCG_RETRYABLE;
439 sp->ux_errno = EIO;
440 break;
441 }
442
443 sp->u_scb.cmd_scb[0] = ccb.cam_scsi_status;
444
445 if (ccb.cam_ch.cam_status & CAM_AUTOSNS_VALID) {
446 sp->sense_count = MIN(ccb.cam_sense_len - ccb.cam_sense_resid,
447 SCG_MAX_SENSE);
448 sp->sense_count = MIN(sp->sense_count, sp->sense_len);
449 if (sp->sense_len < 0)
450 sp->sense_count = 0;
451 }
452 sp->resid = ccb.cam_resid;
453
454
455 /*
456 * this is perfectly wrong.
457 * But without this, we hang...
458 */
459 if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN) {
460 fillbytes(&relsim, sizeof (CCB_RELSIM), 0);
461 relsim.cam_ch.cam_ccb_len = sizeof (CCB_SCSIIO);
462 relsim.cam_ch.cam_func_code = XPT_REL_SIMQ;
463 relsim.cam_ch.cam_flags = CAM_DIR_IN | CAM_DIS_CALLBACK;
464 relsim.cam_ch.cam_path_id = scg_scsibus(scgp);
465 relsim.cam_ch.cam_target_id = scg_target(scgp);
466 relsim.cam_ch.cam_target_lun = scg_lun(scgp);
467
468 relua.uagt_ccb = (struct ccb_header *) & relsim; /* wrong cast */
469 relua.uagt_ccblen = sizeof (relsim);
470 relua.uagt_buffer = NULL;
471 relua.uagt_buflen = 0;
472
473 if (ioctl(scgp->fd, UAGT_CAM_IO, (caddr_t) & relua) < 0)
474 errmsg("DEC CAM -> LMA\n");
475 }
476 return (0);
477 }

  ViewVC Help
Powered by ViewVC 1.1.5