~ubuntu-branches/ubuntu/utopic/cdrdao/utopic

« back to all changes in this revision

Viewing changes to scsilib/libscg/scsi-linux-ata.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Suffield
  • Date: 2004-06-24 22:33:16 UTC
  • Revision ID: james.westby@ubuntu.com-20040624223316-534onzugaeeyq61j
Tags: upstream-1.1.9
ImportĀ upstreamĀ versionĀ 1.1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* @(#)scsi-linux-ata.c 1.6 04/05/20 Copyright 2002 J. Schilling */
 
2
#ifndef lint
 
3
static  char ata_sccsid[] =
 
4
        "@(#)scsi-linux-ata.c   1.6 04/05/20 Copyright 2002 J. Schilling";
 
5
#endif
 
6
/*
 
7
 *      Interface for Linux generic SCSI implementation (sg).
 
8
 *
 
9
 *      This is the interface for the broken Linux SCSI generic driver.
 
10
 *      This is a hack, that tries to emulate the functionality
 
11
 *      of the scg driver.
 
12
 *
 
13
 *      Warning: you may change this source, but if you do that
 
14
 *      you need to change the _scg_version and _scg_auth* string below.
 
15
 *      You may not return "schily" for an SCG_AUTHOR request anymore.
 
16
 *      Choose your name instead of "schily" and make clear that the version
 
17
 *      string is related to a modified source.
 
18
 *
 
19
 *      Copyright (c) 2002 J. Schilling
 
20
 *
 
21
 *      Thanks to Alexander Kern <alex.kern@gmx.de> for the idea and first
 
22
 *      code fragments for supporting the CDROM_SEND_PACKET ioctl() from
 
23
 *      the cdrom.c kernel driver. Please note that this interface in priciple
 
24
 *      is completely unneeded but the Linux kernel is just a cluster of
 
25
 *      code and does not support planned orthogonal interface systems.
 
26
 *      For this reason we need CDROM_SEND_PACKET in order to work around a
 
27
 *      bug in the linux kernel that prevents to use PCATA drives because
 
28
 *      the kernel panics if you try to put ide-scsi on top of the PCATA
 
29
 *      driver.
 
30
 */
 
31
/*
 
32
 * This program is free software; you can redistribute it and/or modify
 
33
 * it under the terms of the GNU General Public License as published by
 
34
 * the Free Software Foundation; either version 2, or (at your option)
 
35
 * any later version.
 
36
 *
 
37
 * This program is distributed in the hope that it will be useful,
 
38
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
39
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
40
 * GNU General Public License for more details.
 
41
 *
 
42
 * You should have received a copy of the GNU General Public License along with
 
43
 * this program; see the file COPYING.  If not, write to the Free Software
 
44
 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
45
 */
 
46
 
 
47
#ifdef  USE_ATA
 
48
 
 
49
LOCAL   char    _scg_atrans_version[] = "scsi-linux-ata.c-1.6"; /* The version for ATAPI transport*/
 
50
 
 
51
LOCAL   char *  scgo_aversion   __PR((SCSI *scgp, int what));
 
52
LOCAL   int     scgo_ahelp      __PR((SCSI *scgp, FILE *f));
 
53
LOCAL   int     scgo_aopen      __PR((SCSI *scgp, char *device));
 
54
LOCAL   int     scgo_aclose     __PR((SCSI *scgp));
 
55
LOCAL   long    scgo_amaxdma    __PR((SCSI *scgp, long amt));
 
56
LOCAL   BOOL    scgo_ahavebus   __PR((SCSI *scgp, int));
 
57
LOCAL   int     scgo_afileno    __PR((SCSI *scgp, int, int, int));
 
58
LOCAL   int     scgo_ainitiator_id __PR((SCSI *scgp));
 
59
LOCAL   int     scgo_aisatapi   __PR((SCSI *scgp));
 
60
LOCAL   int     scgo_areset     __PR((SCSI *scgp, int what));
 
61
LOCAL   int     scgo_asend      __PR((SCSI *scgp));
 
62
 
 
63
LOCAL scg_ops_t ata_ops = {
 
64
        scgo_asend,
 
65
        scgo_aversion,
 
66
        scgo_ahelp,
 
67
        scgo_aopen,
 
68
        scgo_aclose,
 
69
        scgo_amaxdma,
 
70
        scgo_getbuf,            /* Shared with SG driver */
 
71
        scgo_freebuf,           /* Shared with SG driver */
 
72
        scgo_ahavebus,
 
73
        scgo_afileno,
 
74
        scgo_ainitiator_id,
 
75
        scgo_aisatapi,
 
76
        scgo_areset,
 
77
};
 
78
 
 
79
#define HOST_EMPTY      0xF
 
80
#define HOST_SCSI       0x0
 
81
#define HOST_IDE        0x1
 
82
#define HOST_USB        0x2
 
83
#define HOST_IEEE1389   0x3
 
84
#define HOST_PARALLEL   0x4
 
85
#define HOST_OTHER      0xE
 
86
 
 
87
 
 
88
#define typlocal(p, schillybus)         scglocal(p)->bc[schillybus].typ
 
89
#define buslocal(p, schillybus)         scglocal(p)->bc[schillybus].bus
 
90
#define hostlocal(p, schillybus)        scglocal(p)->bc[schillybus].host
 
91
 
 
92
#define MAX_DMA_ATA (131072-1)  /* EINVAL (hart) ENOMEM (weich) bei mehr ... */
 
93
                                /* Bei fehlerhaftem Sense Pointer kommt EFAULT */
 
94
 
 
95
LOCAL int scgo_send             __PR((SCSI * scgp));
 
96
LOCAL BOOL sg_amapdev           __PR((SCSI * scgp, int f, char *device, int *bus,
 
97
                                        int *target, int *lun));
 
98
LOCAL BOOL sg_amapdev_scsi      __PR((SCSI * scgp, int f, int *busp, int *tgtp,
 
99
                                        int *lunp, int *chanp, int *inop));
 
100
LOCAL int scgo_aget_first_free_shillybus __PR((SCSI * scgp, int subsystem,
 
101
                                        int host, int bus));
 
102
LOCAL int scgo_amerge           __PR((char *path, char *readedlink,
 
103
                                        char *buffer, int buflen));
 
104
 
 
105
/*
 
106
 * uncomment this when you will get a debug file #define DEBUG
 
107
 */
 
108
#ifdef DEBUG
 
109
#define LOGFILE "scsi-linux-ata.log"
 
110
#define log(a)  sglog a
 
111
 
 
112
LOCAL   void    sglog           __PR((const char *fmt, ...));
 
113
 
 
114
#include <vadefs.h>
 
115
 
 
116
/* VARARGS1 */
 
117
#ifdef  PROTOTYPES
 
118
LOCAL void
 
119
sglog(const char *fmt, ...)
 
120
#else
 
121
LOCAL void
 
122
error(fmt, va_alist)
 
123
        char    *fmt;
 
124
        va_dcl
 
125
#endif
 
126
{
 
127
        va_list args;
 
128
        FILE    *f       = fopen(LOGFILE, "a");
 
129
 
 
130
        if (f == NULL)
 
131
                return;
 
132
 
 
133
#ifdef  PROTOTYPES
 
134
        va_start(args, fmt);
 
135
#else
 
136
        va_start(args);
 
137
#endif
 
138
        js_fprintf(f, "%r", fmt, args);
 
139
        va_end(args);
 
140
        fclose(f);
 
141
}
 
142
#else
 
143
#define log(a)
 
144
#endif  /* DEBUG */
 
145
 
 
146
LOCAL   int     scan_internal __PR((SCSI * scgp, int *fatal));
 
147
 
 
148
/*
 
149
 * Return version information for the low level SCSI transport code.
 
150
 * This has been introduced to make it easier to trace down problems
 
151
 * in applications.
 
152
 */
 
153
LOCAL char *
 
154
scgo_aversion(scgp, what)
 
155
        SCSI    *scgp;
 
156
        int     what;
 
157
{
 
158
        if (scgp != (SCSI *)0) {
 
159
                switch (what) {
 
160
 
 
161
                case SCG_VERSION:
 
162
                        return (_scg_atrans_version);
 
163
                /*
 
164
                 * If you changed this source, you are not allowed to
 
165
                 * return "schily" for the SCG_AUTHOR request.
 
166
                 */
 
167
                case SCG_AUTHOR:
 
168
                        return (_scg_auth_schily);
 
169
                case SCG_SCCS_ID:
 
170
                        return (ata_sccsid);
 
171
                }
 
172
        }
 
173
        return ((char *)0);
 
174
}
 
175
 
 
176
LOCAL int
 
177
scgo_ahelp(scgp, f)
 
178
        SCSI    *scgp;
 
179
        FILE    *f;
 
180
{
 
181
        __scg_help(f, "ATA", "ATA Packet specific SCSI transport",
 
182
                "ATAPI:", "bus,target,lun", "ATAPI:1,2,0", TRUE, FALSE);
 
183
        return (0);
 
184
}
 
185
 
 
186
LOCAL int
 
187
scgo_aopen(scgp, device)
 
188
        SCSI    *scgp;
 
189
        char    *device;
 
190
{
 
191
        int     bus = scg_scsibus(scgp);
 
192
        int     target = scg_target(scgp);
 
193
        int     lun = scg_lun(scgp);
 
194
 
 
195
        register int    f;
 
196
        register int    b;
 
197
        register int    t;
 
198
        register int    l;
 
199
                int     nopen = 0;
 
200
 
 
201
        if (scgp->overbose)
 
202
                error("Warning: Using ATA Packet interface.\n");
 
203
        if (scgp->overbose) {
 
204
                error("Warning: The related libscg interface code is in pre alpha.\n");
 
205
                error("Warning: There may be fatal problems.\n");
 
206
        }
 
207
 
 
208
        log(("\n<<<<<<<<<<<<<<<<  LOGGING ON >>>>>>>>>>>>>>>>>\n"));
 
209
        if (bus >= MAX_SCHILLY_HOSTS || target >= MAX_TGT || lun >= MAX_LUN) {
 
210
                errno = EINVAL;
 
211
                if (scgp->errstr)
 
212
                        js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
 
213
                                "Illegal value for bus, target or lun '%d,%d,%d'",
 
214
                                bus, target, lun);
 
215
 
 
216
                return (-1);
 
217
        }
 
218
 
 
219
        if (scgp->local == NULL) {
 
220
                scgp->local = malloc(sizeof (struct scg_local));
 
221
                if (scgp->local == NULL) {
 
222
                        return (0);
 
223
                }
 
224
 
 
225
                scglocal(scgp)->scgfile = -1;
 
226
                scglocal(scgp)->pgbus = -2;
 
227
                scglocal(scgp)->SCSIbuf = (char *)-1;
 
228
                scglocal(scgp)->pack_id = 5;
 
229
                scglocal(scgp)->drvers = -1;
 
230
                scglocal(scgp)->isold = -1;
 
231
                scglocal(scgp)->xbufsize = 0L;
 
232
                scglocal(scgp)->xbuf = NULL;
 
233
 
 
234
 
 
235
                for (b = 0; b < MAX_SCHILLY_HOSTS; b++) {
 
236
                        typlocal(scgp, b) = HOST_EMPTY;
 
237
                        for (t = 0; t < MAX_TGT; t++) {
 
238
                                for (l = 0; l < MAX_LUN; l++)
 
239
                                        scglocal(scgp)->scgfiles[b][t][l] = (short) -1;
 
240
                        }
 
241
                }
 
242
        }
 
243
 
 
244
        if (device != NULL && strcmp(device, "ATAPI") == 0)
 
245
                goto atascan;
 
246
 
 
247
        /* if not scanning */
 
248
        if ((device != NULL && *device != '\0') || (bus == -2 && target == -2))
 
249
                goto openbydev;
 
250
 
 
251
atascan:
 
252
        if (scan_internal(scgp, &nopen)) {
 
253
                if (scgp->errstr)
 
254
                        js_printf(scgp->errstr, "INFO: scan_internal(...) failed");
 
255
                return (-1);
 
256
        }
 
257
        return (nopen);
 
258
 
 
259
openbydev:
 
260
        if (device != NULL && strncmp(device, "ATAPI:", 6) == 0)
 
261
                device += 6;
 
262
        if (scgp->debug > 3) {
 
263
                js_fprintf((FILE *) scgp->errfile, "INFO: do scgo_open openbydev");
 
264
        }
 
265
        if (device != NULL && *device != '\0') {
 
266
                int     schilly_bus,
 
267
                        starget,
 
268
                        slun;
 
269
 
 
270
                f = open(device, O_RDONLY | O_NONBLOCK);
 
271
 
 
272
                if (f < 0) {
 
273
                        if (scgp->errstr)
 
274
                                js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
 
275
                                        "Cannot open '%s'", device);
 
276
                        return (0);
 
277
                }
 
278
                if (sg_amapdev(scgp, f, device, &schilly_bus, &starget, &slun)) {
 
279
                        scg_settarget(scgp, schilly_bus, starget, slun);
 
280
                        return (++nopen);
 
281
                }
 
282
        }
 
