Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / libusal / scsi-beos.c
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-beos.c      1.23 06/02/05 Copyright 1998 J. Schilling */
14 /*
15  *      Interface for the BeOS user-land raw SCSI implementation.
16  *
17  *      This is a hack, that tries to emulate the functionality
18  *      of the usal driver.
19  *
20  *      First version done by swetland@be.com
21  *
22  *      Warning: you may change this source, but if you do that
23  *      you need to change the _usal_version and _usal_auth* string below.
24  *      You may not return "schily" for an SCG_AUTHOR request anymore.
25  *      Choose your name instead of "schily" and make clear that the version
26  *      string is related to a modified source.
27  *
28  *      Copyright (c) 1998 J. Schilling
29  */
30 /*
31  * This program is free software; you can redistribute it and/or modify
32  * it under the terms of the GNU General Public License version 2
33  * as published by the Free Software Foundation.
34  *
35  * This program is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  * GNU General Public License for more details.
39  *
40  * You should have received a copy of the GNU General Public License along with
41  * this program; see the file COPYING.  If not, write to the Free Software
42  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43  */
44
45
46 /*
47  *      Warning: you may change this source, but if you do that
48  *      you need to change the _usal_version and _usal_auth* string below.
49  *      You may not return "schily" for an SCG_AUTHOR request anymore.
50  *      Choose your name instead of "schily" and make clear that the version
51  *      string is related to a modified source.
52  */
53 static  char    _usal_trans_version[] = "scsi-beos.c-1.23";     /* The version for this transport*/
54
55 /*
56  * There are also defines for:
57  *      B_BEOS_VERSION_4
58  *      B_BEOS_VERSION_4_5
59  *
60  * in BeOS 5
61  */
62 #ifndef B_BEOS_VERSION_5
63 /*
64  * New BeOS seems to include <be/kernel/OS.h> from device/scsi.h
65  */
66
67 /* nasty hack to avoid broken def of bool in SupportDefs.h */
68 #define _SUPPORT_DEFS_H
69
70 #ifndef _SYS_TYPES_H
71 typedef unsigned long                   ulong;
72 typedef unsigned int                    uint;
73 typedef unsigned short                  ushort;
74 #endif  /* _SYS_TYPES_H */
75
76 #include <BeBuild.h>
77 #include <sys/types.h>
78 #include <Errors.h>
79
80
81 /*-------------------------------------------------------------*/
82 /*----- Shorthand type formats --------------------------------*/
83
84 typedef signed char                     int8;
85 typedef unsigned char                   uint8;
86 typedef volatile signed char            vint8;
87 typedef volatile unsigned char          vuint8;
88
89 typedef short                           int16;
90 typedef unsigned short                  uint16;
91 typedef volatile short                  vint16;
92 typedef volatile unsigned short         vuint16;
93
94 typedef long                            int32;
95 typedef unsigned long                   uint32;
96 typedef volatile long                   vint32;
97 typedef volatile unsigned long          vuint32;
98
99 typedef long long                       int64;
100 typedef unsigned long long              uint64;
101 typedef volatile long long              vint64;
102 typedef volatile unsigned long long     vuint64;
103
104 typedef volatile long                   vlong;
105 typedef volatile int                    vint;
106 typedef volatile short                  vshort;
107 typedef volatile char                   vchar;
108
109 typedef volatile unsigned long          vulong;
110 typedef volatile unsigned int           vuint;
111 typedef volatile unsigned short         vushort;
112 typedef volatile unsigned char          vuchar;
113
114 typedef unsigned char                   uchar;
115 typedef unsigned short                  unichar;
116
117
118
119 /*-------------------------------------------------------------*/
120 /*----- Descriptive formats -----------------------------------*/
121 typedef int32                                   status_t;
122 typedef int64                                   bigtime_t;
123 typedef uint32                                  type_code;
124 typedef uint32                                  perform_code;
125
126 /* end nasty hack */
127
128 #endif  /* ! B_BEOS_VERSION_5 */
129
130
131 #include <stdlib.h>
132 #include <stdio.h>
133 #include <string.h>
134 #include <unistd.h>
135 #include <sys/stat.h>
136 #include <usal/usalio.h>
137
138 /* this is really really dumb (tm) */
139 /*#undef sense*/
140 /*#undef scb*/
141 #include <device/scsi.h>
142
143 #undef bool
144 #include <drivers/CAM.h>
145
146 struct _fdmap_ {
147         struct _fdmap_ *next;
148         int bus;
149         int targ;
150         int lun;
151         int fd;
152 };
153
154 /*
155  * Return version information for the low level SCSI transport code.
156  * This has been introduced to make it easier to trace down problems
157  * in applications.
158  */
159 static char *
160 usalo_version(SCSI *usalp, int what)
161 {
162         if (usalp != (SCSI *)0) {
163                 switch (what) {
164
165                 case SCG_VERSION:
166                         return (_usal_trans_version);
167                 /*
168                  * If you changed this source, you are not allowed to
169                  * return "schily" for the SCG_AUTHOR request.
170                  */
171                 case SCG_AUTHOR:
172                         return (_usal_auth_cdrkit);
173                 case SCG_SCCS_ID:
174                         return (__sccsid);
175                 }
176         }
177         return ((char *)0);
178 }
179
180 static int
181 usalo_help(SCSI *usalp, FILE *f)
182 {
183         __usal_help(f, "CAM", "Generic transport independent SCSI (BeOS CAM variant)",
184                 "", "bus,target,lun", "1,2,0", TRUE, FALSE);
185         return (0);
186 }
187
188 static int
189 usalo_open(SCSI *usalp, char *device)
190 {
191         int     busno   = usal_scsibus(usalp);
192         int     tgt     = usal_target(usalp);
193 #ifdef  nonono
194         int     tlun    = usal_lun(usalp);
195 #endif
196
197 #ifdef  nonono
198         if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
199                 errno = EINVAL;
200                 if (usalp->errstr)
201                         snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
202                                 "Illegal value for busno, target or lun '%d,%d,%d'",
203                                 busno, tgt, tlun);
204                 return (-1);
205         }
206 #endif
207
208         if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
209                 errno = EINVAL;
210                 if (usalp->errstr)
211                         snprintf(usalp->errstr, SCSI_ERRSTR_SIZE,
212                                 "Open by 'devname' not supported on this OS");
213                 return (-1);
214         }
215         return (1);
216 }
217
218 static int
219 usalo_close(SCSI *usalp)
220 {
221         struct _fdmap_  *f;
222         struct _fdmap_  *fnext;
223
224         for (f = (struct _fdmap_ *)usalp->local; f; f = fnext) {
225                 usalp->local = 0;
226                 fnext = f->next;
227                 close(f->fd);
228                 free(f);
229         }
230         return (0);
231 }
232
233 static long
234 usalo_maxdma(SCSI *usalp, long amt)
235 {
236         return (128*1024);
237         return (256*1024);
238 }
239
240 static void *
241 usalo_getbuf(SCSI *usalp, long amt)
242 {
243         if (usalp->debug > 0) {
244                 fprintf((FILE *)usalp->errfile,
245                         "usalo_getbuf: %ld bytes\n", amt);
246         }
247         usalp->bufbase = malloc((size_t)(amt));
248         return (usalp->bufbase);
249 }
250
251 static void
252 usalo_freebuf(SCSI *usalp)
253 {
254         if (usalp->bufbase)
255                 free(usalp->bufbase);
256         usalp->bufbase = NULL;
257 }
258
259 static BOOL
260 usalo_havebus(SCSI *usalp, int busno)
261 {
262         struct stat     sb;
263         char            buf[128];
264
265         if (busno < 8)
266                 snprintf(buf, sizeof (buf), "/dev/bus/scsi/%d", busno);
267         else
268                 snprintf(buf, sizeof (buf), "/dev/disk/ide/atapi/%d", busno-8);
269         if (stat(buf, &sb))
270                 return (FALSE);
271         return (TRUE);
272 }
273
274 static int
275 usalo_fileno(SCSI *usalp, int busno, int tgt, int tlun)
276 {
277         struct _fdmap_  *f;
278         char            buf[128];
279         int             fd;
280
281         for (f = (struct _fdmap_ *)usalp->local; f; f = f->next) {
282                 if (f->bus == busno && f->targ == tgt && f->lun == tlun)
283                         return (f->fd);
284         }
285         if (busno < 8) {
286                 snprintf(buf, sizeof (buf),
287                                         "/dev/bus/scsi/%d/%d/%d/raw",
288                                         busno, tgt, tlun);
289         } else {
290                 char *tgtstr = (tgt == 0) ? "master" : (tgt == 1) ? "slave" : "dummy";
291                 snprintf(buf, sizeof (buf),
292                                         "/dev/disk/ide/atapi/%d/%s/%d/raw",
293                                         busno-8, tgtstr, tlun);
294         }
295         fd = open(buf, 0);
296
297         if (fd >= 0) {
298                 f = (struct _fdmap_ *) malloc(sizeof (struct _fdmap_));
299                 f->bus = busno;
300                 f->targ = tgt;
301                 f->lun = tlun;
302                 f->fd = fd;
303                 f->next = (struct _fdmap_ *)usalp->local;
304                 usalp->local = f;
305         }
306         return (fd);
307 }
308
309 static int
310 usalo_initiator_id(SCSI *usalp)
311 {
312         return (-1);
313 }
314
315 static int
316 usalo_isatapi(SCSI *usalp)
317 {
318         /*
319          * XXX Should check for ATAPI
320          */
321         return (-1);
322 }
323
324 static int
325 usalo_reset(SCSI *usalp, int what)
326 {
327         errno = EINVAL;
328         return (-1);
329 }
330
331 static int
332 usalo_send(SCSI *usalp)
333 {
334         struct usal_cmd         *sp = usalp->scmd;
335         int                     e;
336         int                     scsi_error;
337         int                     cam_error;
338         raw_device_command      rdc;
339
340         if (usalp->fd < 0) {
341                 sp->error = SCG_FATAL;
342                 return (0);
343         }
344
345         memcpy(rdc.command, &(sp->cdb), 12);
346         rdc.command_length = sp->cdb_len;
347         rdc.data = sp->addr;
348         rdc.data_length = sp->size;
349         rdc.sense_data_length = sp->sense_len;
350         rdc.sense_data = sp->u_sense.cmd_sense;
351         rdc.flags = sp->flags & SCG_RECV_DATA ? B_RAW_DEVICE_DATA_IN : 0;
352         if (sp->size > 0)
353                 rdc.flags |= B_RAW_DEVICE_REPORT_RESIDUAL;
354         rdc.timeout = sp->timeout * 1000000;
355
356         sp->error               = SCG_NO_ERROR;
357         sp->sense_count         = 0;
358         sp->u_scb.cmd_scb[0]    = 0;
359         sp->resid               = 0;
360
361         if (usalp->debug > 0) {
362                 fprintf(stderr, "SEND(%d): cmd %02x, cdblen = %d, datalen = %ld, senselen = %ld\n",
363                         usalp->fd, rdc.command[0], rdc.command_length,
364                         rdc.data_length, rdc.sense_data_length);
365         }
366         e = ioctl(usalp->fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof (rdc));
367         if (usalp->debug > 0) {
368                 fprintf(stderr, "SEND(%d): -> %d CAM Status %02X SCSI status %02X\n", e, rdc.cam_status, rdc.scsi_status);
369         }
370         sp->ux_errno = 0;
371 #ifdef  DEBUG
372         fprintf(stderr, "err %d errno %x CAM %X SL %d DL %d/%d FL %X\n",
373                 e, geterrno(), rdc.cam_status,
374                 rdc.sense_data_length, rdc.data_length, sp->size, rdc.flags);
375 #endif
376         if (!e) {
377                 cam_error = rdc.cam_status;
378                 scsi_error = rdc.scsi_status;
379                 sp->u_scb.cmd_scb[0] = scsi_error;
380                 if (sp->size > 0)
381                         sp->resid = sp->size - rdc.data_length;
382
383                 switch (cam_error & CAM_STATUS_MASK) {
384
385                 case CAM_REQ_CMP:
386                         sp->error = SCG_NO_ERROR;
387                         break;
388
389                 case CAM_REQ_CMP_ERR:
390                         sp->sense_count = sp->sense_len; /* XXX */
391                         sp->error = SCG_NO_ERROR;
392                         sp->ux_errno = EIO;
393                         break;
394
395                 case CAM_CMD_TIMEOUT:
396                         sp->error = SCG_TIMEOUT;
397                         sp->ux_errno = EIO;
398
399                 case CAM_SEL_TIMEOUT:
400                         sp->error = SCG_FATAL;
401                         sp->ux_errno = EIO;
402                         break;
403
404                 default:
405                         sp->error = SCG_RETRYABLE;
406                         sp->ux_errno = EIO;
407                 }
408         } else {
409                 sp->error = SCG_FATAL;
410                 sp->ux_errno = geterrno();
411                 sp->resid = sp->size;
412         }
413         return (0);
414 }