1 /* @(#)scsi-beos.c 1.29 09/06/30 Copyright 1998-2009 J. Schilling */
2 #ifndef lint
3 static char __sccsid[] =
4 "@(#)scsi-beos.c 1.29 09/06/30 Copyright 1998-2009 J. Schilling";
5 #endif
6 /*
7 * Interface for the BeOS user-land raw SCSI implementation.
8 *
9 * This is a hack, that tries to emulate the functionality
10 * of the scg driver.
11 *
12 * First version done by swetland@be.com
13 *
14 * Warning: you may change this source, but if you do that
15 * you need to change the _scg_version and _scg_auth* string below.
16 * You may not return "schily" for an SCG_AUTHOR request anymore.
17 * Choose your name instead of "schily" and make clear that the version
18 * string is related to a modified source.
19 *
20 * Copyright (c) 1998-2009 J. Schilling
21 */
22 /*
23 * The contents of this file are subject to the terms of the
24 * Common Development and Distribution License, Version 1.0 only
25 * (the "License"). You may not use this file except in compliance
26 * with the License.
27 *
28 * See the file CDDL.Schily.txt in this distribution for details.
29 * A copy of the CDDL is also available via the Internet at
30 * http://www.opensource.org/licenses/cddl1.txt
31 *
32 * The following exceptions apply:
33 * CDDL �3.6 needs to be replaced by: "You may create a Larger Work by
34 * combining Covered Software with other code if all other code is governed by
35 * the terms of a license that is OSI approved (see www.opensource.org) and
36 * you may distribute the Larger Work as a single product. In such a case,
37 * You must make sure the requirements of this License are fulfilled for
38 * the Covered Software."
39 *
40 * When distributing Covered Code, include this CDDL HEADER in each
41 * file and include the License file CDDL.Schily.txt from this distribution.
42 */
43
44
45 /*
46 * Warning: you may change this source, but if you do that
47 * you need to change the _scg_version and _scg_auth* string below.
48 * You may not return "schily" for an SCG_AUTHOR request anymore.
49 * Choose your name instead of "schily" and make clear that the version
50 * string is related to a modified source.
51 */
52 LOCAL char _scg_trans_version[] = "scsi-beos.c-1.29"; /* The version for this transport*/
53
54 /*
55 * There are also defines for:
56 * B_BEOS_VERSION_4
57 * B_BEOS_VERSION_4_5
58 *
59 * in BeOS 5
60 */
61 #ifdef B_BEOS_VERSION_5
62 #define NEW_BEOS
63 #endif
64 #ifdef __HAIKU__
65 #define NEW_BEOS
66 #endif
67
68 #ifndef NEW_BEOS
69 /*
70 * New BeOS seems to include <be/kernel/OS.h> from device/scsi.h
71 */
72
73 /* nasty hack to avoid broken def of bool in SupportDefs.h */
74 #define _SUPPORT_DEFS_H
75
76 #ifndef _SYS_TYPES_H
77 typedef unsigned long ulong;
78 typedef unsigned int uint;
79 typedef unsigned short ushort;
80 #endif /* _SYS_TYPES_H */
81
82 #include <BeBuild.h>
83 #include <schily/types.h>
84 #include <Errors.h>
85
86
87 /*-------------------------------------------------------------*/
88 /*----- Shorthand type formats --------------------------------*/
89
90 typedef signed char int8;
91 typedef unsigned char uint8;
92 typedef volatile signed char vint8;
93 typedef volatile unsigned char vuint8;
94
95 typedef short int16;
96 typedef unsigned short uint16;
97 typedef volatile short vint16;
98 typedef volatile unsigned short vuint16;
99
100 typedef long int32;
101 typedef unsigned long uint32;
102 typedef volatile long vint32;
103 typedef volatile unsigned long vuint32;
104
105 typedef long long int64;
106 typedef unsigned long long uint64;
107 typedef volatile long long vint64;
108 typedef volatile unsigned long long vuint64;
109
110 typedef volatile long vlong;
111 typedef volatile int vint;
112 typedef volatile short vshort;
113 typedef volatile char vchar;
114
115 typedef volatile unsigned long vulong;
116 typedef volatile unsigned int vuint;
117 typedef volatile unsigned short vushort;
118 typedef volatile unsigned char vuchar;
119
120 typedef unsigned char uchar;
121 typedef unsigned short unichar;
122
123
124
125 /*-------------------------------------------------------------*/
126 /*----- Descriptive formats -----------------------------------*/
127 typedef int32 status_t;
128 typedef int64 bigtime_t;
129 typedef uint32 type_code;
130 typedef uint32 perform_code;
131
132 /* end nasty hack */
133
134 #endif /* ! B_BEOS_VERSION_5 */
135
136
137 #include <schily/stdlib.h>
138 #include <schily/stdio.h>
139 #include <schily/string.h>
140 #include <schily/unistd.h>
141 #include <schily/stat.h>
142 #include <scg/scgio.h>
143
144 /* this is really really dumb (tm) */
145 /*#undef sense*/
146 /*#undef scb*/
147 #include <device/scsi.h>
148
149 #undef bool
150 #ifdef __HAIKU__ /* Probaby already since BeOS 5 */
151 #include <CAM.h>
152 #else
153 #include <drivers/CAM.h>
154 #endif
155
156 struct _fdmap_ {
157 struct _fdmap_ *next;
158 int bus;
159 int targ;
160 int lun;
161 int fd;
162 };
163
164 /*
165 * Return version information for the low level SCSI transport code.
166 * This has been introduced to make it easier to trace down problems
167 * in applications.
168 */
169 LOCAL char *
scgo_version(scgp,what)170 scgo_version(scgp, what)
171 SCSI *scgp;
172 int what;
173 {
174 if (scgp != (SCSI *)0) {
175 switch (what) {
176
177 case SCG_VERSION:
178 return (_scg_trans_version);
179 /*
180 * If you changed this source, you are not allowed to
181 * return "schily" for the SCG_AUTHOR request.
182 */
183 case SCG_AUTHOR:
184 return (_scg_auth_schily);
185 case SCG_SCCS_ID:
186 return (__sccsid);
187 }
188 }
189 return ((char *)0);
190 }
191
192 LOCAL int
scgo_help(scgp,f)193 scgo_help(scgp, f)
194 SCSI *scgp;
195 FILE *f;
196 {
197 __scg_help(f, "CAM", "Generic transport independent SCSI (BeOS CAM variant)",
198 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
199 return (0);
200 }
201
202 LOCAL int
scgo_open(scgp,device)203 scgo_open(scgp, device)
204 SCSI *scgp;
205 char *device;
206 {
207 int busno = scg_scsibus(scgp);
208 int tgt = scg_target(scgp);
209 #ifdef nonono
210 int tlun = scg_lun(scgp);
211 #endif
212
213 #ifdef nonono
214 if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
215 errno = EINVAL;
216 if (scgp->errstr)
217 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
218 "Illegal value for busno, target or lun '%d,%d,%d'",
219 busno, tgt, tlun);
220 return (-1);
221 }
222 #endif
223
224 if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
225 errno = EINVAL;
226 if (scgp->errstr)
227 js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
228 "Open by 'devname' not supported on this OS");
229 return (-1);
230 }
231 return (1);
232 }
233
234 LOCAL int
scgo_close(scgp)235 scgo_close(scgp)
236 SCSI *scgp;
237 {
238 struct _fdmap_ *f;
239 struct _fdmap_ *fnext;
240
241 for (f = (struct _fdmap_ *)scgp->local; f; f = fnext) {
242 scgp->local = 0;
243 fnext = f->next;
244 close(f->fd);
245 free(f);
246 }
247 return (0);
248 }
249
250 LOCAL long
scgo_maxdma(scgp,amt)251 scgo_maxdma(scgp, amt)
252 SCSI *scgp;
253 long amt;
254 {
255 return (128*1024);
256 return (256*1024);
257 }
258
259 LOCAL void *
scgo_getbuf(scgp,amt)260 scgo_getbuf(scgp, amt)
261 SCSI *scgp;
262 long amt;
263 {
264 if (scgp->debug > 0) {
265 js_fprintf((FILE *)scgp->errfile,
266 "scgo_getbuf: %ld bytes\n", amt);
267 }
268 scgp->bufbase = malloc((size_t)(amt));
269 return (scgp->bufbase);
270 }
271
272 LOCAL void
scgo_freebuf(scgp)273 scgo_freebuf(scgp)
274 SCSI *scgp;
275 {
276 if (scgp->bufbase)
277 free(scgp->bufbase);
278 scgp->bufbase = NULL;
279 }
280
281 LOCAL int
scgo_numbus(scgp)282 scgo_numbus(scgp)
283 SCSI *scgp;
284 {
285 return (16); /* XXX we need a better way to find the # of busses */
286 }
287
288 LOCAL BOOL
scgo_havebus(scgp,busno)289 scgo_havebus(scgp, busno)
290 SCSI *scgp;
291 int busno;
292 {
293 struct stat sb;
294 char buf[128];
295
296 if (busno < 8)
297 js_snprintf(buf, sizeof (buf), "/dev/bus/scsi/%d", busno);
298 else
299 #ifdef __HAIKU__
300 js_snprintf(buf, sizeof (buf), "/dev/disk/atapi/%d", busno-8);
301 #else
302 js_snprintf(buf, sizeof (buf), "/dev/disk/ide/atapi/%d", busno-8);
303 #endif
304 if (stat(buf, &sb))
305 return (FALSE);
306 return (TRUE);
307 }
308
309 LOCAL int
scgo_fileno(scgp,busno,tgt,tlun)310 scgo_fileno(scgp, busno, tgt, tlun)
311 SCSI *scgp;
312 int busno;
313 int tgt;
314 int tlun;
315 {
316 struct _fdmap_ *f;
317 char buf[128];
318 int fd;
319
320 for (f = (struct _fdmap_ *)scgp->local; f; f = f->next) {
321 if (f->bus == busno && f->targ == tgt && f->lun == tlun)
322 return (f->fd);
323 }
324 if (busno < 8) {
325 js_snprintf(buf, sizeof (buf),
326 "/dev/bus/scsi/%d/%d/%d/raw",
327 busno, tgt, tlun);
328 } else {
329 char *tgtstr = (tgt == 0) ? "master" : (tgt == 1) ? "slave" : "dummy";
330 js_snprintf(buf, sizeof (buf),
331 #ifdef __HAIKU__
332 "/dev/disk/atapi/%d/%s/raw",
333 busno-8, tgtstr);
334 #else
335 "/dev/disk/ide/atapi/%d/%s/%d/raw",
336 busno-8, tgtstr, tlun);
337 #endif
338 }
339 fd = open(buf, 0);
340
341 if (fd >= 0) {
342 f = (struct _fdmap_ *) malloc(sizeof (struct _fdmap_));
343 f->bus = busno;
344 f->targ = tgt;
345 f->lun = tlun;
346 f->fd = fd;
347 f->next = (struct _fdmap_ *)scgp->local;
348 scgp->local = f;
349 }
350 return (fd);
351 }
352
353 LOCAL int
scgo_initiator_id(scgp)354 scgo_initiator_id(scgp)
355 SCSI *scgp;
356 {
357 return (-1);
358 }
359
360 LOCAL int
scgo_isatapi(scgp)361 scgo_isatapi(scgp)
362 SCSI *scgp;
363 {
364 /*
365 * XXX Should check for ATAPI
366 */
367 return (-1);
368 }
369
370 LOCAL int
scgo_reset(scgp,what)371 scgo_reset(scgp, what)
372 SCSI *scgp;
373 int what;
374 {
375 errno = EINVAL;
376 return (-1);
377 }
378
379 LOCAL int
scgo_send(scgp)380 scgo_send(scgp)
381 SCSI *scgp;
382 {
383 struct scg_cmd *sp = scgp->scmd;
384 int e;
385 int scsi_error;
386 int cam_error;
387 raw_device_command rdc;
388
389 if (scgp->fd < 0) {
390 sp->error = SCG_FATAL;
391 return (0);
392 }
393
394 memcpy(rdc.command, &(sp->cdb), 12);
395 rdc.command_length = sp->cdb_len;
396 rdc.data = sp->addr;
397 rdc.data_length = sp->size;
398 rdc.sense_data_length = sp->sense_len;
399 rdc.sense_data = sp->u_sense.cmd_sense;
400 rdc.flags = sp->flags & SCG_RECV_DATA ? B_RAW_DEVICE_DATA_IN : 0;
401 if (sp->size > 0)
402 rdc.flags |= B_RAW_DEVICE_REPORT_RESIDUAL;
403 rdc.timeout = sp->timeout * 1000000;
404
405 sp->error = SCG_NO_ERROR;
406 sp->sense_count = 0;
407 sp->u_scb.cmd_scb[0] = 0;
408 sp->resid = 0;
409
410 if (scgp->debug > 0) {
411 error("SEND(%d): cmd %02x, cdblen = %d, datalen = %ld, senselen = %ld\n",
412 scgp->fd, rdc.command[0], rdc.command_length,
413 rdc.data_length, rdc.sense_data_length);
414 }
415 e = ioctl(scgp->fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof (rdc));
416 if (scgp->debug > 0) {
417 error("SEND(%d): -> %d CAM Status %02X SCSI status %02X\n", e, rdc.cam_status, rdc.scsi_status);
418 }
419 sp->ux_errno = 0;
420 #ifdef DEBUG
421 error("err %d errno %x CAM %X SL %d DL %d/%d FL %X\n",
422 e, geterrno(), rdc.cam_status,
423 rdc.sense_data_length, rdc.data_length, sp->size, rdc.flags);
424 #endif
425 if (!e) {
426 cam_error = rdc.cam_status;
427 scsi_error = rdc.scsi_status;
428 sp->u_scb.cmd_scb[0] = scsi_error;
429 if (sp->size > 0)
430 sp->resid = sp->size - rdc.data_length;
431
432 switch (cam_error & CAM_STATUS_MASK) {
433
434 case CAM_REQ_CMP:
435 sp->error = SCG_NO_ERROR;
436 break;
437
438 case CAM_REQ_CMP_ERR:
439 sp->sense_count = sp->sense_len; /* XXX */
440 sp->error = SCG_NO_ERROR;
441 sp->ux_errno = EIO;
442 break;
443
444 case CAM_CMD_TIMEOUT:
445 sp->error = SCG_TIMEOUT;
446 sp->ux_errno = EIO;
447
448 case CAM_SEL_TIMEOUT:
449 sp->error = SCG_FATAL;
450 sp->ux_errno = EIO;
451 break;
452
453 default:
454 sp->error = SCG_RETRYABLE;
455 sp->ux_errno = EIO;
456 }
457 } else {
458 sp->error = SCG_FATAL;
459 sp->ux_errno = geterrno();
460 sp->resid = sp->size;
461 }
462 return (0);
463 }
464