283
        return (nopen);
 
284
}
 
285
 
 
286
LOCAL int
 
287
scan_internal(scgp, nopen)
 
288
        SCSI    *scgp;
 
289
        int     *nopen;
 
290
{
 
291
        int     i,
 
292
                f;
 
293
        int     schilly_bus,
 
294
                target,
 
295
                lun;
 
296
        char    device[128];
 
297
        /*
 
298
         * try always with devfs
 
299
         * unfortunatelly the solution with test of existing
 
300
         * of '/dev/.devfsd' don't work, because it root.root 700
 
301
         * and i don't like run suid root
 
302
         */
 
303
        BOOL    DEVFS = TRUE;
 
304
 
 
305
        if (DEVFS) {
 
306
                for (i = 0; ; i++) {
 
307
                        sprintf(device, "/dev/cdroms/cdrom%i", i);
 
308
                        if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
 
309
                                if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
 
310
                                        if (scgp->debug > 4) {
 
311
                                                js_fprintf((FILE *) scgp->errfile,
 
312
                                                "try open(%s) return %i, errno %i, cancel\n", device, f, errno);
 
313
                                        }
 
314
                                        return (-2);
 
315
                                } else if (errno == ENOENT || errno == ENODEV) {
 
316
                                        if (scgp->debug > 4) {
 
317
                                                js_fprintf((FILE *) scgp->errfile,
 
318
                                                "try open(%s) return %i, errno %i\n", device, f, errno);
 
319
                                        }
 
320
                                        if (0 == i) {
 
321
                                                DEVFS = FALSE;
 
322
                                                if (scgp->debug > 4) {
 
323
                                                        js_fprintf((FILE *) scgp->errfile,
 
324
                                                        "DEVFS not detected, continuing with old dev\n");
 
325
                                                }
 
326
                                        }
 
327
                                        break;
 
328
                                }
 
329
                                if (scgp->debug > 4) {
 
330
                                        if (errno == EACCES) {
 
331
                                                js_fprintf((FILE *) scgp->errfile,
 
332
                                                "errno (EACCESS), you don't have the needed rights for %s\n",
 
333
                                                device);
 
334
                                        }
 
335
                                        js_fprintf((FILE *) scgp->errfile,
 
336
                                        "try open(%s) return %i, errno %i, trying next cdrom\n",
 
337
                                        device, f, errno);
 
338
                                }
 
339
                        } else {
 
340
                                if (scgp->debug > 4) {
 
341
                                        js_fprintf((FILE *) scgp->errfile,
 
342
                                        "try open(%s) return %i errno %i calling sg_mapdev(...)\n",
 
343
                                        device, f, errno);
 
344
                                }
 
345
                                if (sg_amapdev(scgp, f, device, &schilly_bus, &target, &lun)) {
 
346
                                        (++(*nopen));
 
347
                                } else {
 
348
                                        close(f);
 
349
                                }
 
350
                        }
 
351
                }
 
