1
/* @(#)scsi-os2.c 1.25 04/01/15 Copyright 1998 J. Schilling, C. Wohlgemuth */
3
static char __sccsid[] =
4
"@(#)scsi-os2.c 1.25 04/01/15 Copyright 1998 J. Schilling, C. Wohlgemuth";
7
* Interface for the OS/2 ASPI-Router ASPIROUT.SYS ((c) D. Dorau).
8
* This additional driver is a prerequisite for using cdrecord.
9
* Get it from HOBBES or LEO.
11
* Warning: you may change this source, but if you do that
12
* you need to change the _scg_version and _scg_auth* string below.
13
* You may not return "schily" for an SCG_AUTHOR request anymore.
14
* Choose your name instead of "schily" and make clear that the version
15
* string is related to a modified source.
17
* XXX it currently uses static SRB and for this reason is not reentrant
19
* Copyright (c) 1998 J. Schilling
20
* Copyright (c) 1998 C. Wohlgemuth for this interface.
23
* This program is free software; you can redistribute it and/or modify
24
* it under the terms of the GNU General Public License as published by
25
* the Free Software Foundation; either version 2, or (at your option)
28
* This program is distributed in the hope that it will be useful,
29
* but WITHOUT ANY WARRANTY; without even the implied warranty of
30
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
* GNU General Public License for more details.
33
* You should have received a copy of the GNU General Public License along with
34
* this program; see the file COPYING. If not, write to the Free Software
35
* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43
#include "scg/srb_os2.h"
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.
52
LOCAL char _scg_trans_version[] = "scsi-os2.c-1.25"; /* The version for this transport*/
54
#define FILE_OPEN 0x0001
55
#define OPEN_SHARE_DENYREADWRITE 0x0010
56
#define OPEN_ACCESS_READWRITE 0x0002
57
#define DC_SEM_SHARED 0x01
58
#define OBJ_TILE 0x0040
59
#define PAG_READ 0x0001
60
#define PAG_WRITE 0x0002
61
#define PAG_COMMIT 0x0010
63
typedef unsigned long LHANDLE;
64
typedef unsigned long ULONG;
65
typedef unsigned char *PSZ;
66
typedef unsigned short USHORT;
67
typedef unsigned char UCHAR;
69
typedef LHANDLE HFILE;
72
#define MAX_SCG 16 /* Max # of SCSI controllers */
79
#define scglocal(p) ((struct scg_local *)((p)->local))
81
#define MAX_DMA_OS2 (63*1024) /* ASPI-Router allows up to 64k */
83
LOCAL void *buffer = NULL;
84
LOCAL HFILE driver_handle = 0;
85
LOCAL HEV postSema = 0;
87
LOCAL BOOL open_driver __PR((SCSI *scgp));
88
LOCAL BOOL close_driver __PR((void));
89
LOCAL ULONG wait_post __PR((ULONG ulTimeOut));
90
LOCAL BOOL init_buffer __PR((void* mem));
91
LOCAL void exit_func __PR((void));
92
LOCAL void set_error __PR((SRB *srb, struct scg_cmd *sp));
99
js_fprintf(stderr, "Cannot close OS/2-ASPI-Router!\n");
103
* Return version information for the low level SCSI transport code.
104
* This has been introduced to make it easier to trace down problems
108
scgo_version(scgp, what)
112
if (scgp != (SCSI *)0) {
116
return (_scg_trans_version);
118
* If you changed this source, you are not allowed to
119
* return "schily" for the SCG_AUTHOR request.
122
return (_scg_auth_schily);
135
__scg_help(f, "ASPI", "Generic transport independent SCSI",
136
"", "bus,target,lun", "1,2,0", TRUE, FALSE);
141
scgo_open(scgp, device)
145
int busno = scg_scsibus(scgp);
146
int tgt = scg_target(scgp);
147
int tlun = scg_lun(scgp);
149
if (busno >= MAX_SCG || tgt >= MAX_TGT || tlun >= MAX_LUN) {
152
js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
153
"Illegal value for busno, target or lun '%d,%d,%d'",
158
if ((device != NULL && *device != '\0') || (busno == -2 && tgt == -2)) {
161
js_snprintf(scgp->errstr, SCSI_ERRSTR_SIZE,
162
"Open by 'devname' not supported on this OS");
166
if (scgp->local == NULL) {
167
scgp->local = malloc(sizeof (struct scg_local));
168
if (scgp->local == NULL)
172
if (!open_driver(scgp)) /* Try to open ASPI-Router */
174
atexit(exit_func); /* Install Exit Function which closes the ASPI-Router */
191
scgo_maxdma(scgp, amt)
195
long maxdma = MAX_DMA_OS2;
200
scgo_getbuf(scgp, amt)
207
js_fprintf((FILE *)scgp->errfile, "scgo_getbuf: %ld bytes\n", amt);
209
rc = DosAllocMem(&buffer, amt, OBJ_TILE | PAG_READ | PAG_WRITE | PAG_COMMIT);
212
js_fprintf((FILE *)scgp->errfile, "Cannot allocate buffer.\n");
215
scgp->bufbase = buffer;
218
js_fprintf((FILE *)scgp->errfile, "Buffer allocated at: 0x%x\n", scgp->bufbase);
222
if (init_buffer(scgp->bufbase))
223
return (scgp->bufbase);
225
js_fprintf((FILE *)scgp->errfile, "Cannot lock memory buffer.\n");
226
return ((void *)0); /* Error */
233
if (scgp->bufbase && DosFreeMem(scgp->bufbase)) {
234
js_fprintf((FILE *)scgp->errfile,
235
"Cannot free buffer memory for ASPI-Router!\n"); /* Free our memory buffer if not already done */
237
if (buffer == scgp->bufbase)
239
scgp->bufbase = NULL;
243
scgo_havebus(scgp, busno)
250
if (busno < 0 || busno >= MAX_SCG)
257
scgo_fileno(scgp, busno, tgt, tlun)
263
if (busno < 0 || busno >= MAX_SCG ||
264
tgt < 0 || tgt >= MAX_TGT ||
265
tlun < 0 || tlun >= MAX_LUN)
276
scgo_initiator_id(scgp)
291
scgo_reset(scgp, what)
295
ULONG rc; /* return value */
299
static SRB SRBlock; /* XXX makes it non reentrant */
301
if (what == SCG_RESET_NOP)
303
if (what != SCG_RESET_BUS) {
308
* XXX Does this reset TGT or BUS ???
310
SRBlock.cmd = SRB_Reset; /* reset device */
311
SRBlock.ha_num = scg_scsibus(scgp); /* host adapter number */
312
SRBlock.flags = SRB_Post; /* posting enabled */
313
SRBlock.u.res.target = scg_target(scgp); /* target id */
314
SRBlock.u.res.lun = scg_lun(scgp); /* target LUN */
316
rc = DosDevIOCtl(driver_handle, 0x92, 0x02, (void*) &SRBlock, sizeof (SRB), &cbParam,
317
(void*) &SRBlock, sizeof (SRB), &cbreturn);
319
js_fprintf((FILE *)scgp->errfile,
320
"DosDevIOCtl() failed in resetDevice.\n");
321
return (1); /* DosDevIOCtl failed */
323
success = wait_post(40000); /** wait for SRB being processed */
327
if (SRBlock.status != SRB_Done)
330
js_fprintf((FILE *)scgp->errfile,
331
"resetDevice of host: %d target: %d lun: %d successful.\n", scg_scsibus(scgp), scg_target(scgp), scg_lun(scgp));
332
js_fprintf((FILE *)scgp->errfile,
333
"SRBlock.ha_status: 0x%x, SRBlock.target_status: 0x%x, SRBlock.satus: 0x%x\n",
334
SRBlock.u.cmd.ha_status, SRBlock.u.cmd.target_status, SRBlock.status);
347
switch (srb->status) {
349
case SRB_InvalidCmd: /* 0x80 Invalid SCSI request */
350
case SRB_InvalidHA: /* 0x81 Invalid host adapter number */
351
case SRB_BadDevice: /* 0x82 SCSI device not installed */
352
sp->error = SCG_FATAL;
353
sp->ux_errno = EINVAL; /* Should we ever return != EIO */
358
case SRB_Busy: /* 0x00 SCSI request in progress */
359
case SRB_Aborted: /* 0x02 SCSI aborted by host */
360
case SRB_BadAbort: /* 0x03 Unable to abort SCSI request */
361
case SRB_Error: /* 0x04 SCSI request completed with error */
363
sp->error = SCG_RETRYABLE;
373
struct scg_cmd *sp = scgp->scmd;
374
ULONG rc; /* return value */
375
static SRB SRBlock; /* XXX makes it non reentrant */
380
if (scgp->fd < 0) { /* Set in scgo_open() */
381
sp->error = SCG_FATAL;
385
if (sp->cdb_len > sizeof (SRBlock.u.cmd.cdb_st)) { /* commandsize too big */
386
sp->error = SCG_FATAL;
387
sp->ux_errno = EINVAL;
388
js_fprintf((FILE *)scgp->errfile,
389
"sp->cdb_len > SRBlock.u.cmd.cdb_st. Fatal error in scgo_send, exiting...\n");
393
/* clear command block */
394
fillbytes((caddr_t)&SRBlock.u.cmd.cdb_st, sizeof (SRBlock.u.cmd.cdb_st), '\0');
395
/* copy cdrecord command into SRB */
396
movebytes(&sp->cdb, &SRBlock.u.cmd.cdb_st, sp->cdb_len);
398
/* Build SRB command block */
399
SRBlock.cmd = SRB_Command;
400
SRBlock.ha_num = scg_scsibus(scgp); /* host adapter number */
402
SRBlock.flags = SRB_Post; /* flags */
404
SRBlock.u.cmd.target = scg_target(scgp); /* Target SCSI ID */
405
SRBlock.u.cmd.lun = scg_lun(scgp); /* Target SCSI LUN */
406
SRBlock.u.cmd.data_len = sp->size; /* # of bytes transferred */
407
SRBlock.u.cmd.data_ptr = 0; /* pointer to data buffer */
408
SRBlock.u.cmd.sense_len = sp->sense_len; /* length of sense buffer */
410
SRBlock.u.cmd.link_ptr = 0; /* pointer to next SRB */
411
SRBlock.u.cmd.cdb_len = sp->cdb_len; /* SCSI command length */
413
/* Specify direction */
414
if (sp->flags & SCG_RECV_DATA) {
415
SRBlock.flags |= SRB_Read;
418
SRBlock.flags |= SRB_Write;
419
if (scgp->bufbase != sp->addr) { /* Copy only if data not in ASPI-Mem */
420
movebytes(sp->addr, scgp->bufbase, sp->size);
423
SRBlock.flags |= SRB_NoTransfer;
426
sp->error = SCG_NO_ERROR;
428
sp->u_scb.cmd_scb[0] = 0;
431
/* execute SCSI command */
432
rc = DosDevIOCtl(driver_handle, 0x92, 0x02,
433
(void*) &SRBlock, sizeof (SRB), &cbParam,
434
(void*) &SRBlock, sizeof (SRB), &cbreturn);
436
if (rc) { /* An error occured */
437
js_fprintf((FILE *)scgp->errfile,
438
"DosDevIOCtl() in sendCommand failed.\n");
439
sp->error = SCG_FATAL;
440
sp->ux_errno = EIO; /* Sp�ter vielleicht errno einsetzen */
443
/* Wait until the command is processed */
444
rc = wait_post(sp->timeout*1000);
445
if (rc) { /* An error occured */
448
sp->error = SCG_TIMEOUT;
450
js_fprintf((FILE *)scgp->errfile,
451
"Timeout during SCSI-Command.\n");
454
sp->error = SCG_FATAL;
456
js_fprintf((FILE *)scgp->errfile,
457
"Fatal Error during DosWaitEventSem().\n");
461
/* The command is processed */
462
if (SRBlock.status == SRB_Done) { /* succesful completion */
464
js_fprintf((FILE *)scgp->errfile,
465
"Command successful finished. SRBlock.status=0x%x\n\n", SRBlock.status);
469
if (sp->flags & SCG_RECV_DATA) { /* We read data */
470
if (sp->addr && sp->size) {
471
if (scgp->bufbase != sp->addr) /* Copy only if data not in ASPI-Mem */
472
movebytes(scgp->bufbase, sp->addr, SRBlock.u.cmd.data_len);
473
ptr = (UCHAR*)sp->addr;
474
sp->resid = sp->size - SRBlock.u.cmd.data_len; /*nicht �bertragene bytes. Korrekt berechnet???*/
476
} /* end of if (sp->flags & SCG_RECV_DATA) */
477
if (SRBlock.u.cmd.target_status == SRB_CheckStatus) { /* Sense data valid */
478
sp->sense_count = (int)SRBlock.u.cmd.sense_len;
479
if (sp->sense_count > sp->sense_len)
480
sp->sense_count = sp->sense_len;
482
ptr = (UCHAR*)&SRBlock.u.cmd.cdb_st;
483
ptr += SRBlock.u.cmd.cdb_len;
485
fillbytes(&sp->u_sense.Sense, sizeof (sp->u_sense.Sense), '\0');
486
movebytes(ptr, &sp->u_sense.Sense, sp->sense_len);
488
sp->u_scb.cmd_scb[0] = SRBlock.u.cmd.target_status;
489
sp->ux_errno = EIO; /* Sp�ter differenzieren? */
493
/* SCSI-Error occured */
494
set_error(&SRBlock, sp);
496
if (SRBlock.u.cmd.target_status == SRB_CheckStatus) { /* Sense data valid */
497
sp->sense_count = (int)SRBlock.u.cmd.sense_len;
498
if (sp->sense_count > sp->sense_len)
499
sp->sense_count = sp->sense_len;
501
ptr = (UCHAR*)&SRBlock.u.cmd.cdb_st;
502
ptr += SRBlock.u.cmd.cdb_len;
504
fillbytes(&sp->u_sense.Sense, sizeof (sp->u_sense.Sense), '\0');
505
movebytes(ptr, &sp->u_sense.Sense, sp->sense_len);
507
sp->u_scb.cmd_scb[0] = SRBlock.u.cmd.target_status;
509
if (sp->flags & SCG_RECV_DATA) {
510
if (sp->addr && sp->size) {
511
if (scgp->bufbase != sp->addr) /* Copy only if data not in ASPI-Mem */
512
movebytes(scgp->bufbase, sp->addr, SRBlock.u.cmd.data_len);
516
sp->resid = SRBlock.u.cmd.data_len; /* XXXXX Got no Data ????? */
518
sp->resid = sp->size - SRBlock.u.cmd.data_len;
524
/***************************************************************************
526
* BOOL open_driver() *
528
* Opens the ASPI Router device driver and sets device_handle. *
531
* FALSE - Unsuccessful opening of device driver *
533
* Preconditions: ASPI Router driver has be loaded *
535
***************************************************************************/
540
ULONG rc; /* return value */
541
ULONG ActionTaken; /* return value */
542
USHORT openSemaReturn; /* return value */
546
if (driver_handle) /* ASPI-Router already opened */
549
rc = DosOpen((PSZ) "aspirou$", /* open driver*/
555
OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
558
js_fprintf((FILE *)scgp->errfile,
559
"Cannot open ASPI-Router!\n");
561
return (FALSE); /* opening failed -> return false*/
565
if (DosCreateEventSem(NULL, &postSema, /* create event semaphore */
567
DosClose(driver_handle);
568
js_fprintf((FILE *)scgp->errfile,
569
"Cannot create event semaphore!\n");
573
rc = DosDevIOCtl(driver_handle, 0x92, 0x03, /* pass semaphore handle */
574
(void*) &postSema, sizeof (HEV), /* to driver */
575
&cbParam, (void*) &openSemaReturn,
576
sizeof (USHORT), &cbreturn);
578
if (rc||openSemaReturn) { /* Error */
579
DosCloseEventSem(postSema);
580
DosClose(driver_handle);
586
/***************************************************************************
588
* BOOL close_driver() *
590
* Closes the device driver *
593
* FALSE - Unsuccessful closing of device driver *
595
* Preconditions: ASPI Router driver has be opened with open_driver *
597
***************************************************************************/
601
ULONG rc; /* return value */
604
rc = DosClose(driver_handle);
606
return (FALSE); /* closing failed -> return false */
608
if (DosCloseEventSem(postSema))
609
js_fprintf(stderr, "Cannot close event semaphore!\n");
610
if (buffer && DosFreeMem(buffer)) {
612
"Cannot free buffer memory for ASPI-Router!\n"); /* Free our memory buffer if not already done */
620
wait_post(ULONG ulTimeOut)
623
ULONG rc; /* return value */
625
/* rc = DosWaitEventSem(postSema, -1);*/ /* wait forever*/
626
rc = DosWaitEventSem(postSema, ulTimeOut);
627
DosResetEventSem(postSema, &count);
635
ULONG rc; /* return value */
636
USHORT lockSegmentReturn; /* return value */
640
rc = DosDevIOCtl(driver_handle, 0x92, 0x04, /* pass buffers pointer */
641
(void*) mem, sizeof (void*), /* to driver */
642
&cbParam, (void*) &lockSegmentReturn,
643
sizeof (USHORT), &cbreturn);
645
return (FALSE); /* DosDevIOCtl failed */
646
if (lockSegmentReturn)
647
return (FALSE); /* Driver could not lock segment */
650
#define sense u_sense.Sense