352
        }
 
353
        if (!DEVFS) {
 
354
                /* for /dev/sr0 - /dev/sr? */
 
355
                for (i = 0; ; i++) {
 
356
                        sprintf(device, "/dev/sr%i", i);
 
357
                        if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
 
358
                                if (errno != ENOENT && errno != ENXIO && errno != ENODEV && errno != EACCES) {
 
359
                                        if (scgp->debug > 4) {
 
360
                                                js_fprintf((FILE *) scgp->errfile,
 
361
                                                "try open(%s) return %i, errno %i, cancel\n",
 
362
                                                device, f, errno);
 
363
                                        }
 
364
                                        return (-2);
 
365
                                } else if (errno == ENOENT || errno == ENODEV) {
 
366
                                        break;
 
367
                                }
 
368
                        } else {
 
369
                                if (sg_amapdev(scgp, f, device, &schilly_bus, &target, &lun)) {
 
370
                                        (++(*nopen));
 
371
                                } else {
 
372
                                        close(f);
 
373
                                }
 
374
                        }
 
375
                }
 
376
 
 
377
                /* for /dev/hda - /dev/hdz */
 
378
                for (i = 'a'; i <= 'z'; i++) {
 
379
                        sprintf(device, "/dev/hd%c", i);
 
380
                        if ((f = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
 
381
                                if (errno != ENOENT && errno != ENXIO && errno != EACCES) {
 
382
                                        if (scgp->debug > 4) {
 
383
                                                js_fprintf((FILE *) scgp->errfile,
 
384
                                                "try open(%s) return %i, errno %i, cancel\n",
 
385
                                                device, f, errno);
 
386
                                        }
 
387
                                        return (-2);
 
388
                                } else if (errno == ENOENT || errno == ENODEV) {
 
389
                                        break;
 
390
                                }
 
391
                        } else {
 
392
                                /* ugly hack, make better, when you can. Alex */
 
393
                                if (0 > ioctl(f, CDROM_DRIVE_STATUS, CDSL_CURRENT)) {
 
394
                                        if (scgp->debug > 4) {
 
395
                                                js_fprintf((FILE *) scgp->errfile,
 
396
                                                "%s is not a cdrom, skipping\n",
 
397
                                                device);
 
398
                                        }
 
399
                                        close(f);
 
400
                                } else if (sg_amapdev(scgp, f, device, &schilly_bus, &target, &lun)) {
 
401
                                        (++(*nopen));
 
402
                                } else {
 
403
                                        close(f);
 
404
                                }
 
405
                        }
 
406
                }
 
407
        }
 
408
        return (0);
 
409
}
 
410
 
 
411
LOCAL int
 
412
scgo_aclose(scgp)
 
413
        SCSI    *scgp;
 
414
{
 
415
        register int    f;
 
416
        register int    h;
 
417
        register int    t;
 
418
        register int    l;
 
419
 
 
420
        if (scgp->local == NULL)
 
421
                return (-1);
 
422
 
 
423
        for (h = 0; h < MAX_SCHILLY_HOSTS; h++) {
 
424
                typlocal(scgp, h) = (HOST_EMPTY);
 
425
                for (t = 0; t < MAX_TGT; t++) {
 
426
                        for (l = 0; l < MAX_LUN; l++) {
 
427
                                f = scglocal(scgp)->scgfiles[h][t][l];
 
428
                                if (f >= 0)
 
429
                                        close(f);
 
430
                                scglocal(scgp)->scgfiles[h][t][l] = (short) -1;
 
431
                        }
 
432
                }
 
433
        }
 
434
 
 
435
        if (scglocal(scgp)->xbuf != NULL) {
 
436
                free(scglocal(scgp)->xbuf);
 
437
                scglocal(scgp)->xbufsize = 0L;
 
438
                scglocal(scgp)->xbuf = NULL;
 
439
        }
 
440
        log(("<<<<<<<<<<<<<<<<  LOGGING OFF >>>>>>>>>>>>>>>>>\n\n"));
 
441
        return (0);
 
442
}
 
443
 
 
444
LOCAL int
 
445
scgo_aget_first_free_shillybus(scgp, subsystem, host, bus)
 
446
        SCSI    *scgp;
 
447
        int     subsystem;
 
448
        int     host;
 
449
        int     bus;
 
450
{
 
451
        int     first_free_schilly_bus;
 
452
 
 
453
        for (first_free_schilly_bus = 0;
 
454
                        first_free_schilly_bus < MAX_SCHILLY_HOSTS;
 
455
                                                first_free_schilly_bus++) {
 
456
 
 
457
                if (typlocal(scgp, first_free_schilly_bus) == HOST_EMPTY ||
 
458
                    (typlocal(scgp, first_free_schilly_bus) == subsystem &&
 
459
                    hostlocal(scgp, first_free_schilly_bus) == host &&
 
460
                    buslocal(scgp, first_free_schilly_bus) == bus))
 
461
                        break;
 
462
        }
 
463
 
 
464
        if (first_free_schilly_bus >= MAX_SCHILLY_HOSTS) {
 
465
                errmsgno(EX_BAD, "ERROR: in scgo_get_first_free_shillybus(...). Too many CDROMs, more than %i",
 
466
                        MAX_SCHILLY_HOSTS);
 
467
                errmsgno(EX_BAD, "Increase MAX_SCHILLY_HOSTS in scsi-linux-ata.c and recompile!");
 
468
                return (-1);
 
469
        }
 
470
        return (first_free_schilly_bus);
 
471
}
 
472
 
 
473
LOCAL int
 
474
scgo_amerge(path, readedlink, buffer, buflen)
 
475
        char    *path;
 
476
        char    *readedlink;
 
477
        char    *buffer;
 
478
        int     buflen;
 
479
{
 
480
        char    *aa;
 
481
 
 
482
#define TOKEN_ARRAY             20
 
483
#define LAST_CHAR(x)            (x)[strlen((x))-1]
 
484
#define ONE_CHAR_BACK(x)        (x)[strlen((x))-1] = '\0'
 
485
        char    *ppa[TOKEN_ARRAY];
 
486
        char    *pa;
 
487
 
 
488
        int     i;
 
489
        int     len;
 
490
        char    seps[] = "/";
 
491
        char    *last_slash;
 
492
 
 
493
        if (!path || !readedlink || !buffer)
 
494
                return (-EINVAL);
 
495
 
 
496
        if ('/' == readedlink[0]) {
 
497
                aa = (char *) malloc(strlen(readedlink) + 1);
 
498
                if (!aa)
 
499
                        return (-ENOMEM);
 
500
 
 
501
                strcpy(aa, readedlink);
 
502
        } else {
 
503
                aa = (char *) malloc(strlen(path) + strlen(readedlink) + 1);
 
504
                if (!aa)
 
505
                        return (-ENOMEM);
 
506
 
 
507
                strcpy(aa, path);
 
508
                if (LAST_CHAR(aa) == '/') {
 
509
                        ONE_CHAR_BACK(aa);
 
510
                }
 
511
                last_slash = strrchr(aa, '/');
 
512
                if (last_slash == NULL)
 
513
                        strcpy(aa, "/");
 
514
                else
 
515
                        *(++last_slash) = '\0';
 
516
                strcat(aa, readedlink);
 
517
        }
 
518
        memset(ppa, 0x00, sizeof (ppa));
 
519
 
 
520
        for (i = 0, pa = strtok(aa, seps);
 
521
                i < TOKEN_ARRAY && pa != NULL;
 
522
                ++i, pa = strtok(NULL, seps)) {
 
523
                ppa[i] = pa;
 
524
        }
 
525
 
 
526
        if (i == TOKEN_ARRAY) {
 
527
                free(aa);
 
528
                return (-ENOMEM);
 
529
        }
 
530
        for (i = 0; i < TOKEN_ARRAY && ppa[i]; i++) {
 
531
                if (strcmp(ppa[i], "..") == 0) {
 
532
                        ppa[i] = NULL;
 
533
                        if (i > 1)
 
534
                                ppa[i - 1] = NULL;
 
535
                }
 
536
        }
 
537
 
 
538
        /* dry run */
 
539
        len = 0;
 
540
        for (i = 0; i < TOKEN_ARRAY; i++) {
 
541
                if (ppa[i]) {
 
542
                        len += 1;
 
543
                        len += strlen(ppa[i]);
 
544
                }
 
545
        }
 
546
        if (0 == len)
 
547
                len = 1;
 
548
 
 
549
        if (len + 1 <= buflen) {
 
550
                strcpy(buffer, "");
 
551
                for (i = 0; i < TOKEN_ARRAY; i++) {
 
552
                        if (ppa[i]) {
 
553
                                strcat(buffer, "/");
 
554
                                strcat(buffer, ppa[i]);
 
555
                        }
 
556
                }
 
557
 
 
558
                if (strlen(buffer) == 0)
 
559
                        strcpy(buffer, "/");
 
560
        }
 
561
        free(aa);
 
562
 
 
563
        return (len + 1);
 
564
}
 
565
 
 
566
/*
 
567
 *      /dev/cdroms/cdrom0      first CD-ROM
 
568
 *      /dev/cdroms/cdrom1      second CD-ROM
 
569
 *
 
570
 *
 
571
 *      SCSI Devices
 
572
 *
 
573
 *      To uniquely identify any SCSI device requires the following information:
 
574
 *
 
575
 *      controller      (host adapter)
 
576
 *      bus             (SCSI channel)
 
577
 *      target          (SCSI ID)
 
578
 *      unit            (Logical Unit Number)
 
579
 *
 
580
 *      All SCSI devices are placed under /dev/scsi (assuming devfs is mounted on /dev).
 
581
 *      Hence, a SCSI device with the following parameters:
 
582
 *              c=1,b=2,t=3,u=4 would appear as:
 
583
 *
 
584
 *              /dev/scsi/host1/bus2/target3/lun4       device directory
 
585
 *
 
586
 *      Inside this directory, a number of device entries may be created,
 
587
 *      depending on which SCSI device-type drivers were installed.
 
588
 *
 
589
 *      See the section on the disc naming scheme to see what entries
 
590
 *      the SCSI disc driver creates.
 
591
 *
 
592
 *      See the section on the tape naming scheme to see what entries
 
593
 *      the SCSI tape driver creates.
 
594
 *
 
595
 *      The SCSI CD-ROM driver creates:  cd
 
596
 *      The SCSI generic driver creates: generic
 
597
 *
 
598
 *      IDE Devices
 
599
 *
 
600
 *      To uniquely identify any IDE device requires the following information:
 
601
 *
 
602
 *      controller
 
603
 *      bus             (0/1 aka. primary/secondary)
 
604
 *      target          (0/1 aka. master/slave)
 
605
 *      unit
 
606
 *
 
607
 *      All IDE devices are placed under /dev/ide, and uses a similar
 
608
 *      naming scheme to the SCSI subsystem.
 
609
 *
 
610
 *
 
611
 *      Example /dev/cdroms/cdrom0 ->  /dev/scsi/host1/bus2/target3/lun4/cd
 
612
 *      Example /dev/cdroms/cdrom1 ->  /dev/ide/host1/bus0/target1/lun4/cd
 
613
 *
 
614
 */
 
615
LOCAL BOOL
 
616
sg_amapdev(scgp, f, device, schillybus, target, lun)
 
617
        SCSI    *scgp;
 
618
        int     f;
 
619
        char    *device;
 
620
        int     *schillybus;
 
621
        int     *target;
 
622
        int     *lun;
 
623
{
 
624
        struct host {
 
625
                char    host[4];
 
626
                char    host_no;
 
627
        };
 
628
        struct bus {
 
629
                char    bus[3];
 
630
                char    bus_no;
 
631
        };
 
632
        struct target {
 
633
                char    target[6];
 
634
                char    target_no;
 
635
        };
 
636
        struct lun {
 
637
                char    lun[3];
 
638
                char    lun_no;
 
639
        };
 
640
 
 
641
        int     h,
 
642
                b,
 
643
                t,
 
644
                l;
 
645
 
 
646
#define TOKEN_DEV               "dev"
 
647
#define TOKEN_SUBSYSTEM_SCSI    "scsi"
 
648
#define TOKEN_SUBSYSTEM_IDE     "ide"
 
649
#define TOKEN_HOST              "host"
 
650
#define TOKEN_BUS               "bus"
 
651
#define TOKEN_TARGET            "target"
 
652
#define TOKEN_LUN               "lun"
 
653
#define TOKEN_CD                "cd"
 
654
 
 
655
#define ID_TOKEN_DEV            0
 
656
#define ID_TOKEN_SUBSYSTEM      1
 
657
#define ID_TOKEN_HOST           2
 
658
#define ID_TOKEN_BUS            3
 
659
#define ID_TOKEN_TARGET         4
 
660
#define ID_TOKEN_LUN            5
 
661
#define ID_TOKEN_CD             6
 
662
#define ID_TOKEN_LAST           ID_TOKEN_CD
 
663
#define ID_TOKEN_MAX            ID_TOKEN_LAST + 2
 
664
#define CHARTOINT(x)            (abs(atoi(&x)))
 
665
 
 
666
        char            *token[ID_TOKEN_MAX],
 
667
                        *seps = "/";
 
668
        int             i,
 
669
                        result;
 
670
        struct stat     buf;
 
671
 
 
672
#ifndef MAX_PATH
 
673
#define MAX_PATH 260
 
674
#endif
 
675
#define LOCAL_MAX_PATH MAX_PATH
 
676
        char            tmp[LOCAL_MAX_PATH],
 
677
                        tmp1[LOCAL_MAX_PATH];
 
678
        int             first_free_schilly_bus;
 
679
        int             subsystem = HOST_EMPTY;
 
680
 
 
681
        /* old DEV */
 
682
        typedef struct {
 
683
                char            prefix[2];
 
684
                char            device;
 
685
        } old_dev;
 
686
        /* strtok need char* instead of const char* */
 
687
        result = stat(device, &buf);
 
688
        if (result || !S_ISBLK(buf.st_mode))
 
689
                return (FALSE);
 
690
 
 
691
        result = lstat(device, &buf);
 
692
        if (!result && S_ISLNK(buf.st_mode)) {
 
693
                result = readlink(device, tmp, LOCAL_MAX_PATH);
 
694
                if (result > 0 && result < LOCAL_MAX_PATH) {
 
695
                        tmp[result] = '\0';
 
696
 
 
697
                        result = scgo_amerge(device, tmp, tmp1, LOCAL_MAX_PATH);
 
698
                        if (result > 0 && result < LOCAL_MAX_PATH) {
 
699
                                tmp1[result] = '\0';
 
700
                                strcpy(tmp, tmp1);
 
701
                        } else {
 
702
                                errmsgno(EX_BAD,
 
703
                                "ERROR: with link merging! base %s link %s, result of merging %i\n",
 
704
                                        device, tmp, result);
 
705
                                return (FALSE);
 
706
                        }
 
707
                } else {
 
708
                        errmsgno(EX_BAD,
 
709
                        "ERROR: with link reading! link %s, result of readlink %i\n",
 
710
                                device, result);
 
711
                        return (FALSE);
 
712
                }
 
713
        } else {
 
714
                strncpy(tmp, device, sizeof (tmp));
 
715
        }
 
716
        if (scgp->debug > 3) {
 
717
                js_fprintf((FILE *) scgp->errfile, "INFO: %s -> %s\n", device, tmp);
 
718
        }
 
719
        memset(token, 0x00, sizeof (token));
 
720
        i = 0;
 
721
        token[i] = strtok(tmp, seps);
 
722
        while (token[i] != NULL && (++i) && i < ID_TOKEN_MAX) {
 
723
                token[i] = strtok(NULL, seps);
 
724
        }
 
725
 
 
726
        if (i == ID_TOKEN_MAX ||
 
727
                !(token[ID_TOKEN_DEV]) ||
 
728
                strcmp(token[ID_TOKEN_DEV], TOKEN_DEV)) {
 
729
 
 
730
                errmsgno(EX_BAD, "ERROR: unknow format\n");
 
731
                errmsgno(EX_BAD, "EXAMPLE: /dev/scsi/host1/bus2/target3/lun4/cd\n");
 
732
                errmsgno(EX_BAD, "EXAMPLE: /dev/ide/host0/bus0/target1/lun0/cd\n");
 
733
                errmsgno(EX_BAD, "EXAMPLE: /dev/hda or /dev/sr0\n");
 
734
                return (FALSE);
 
735
        }
 
736
        if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_SCSI)) ||
 
737
            !(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
 
738
                h = CHARTOINT(((struct host *) token[ID_TOKEN_HOST])->host_no);
 
739
                b = CHARTOINT(((struct bus *) token[ID_TOKEN_BUS])->bus_no);
 
740
                t = CHARTOINT(((struct target *) token[ID_TOKEN_TARGET])->target_no);
 
741
                l = CHARTOINT(((struct lun *) token[ID_TOKEN_LUN])->lun_no);
 
742
#ifdef PARANOID
 
743
                if (strncmp(token[ID_TOKEN_HOST], TOKEN_HOST, strlen(TOKEN_HOST))) {
 
744
                        log(("ERROR: invalid host specified\n"));
 
745
                        return (FALSE);
 
746
                }
 
747
                if (strncmp(token[ID_TOKEN_BUS], TOKEN_BUS, strlen(TOKEN_BUS))) {
 
748
                        log(("ERROR: invalid bus specified\n"));
 
749
                        return (FALSE);
 
750
                }
 
751
                if (strncmp(token[ID_TOKEN_TARGET], TOKEN_TARGET, strlen(TOKEN_TARGET))) {
 
752
                        log(("ERROR: invalid target specified\n"));
 
753
                        return (FALSE);
 
754
                }
 
755
                if (strncmp(token[ID_TOKEN_LUN], TOKEN_LUN, strlen(TOKEN_LUN))) {
 
756
                        log(("ERROR: invalid lun specified\n"));
 
757
                        return (FALSE);
 
758
                }
 
759
                if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
 
760
                        if (b > 1 || t > 1) {
 
761
                                log(("ERROR: invalid bus or target for IDE specified\n"));
 
762
                                return (FALSE);
 
763
                        }
 
764
                }
 
765
#endif  /* PARANOID */
 
766
 
 
767
                if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_IDE))) {
 
768
                        subsystem = HOST_IDE;
 
769
                } else if (!(strcmp(token[ID_TOKEN_SUBSYSTEM], TOKEN_SUBSYSTEM_SCSI))) {
 
770
                        subsystem = HOST_SCSI;
 
771
                } else {
 
772
                        subsystem = HOST_OTHER;
 
773
                }
 
774
        } else if (!token[ID_TOKEN_HOST] &&
 
775
                strlen(token[ID_TOKEN_SUBSYSTEM]) == sizeof (old_dev)) {
 
776
                char    j;
 
777
 
 
778
                old_dev *pDev = (old_dev *) token[ID_TOKEN_SUBSYSTEM];
 
779
 
 
780
                if (strncmp(pDev->prefix, "hd", 2) == 0) {
 
781
                        j = pDev->device - ('a');
 
782
 
 
783
                        subsystem = HOST_IDE;
 
784
                        h = j / 4;
 
785
                        b = (j % 4) / 2;
 
786
                        t = (j % 4) % 2;
 
787
                        l = 0;
 
788
                } else if (strncmp(pDev->prefix, "sr", 2) == 0) {
 
789
#ifdef  nonono
 
790
                        if (pDev->device >= '0' && pDev->device <= '9')
 
791
                                j = pDev->device - ('0');
 
792
                        else
 
793
                                j = pDev->device - ('a');
 
794
 
 
795
 
 
796
                        h = j / 4;
 
797
                        b = (j % 4) / 2;
 
798
                        t = (j % 4) % 2;
 
799
                        l = 0;
 
800
#endif  /* nonono */
 
801
                        /* other solution, with ioctl */
 
802
                        int     Chan,
 
803
                                Ino,
 
804
                                Bus,
 
805
                                Target,
 
806
                                Lun;
 
807
 
 
808
                        subsystem = HOST_SCSI;
 
809
                        sg_amapdev_scsi(scgp, f, &Bus, &Target, &Lun, &Chan, &Ino);
 
810
 
 
811
                        /* For old kernels try to make the best guess. */
 
812
#ifdef  nonono
 
813
                                int     n;
 
814
                                Ino |= Chan << 8;
 
815
                                n = sg_mapbus(scgp, Bus, Ino);
 
816
                                if (Bus == -1) {
 
817
                                        Bus = n;
 
818
                                        if (scgp->debug > 0) {
 
819
                                                js_fprintf((FILE *)scgp->errfile,
 
820
                                                        "SCSI Bus: %d (mapped from %d)\n",
 
821
                                                        Bus, Ino);
 
822
                                        }
 
823
                                }
 
824
/*                              It is me too high ;-()*/
 
825
#endif  /* nonono */
 
826
                        h = Ino;
 
827
                        b = Chan;
 
828
                        t = Target;
 
829
                        l = Lun;
 
830
                } else {
 
831
                        errmsgno(EX_BAD, "ERROR: unknow subsystem (%s) in (%s)\n",
 
832
                                token[ID_TOKEN_SUBSYSTEM], device);
 
833
                        return (FALSE);
 
834
                }
 
835
        } else {
 
836
                errmsgno(EX_BAD, "ERROR: unknow subsystem (%s) in (%s)\n",
 
837
                        token[ID_TOKEN_SUBSYSTEM], device);
 
838
                return (FALSE);
 
839
        }
 
840
 
 
841
        if (scgp->verbose)
 
842
                js_printf(scgp->errstr, "INFO: subsystem %s: h %i, b %i, t %i, l %i",
 
843
                        token[ID_TOKEN_SUBSYSTEM], h, b, t, l);
 
844
 
 
845
        first_free_schilly_bus = scgo_aget_first_free_shillybus(scgp, subsystem, h, b);
 
846
        if (-1 == first_free_schilly_bus) {
 
847
                return (FALSE);
 
848
        }
 
849
        if (scglocal(scgp)->scgfiles[first_free_schilly_bus][t][l] != (-1)) {
 
850
                errmsgno(EX_BAD, "ERROR: this cdrom is already mapped %s(%d,%d,%d)\n",
 
851
                        device, first_free_schilly_bus, t, l);
 
852
                return (FALSE);
 
853
        } else {
 
854
                scglocal(scgp)->scgfiles[first_free_schilly_bus][t][l] = f;
 
855
                typlocal(scgp, first_free_schilly_bus) = subsystem;
 
856
                hostlocal(scgp, first_free_schilly_bus) = h;
 
857
                buslocal(scgp, first_free_schilly_bus) = b;
 
858
                *schillybus = first_free_schilly_bus;
 
859
                *target = t;
 
860
                *lun = l;
 
861
 
 
862
                if (scgp->debug > 1) {
 
863
                        js_fprintf((FILE *) scgp->errfile,
 
864
                                "INFO: /dev/%s, (host%d/bus%d/target%d/lun%d) will be mapped on the schilly bus No %d (%d,%d,%d)\n",
 
865
                                token[ID_TOKEN_SUBSYSTEM], h, b, t, l,
 
866
                                first_free_schilly_bus, first_free_schilly_bus, t, l);
 
867
                }
 
868
        }
 
869
        return (TRUE);
 
870
}
 
871
 
 
872
LOCAL BOOL
 
873
sg_amapdev_scsi(scgp, f, busp, tgtp, lunp, chanp, inop)
 
874
        SCSI    *scgp;
 
875
        int     f;
 
876
        int     *busp;
 
877
        int     *tgtp;
 
878
        int     *lunp;
 
879
        int     *chanp;
 
880
        int     *inop;
 
881
{
 
882
        struct sg_id {
 
883
                long    l1;     /* target | lun << 8 | channel << 16 | low_ino << 24 */
 
884
                long    l2;     /* Unique id */
 
885
        } sg_id;
 
886
        int     Chan;
 
887
        int     Ino;
 
888
        int     Bus;
 
889
        int     Target;
 
890
        int     Lun;
 
891
 
 
892
        if (ioctl(f, SCSI_IOCTL_GET_IDLUN, &sg_id))
 
893
                return (FALSE);
 
894
 
 
895
        if (scgp->debug > 0) {
 
896
                js_fprintf((FILE *) scgp->errfile,
 
897
                        "INFO: l1: 0x%lX l2: 0x%lX\n", sg_id.l1, sg_id.l2);
 
898
        }
 
899
        if (ioctl(f, SCSI_IOCTL_GET_BUS_NUMBER, &Bus) < 0) {
 
900
                Bus = -1;
 
901
        }
 
902
        Target = sg_id.l1 & 0xFF;
 
903
        Lun = (sg_id.l1 >> 8) & 0xFF;
 
904
        Chan = (sg_id.l1 >> 16) & 0xFF;
 
905
        Ino = (sg_id.l1 >> 24) & 0xFF;
 
906
        if (scgp->debug > 0) {
 
907
                js_fprintf((FILE *) scgp->errfile,
 
908
                        "INFO: Bus: %d Target: %d Lun: %d Chan: %d Ino: %d\n",
 
909
                        Bus, Target, Lun, Chan, Ino);
 
910
        }
 
911
        *busp = Bus;
 
912
        *tgtp = Target;
 
913
        *lunp = Lun;
 
914
        if (chanp)
 
915
                *chanp = Chan;
 
916
        if (inop)
 
917
                *inop = Ino;
 
918
        return (TRUE);
 
919
}
 
920
 
 
921
LOCAL long
 
922
scgo_amaxdma(scgp, amt)
 
923
        SCSI    *scgp;
 
924
        long    amt;
 
925
{
 
926
        /*
 
927
         * EINVAL (hart) ENOMEM (weich) bei mehr ...
 
928
         * Bei fehlerhaftem Sense Pointer kommt EFAULT
 
929
         */
 
930
        return (MAX_DMA_ATA);
 
931
}
 
932
 
 
933
LOCAL BOOL
 
934
scgo_ahavebus(scgp, busno)
 
935
        SCSI    *scgp;
 
936
        int     busno;
 
937
{
 
938
        register int    t;
 
939
        register int    l;
 
940
 
 
941
        if (busno < 0 || busno >= MAX_SCHILLY_HOSTS)
 
942
                return (FALSE);
 
943
 
 
944
        if (scgp->local == NULL)
 
945
                return (FALSE);
 
946
 
 
947
        for (t = 0; t < MAX_TGT; t++) {
 
948
                for (l = 0; l < MAX_LUN; l++)
 
949
                        if (scglocal(scgp)->scgfiles[busno][t][l] >= 0)
 
950
                                return (TRUE);
 
951
        }
 
952
        return (FALSE);
 
953
}
 
954
 
 
955
LOCAL int
 
956
scgo_afileno(scgp, busno, tgt, tlun)
 
957
        SCSI    *scgp;
 
958
        int     busno;
 
959
        int     tgt;
 
960
        int     tlun;
 
961
{
 
962
        if (busno < 0 || busno >= MAX_SCHILLY_HOSTS ||
 
963
                tgt < 0 || tgt >= MAX_TGT ||
 
964
                tlun < 0 || tlun >= MAX_LUN)
 
965
                return (-1);
 
966
 
 
967
        if (scgp->local == NULL)
 
968
                return (-1);
 
969
 
 
970
        return ((int) scglocal(scgp)->scgfiles[busno][tgt][tlun]);
 
971
}
 
972
 
 
973
LOCAL int
 
974
scgo_ainitiator_id(scgp)
 
975
        SCSI    *scgp;
 
976
{
 
977
        js_printf(scgp->errstr, "NOT IMPELEMENTED: scgo_initiator_id");
 
978
        return (-1);
 
979
}
 
980
 
 
981
LOCAL int
 
982
scgo_aisatapi(scgp)
 
983
        SCSI    *scgp;
 
984
{
 
985
        int schillybus = scgp->addr.scsibus;
 
986
        int typ = typlocal(scgp, schillybus);
 
987
        if (typ == HOST_EMPTY)
 
988
                return (-1);
 
989
        if (typ != HOST_SCSI)
 
990
                return (1);
 
991
        else
 
992
                return (0);
 
993
}
 
994
 
 
995
LOCAL int
 
996
scgo_areset(scgp, what)
 
997
        SCSI    *scgp;
 
998
        int     what;
 
999
{
 
1000
        if (what == SCG_RESET_NOP)
 
1001
                return (0);
 
1002
 
 
1003
        if (what == SCG_RESET_TGT || what == SCG_RESET_BUS)
 
1004
                return (ioctl(what, CDROMRESET));
 
1005
 
 
1006
        return (-1);
 
1007
}
 
1008
 
 
1009
LOCAL int
 
1010
scgo_asend(scgp)
 
1011
        SCSI    *scgp;
 
1012
{
 
1013
        struct scg_cmd  *sp = scgp->scmd;
 
1014
        int             ret,
 
1015
                        i;
 
1016
        struct cdrom_generic_command sg_cgc;
 
1017
        struct request_sense sense_cgc;
 
1018
 
 
1019
#ifdef DEBUG
 
1020
        char            tmp_send[340],
 
1021
                        tmp_read[340],
 
1022
                        tmp_sense[340],
 
1023
                        tmp1[30];
 
1024
        int             j;
 
1025
        char            *p;
 
1026
#endif
 
1027
 
 
1028
        if (scgp->fd < 0) {
 
1029
                sp->error = SCG_FATAL;
 
1030
                sp->ux_errno = EIO;
 
1031
                return (0);
 
1032
        }
 
1033
        if (sp->cdb_len > CDROM_PACKET_SIZE) {
 
1034
                sp->error = SCG_FATAL;
 
1035
                sp->ux_errno = EIO;
 
1036
                return (0);
 
1037
        }
 
1038
        /* initialize */
 
1039
        fillbytes((caddr_t) & sg_cgc, sizeof (sg_cgc), '\0');
 
1040
        fillbytes((caddr_t) & sense_cgc, sizeof (sense_cgc), '\0');
 
1041
 
 
1042
        if (sp->flags & SCG_RECV_DATA) {
 
1043
                sg_cgc.data_direction = CGC_DATA_READ;
 
1044
        } else if (sp->size > 0) {
 
1045
                sg_cgc.data_direction = CGC_DATA_WRITE;
 
1046
        } else {
 
1047
                sg_cgc.data_direction = CGC_DATA_NONE;
 
1048
        }
 
1049
#if LINUX_VERSION_CODE >= 0x020403
 
1050
        if (sp->flags & SCG_SILENT) {
 
1051
                sg_cgc.quiet = 1;
 
1052
        }
 
1053
#endif
 
1054
        for (i = 0; i < sp->cdb_len; i++) {
 
1055
                sg_cgc.cmd[i] = sp->cdb.cmd_cdb[i];
 
1056
        }
 
1057
 
 
1058
        sg_cgc.buflen = sp->size;
 
1059
        sg_cgc.buffer = sp->addr;
 
1060
 
 
1061
        if (sp->sense_len > sizeof (sense_cgc))
 
1062
                sense_cgc.add_sense_len = sizeof (sense_cgc) - 8;
 
1063
        else
 
1064
                sense_cgc.add_sense_len = sp->sense_len - 8;
 
1065
 
 
1066
        sg_cgc.sense = &sense_cgc;
 
1067
#if LINUX_VERSION_CODE >= 0x020403
 
1068
        sg_cgc.timeout = sp->timeout * 1000;
 
1069
#endif
 
1070
#ifdef DEBUG
 
1071
        strcpy(tmp_send, "send cmd:\n");
 
1072
        for (j = 0; j < sp->cdb_len; j++) {
 
1073
                sprintf(tmp1, " %02X", sp->cdb.cmd_cdb[j]);
 
1074
                strcat(tmp_send, tmp1);
 
1075
        }
 
1076
        strcat(tmp_send, "\n");
 
1077
 
 
1078
        if (sg_cgc.data_direction == CGC_DATA_WRITE) {
 
1079
                int     z;
 
1080
 
 
1081
                sprintf(tmp1, "data_write: %i bytes\n", sp->size);
 
1082
                strcat(tmp_send, tmp1);
 
1083
                for (j = 0, z = 1; j < 80 && j < sp->size; j++, z++) {
 
1084
                        if (z > 16) {
 
1085
                                z = 1;
 
1086
                                strcat(tmp_send, "\n");
 
1087
                        }
 
1088
                        sprintf(tmp1, " %02X", (unsigned char) (sp->addr[j]));
 
1089
                        strcat(tmp_send, tmp1);
 
1090
                }
 
1091
                strcat(tmp_send, "\n");
 
1092
 
 
1093
                if (sp->size > 80) {
 
1094
                        strcat(tmp_send, "...\n");
 
1095
                }
 
1096
        }
 
1097
#endif  /* DEBUG */
 
1098
        if ((ret = ioctl(scgp->fd, CDROM_SEND_PACKET, &sg_cgc)) < 0)
 
1099
                sp->ux_errno = geterrno();
 
1100
 
 
1101
        if (ret < 0 && scgp->debug > 4) {
 
1102
                js_fprintf((FILE *) scgp->errfile,
 
1103
                        "ioctl(CDROM_SEND_PACKET) ret: %d\n", ret);
 
1104
        }
 
1105
        /*
 
1106
         * copy scsi data back
 
1107
         */
 
1108
        if (sp->flags & SCG_RECV_DATA && ((void *) sp->addr != (void *) sg_cgc.buffer)) {
 
1109
                memcpy(sp->addr, sg_cgc.buffer, (sp->size < sg_cgc.buflen) ? sp->size : sg_cgc.buflen);
 
1110
                if (sg_cgc.buflen > sp->size)
 
1111
                        sp->resid = sg_cgc.buflen - sp->size;
 
1112
        }
 
1113
        sp->error = SCG_NO_ERROR;
 
1114
#ifdef DEBUG
 
1115
        if (ret < 0) {
 
1116
                switch (sp->ux_errno) {
 
1117
                case ENOTTY:
 
1118
                        p = "ENOTTY";
 
1119
                        break;
 
1120
                case EINVAL:
 
1121
                        p = "EINVAL";
 
1122
                        break;
 
1123
                case ENXIO:
 
1124
                        p = "ENXIO";
 
1125
                        break;
 
1126
                case EACCES:
 
1127
                        p = "EACCES";
 
1128
                        break;
 
1129
                case EIO:
 
1130
                        p = "EIO";
 
1131
                        break;
 
1132
                case ENOMEDIUM:
 
1133
                        p = "ENOMEDIUM";
 
1134
                        break;
 
1135
                case EDRIVE_CANT_DO_THIS:
 
1136
                        p = "EDRIVE_CANT_DO_THIS";
 
1137
                        break;
 
1138
                default:
 
1139
                        p = "UNKNOW";
 
1140
                };
 
1141
                log(("%s", tmp_send));
 
1142
                log(("ERROR: returns %i errno %i(%s)\n", ret, sp->ux_errno, p));
 
1143
        }
 
1144
#endif  /* DEBUG */
 
1145
        if (ret < 0) {
 
1146
                /*
 
1147
                 * Check if SCSI command cound not be send at all.
 
1148
                 * Linux usually returns EINVAL for an unknoen ioctl.
 
1149
                 * In case somebody from the Linux kernel team learns that the
 
1150
                 * corect errno would be ENOTTY, we check for this errno too.
 
1151
                 */
 
1152
                if (sp->ux_errno == EINVAL) {
 
1153
                        /*
 
1154
                         * Try to work around broken Linux kernel design...
 
1155
                         * If SCSI Sense Key is 0x05 (Illegal request), Linux
 
1156
                         * returns a useless EINVAL making it close to
 
1157
                         * impossible distinct from "Illegal ioctl()" or
 
1158
                         * "Invalid parameter".
 
1159
                         */
 
1160
                        if ((((Uchar *)sg_cgc.sense)[0] != 0) ||
 
1161
                            (((Uchar *)sg_cgc.sense)[2] != 0))
 
1162
                                sp->ux_errno = EIO;
 
1163
 
 
1164
                } else if ((sp->ux_errno == ENOTTY || sp->ux_errno == EINVAL)) {
 
1165
                        /*
 
1166
                         * May be "Illegal ioctl()".
 
1167
                         */
 
1168
                        return (-1);
 
1169
                }
 
1170
                if (sp->ux_errno == ENXIO || sp->ux_errno == EACCES) {
 
1171
                        return (-1);
 
1172
                }
 
1173
        } else if (ret == 0) {
 
1174
#ifdef DEBUG
 
1175
                if (sg_cgc.data_direction == CGC_DATA_READ) {
 
1176
                        int     z;
 
1177
 
 
1178
                        sprintf(tmp_read, "data_read: %i bytes\n", sp->size);
 
1179
                        for (j = 0, z = 1; j < 80 && j < sp->size; j++, z++) {
 
1180
                                if (z > 16) {
 
1181
                                        z = 1;
 
1182
                                        strcat(tmp_read, "\n");
 
1183
                                }
 
1184
                                sprintf(tmp1, " %02X", (unsigned char) (sp->addr[j]));
 
1185
                                strcat(tmp_read, tmp1);
 
1186
                        }
 
1187
                        strcat(tmp_read, "\n");
 
1188
                        if (sp->size > 80) {
 
1189
                                strcat(tmp_read, "...\n");
 
1190
                        }
 
1191
                }
 
1192
#endif  /* DEBUG */
 
1193
        }
 
1194
        /*
 
1195
         * copy sense back
 
1196
         */
 
1197
        if (ret < 0 && sg_cgc.sense->error_code) {
 
1198
                sp->sense_count = sense_cgc.add_sense_len + 8;
 
1199
#ifdef DEBUG
 
1200
                sprintf(tmp_sense, "sense_data: length %i\n", sp->sense_count);
 
1201
                for (j = 0; j < sp->sense_count; j++) {
 
1202
                        sprintf(tmp1, " %02X", (((unsigned char *) (&sense_cgc))[j]));
 
1203
                        strcat(tmp_sense, tmp1);
 
1204
                }
 
1205
                log(("%s\n", tmp_sense));
 
1206
 
 
1207
                sprintf(tmp_sense, "sense_data: error code 0x%02X, sense key 0x%02X,"
 
1208
                        " additional length %i, ASC 0x%02X, ASCQ 0x%02X\n",
 
1209
                        sg_cgc.sense->error_code, sg_cgc.sense->sense_key,
 
1210
                        sg_cgc.sense->add_sense_len, sg_cgc.sense->asc,
 
1211
                        sg_cgc.sense->ascq);
 
1212
 
 
1213
                log(("%s\n", tmp_sense));
 
1214
#endif  /* DEBUG */
 
1215
                memcpy(sp->u_sense.cmd_sense, /* (caddr_t) */ &sense_cgc, SCG_MAX_SENSE);
 
1216
                sp->u_scb.cmd_scb[0] = ST_CHK_COND;
 
1217
 
 
1218
                switch (sg_cgc.sense->sense_key) {
 
1219
                case SC_UNIT_ATTENTION:
 
1220
                case SC_NOT_READY:
 
1221
                        sp->error = SCG_RETRYABLE;      /* may be BUS_BUSY */
 
1222
                        sp->u_scb.cmd_scb[0] |= ST_BUSY;
 
1223
                        break;
 
1224
                case SC_ILLEGAL_REQUEST:
 
1225
                        break;
 
1226
                default:
 
1227
                        break;
 
1228
                }
 
1229
        } else {
 
1230
                sp->u_scb.cmd_scb[0] = 0x00;
 
1231
        }
 
1232
 
 
1233
        sp->resid = 0;
 
1234
        return (0);
 
1235
}
 
1236
#endif  /* USE_ATA */