--- uae/src/scsidev.c 2018/04/24 16:48:42 1.1.1.2 +++ uae/src/scsidev.c 2018/04/24 16:54:50 1.1.1.4 @@ -23,19 +23,26 @@ #include "execlib.h" #include "native2amiga.h" #include "scsidev.h" -#include "scg/scsireg.h" -/* our configure does not distinguish that */ -#ifdef UAE_FILESYS_THREADS -#define UAE_SCSIDEV_THREADS +#include + +/* the new libscg should always have a scsi_close */ +#ifndef SCSI_CLOSE +#define SCSI_CLOSE #endif -#undef DEBUGME +typedef int BOOL; -/* follow the cdrecord style by including the correct code */ -#include "scsi-support.c" +#include "scg/scgcmd.h" +#include "scg/scsitransp.h" +#include "scg/scsireg.h" +/* our configure does not have a seperate UAE_SCSIDEV_THREADS */ +#if defined(UAE_FILESYS_THREADS) && !defined(SCSI_IS_NOT_THREAD_SAFE) +#define UAE_SCSIDEV_THREADS +#endif +#undef DEBUGME /****************** generic SCSI stuff stolen from cdrecord and scsitransp.c ***********/ static int scsierr(SCSI *scgp) @@ -48,38 +55,12 @@ static int scsierr(SCSI *scgp) return 0; } -int scsicmd(SCSI *scgp) -{ - int f; - int ret; - register struct scg_cmd *scmd = scgp->scmd; - - f = scsi_fileno(scgp, scgp->scsibus, scgp->target, scgp->lun); - scmd->kdebug = scgp->kdebug; - if (scmd->timeout == 0 || scmd->timeout < scgp->deftimeout) - scmd->timeout = scgp->deftimeout; - if (scgp->disre_disable) - scmd->flags &= ~SCG_DISRE_ENA; - if (scgp->noparity) - scmd->flags |= SCG_NOPARITY; - - gettimeofday(scgp->cmdstart, (struct timezone *)0); - errno = 0; - ret = scsi_send(scgp, f, scmd); - scsitimes(scgp); - if (ret < 0 && errno && !scgp->scmd->ux_errno) { - scgp->scmd->ux_errno = errno; - } - ret = scsierr(scgp); - return (ret); -} - static int inquiry (SCSI *scgp, void *bp, int cnt) { struct scg_cmd *scmd = scgp->scmd; - fillbytes(bp, cnt, '\0'); - fillbytes((caddr_t)scmd, sizeof(*scmd), '\0'); + memset(bp, cnt, '\0'); + memset((caddr_t)scmd, sizeof(*scmd), '\0'); scmd->addr = bp; scmd->size = cnt; scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA; @@ -107,35 +88,42 @@ static void print_product(struct scsi_in } } -static SCSI *openscsi (char *dev, int bus, int target, int lun) +/* get integer value from env or return default value, if unset */ +static int getenvint (const char *varname, int def) { - SCSI *scgp; - - if(!(scgp = calloc(1, sizeof (*scgp))) || - !(scgp->scmd = calloc(1, sizeof (*scgp->scmd))) || - !(scgp->cmdstart = malloc(sizeof (*scgp->cmdstart))) || - !(scgp->cmdstop = malloc(sizeof (*scgp->cmdstop)))) { + const char *val = getenv (varname); + return val ? atoi (val) : def; +} + +/* wrapper for the underlying combination of scsi_smalloc()/scsi_open() */ +static SCSI *openscsi (int scsibus, int target, int lun) +{ + SCSI *scgp = scsi_smalloc (); + if (!scgp) { return NULL; } - /* we don't really know the timeout - should better - disable it, if possible */ - scgp->deftimeout = 80 * 60; /* 80min */ - scgp->scsibus = bus; + + scgp->debug = getenvint ("UAE_SCSI_DEBUG", 0); + scgp->kdebug = getenvint ("UAE_SCSI_KDEBUG", 0); + scgp->silent = getenvint ("UAE_SCSI_SILENT", 1); + scgp->verbose = getenvint ("UAE_SCSI_VERBOSE", 0); + scgp->scsibus = scsibus; scgp->target = target; scgp->lun = lun; - return scsi_open (scgp, dev, bus, target, lun) >= 0 ? scgp : NULL; + + if (!scsi_open(scgp, NULL, scsibus, target, lun)) { + scsi_sfree (scgp); + return NULL; + } else { + return scgp; + } } -#ifdef SCSI_CLOSE -/* if there is no scsi_close, then we have to keep everything */ static void closescsi (SCSI *scgp) { scsi_close (scgp); - free (scgp->scmd); - free (scgp->cmdstart); - free (scgp->cmdstop); + scsi_sfree (scgp); } -#endif /********************* start of our own code ************************/ @@ -155,6 +143,7 @@ struct scsidevdata { (target % 8) SCSI *scgp; long max_dma; + int isatapi; #ifdef UAE_SCSIDEV_THREADS /* Threading stuff */ smp_comm_pipe requests; @@ -187,10 +176,15 @@ static struct scsidevdata *add_scsidev_d drives[num_drives].target = target; drives[num_drives].lun = lun; drives[num_drives].aunit = aunit; -#if !defined(UAE_SCSIDEV_THREADS) || !defined(SCSI_IS_THREAD_SAFE) +#if !defined(UAE_SCSIDEV_THREADS) drives[num_drives].scgp = scgp; - drives[num_drives].max_dma = scsi_maxdma (scgp); + drives[num_drives].max_dma = scsi_bufsize (scgp, 512 * 1024); #endif + /* check if this drive is an ATAPI drive */ + scgp->scsibus = bus; + scgp->target = target; + scgp->lun = lun; + drives[num_drives].isatapi = scsi_isatapi (scgp); return &drives[num_drives++]; } @@ -269,6 +263,48 @@ static uae_u32 scsidev_expunge (void) #define MODE_SENSE_10 0x5A #endif + +#ifdef DEBUG_CDR +/* please ignore this code - it can be used to debug raw CD-R writing... */ + +/* +** convert time in (BCD) min:sec:frame to block address +*/ +typedef signed char BYTE; +typedef unsigned char UBYTE; +typedef long LONG; +typedef BYTE BCD; +typedef BYTE WORD[2]; +#define BCD_DEC(x) (((x) >> 4) * 10 + ((x) & 0xF)) +static LONG TestNegativeTime(LONG block) +{ + /* block -151 == 99:59:74 + -150 == 100:00:00 = 00:00:00 */ + if (block > (97 * 60 * 75)) + { + /* must be a negative block */ + block -= 100 * 60 * 75; + } + return block; +} +static LONG BCDTime2Block(UBYTE min, UBYTE sec, UBYTE frame) +{ + return(TestNegativeTime((LONG)((BCD_DEC(min) * 60 + BCD_DEC(sec)) * 75 + BCD_DEC(frame) - 2 * 75))); +} +static LONG Time2Block(UBYTE min, UBYTE sec, UBYTE frame) +{ + return(TestNegativeTime((LONG)((min * 60 + sec) * 75 + frame - 2 * 75))); +} +static LONG BCDTime2Block_Pointer (UBYTE *p) +{ + return BCDTime2Block (p[0], p[1], p[2]); +} +static LONG Time2Block_Pointer (UBYTE *p) +{ + return Time2Block (p[0], p[1], p[2]); +} +#endif + static void scsidev_do_scsi (struct scsidevdata *sdd, uaecptr request) { SCSI *scgp = sdd->scgp; @@ -292,16 +328,11 @@ static void scsidev_do_scsi (struct scsi return; } - /* we are limited by the hosts DMA limits */ - if (scsi_len > sdd->max_dma) { - put_byte (request + 31, (uae_u8)-4); /* IOERR_BADLENGTH */ - return; - } - -#ifndef SCSI_IS_THREAD_SAFE +#ifdef SCSI_IS_NOT_THREAD_SAFE uae_sem_wait (&scgp_sem); #endif + scmd->timeout = 80 * 60; /* the Amiga does not tell us how long the timeout shall be, so make it _very_ long (specified in seconds) */ scmd->addr = bank_data->xlateaddr (scsi_data); scmd->size = scsi_len; scmd->flags = ((scsi_flags & 1) ? SCG_RECV_DATA : 0) | SCG_DISRE_ENA; @@ -314,15 +345,50 @@ static void scsidev_do_scsi (struct scsi scmd->sense_count = 0; *(uae_u8 *)&scmd->scb = 0; + #ifdef DEBUG_CDR + /* please ignore this code - it can be used to debug raw CD-R writing... */ + if (!(scsi_len % 2368)) { + /* Structure for generating bytes 2353...2368 if writing in ultra raw mode */ + typedef struct QDATAtag { + BYTE ControlAdr; + BCD Tno; + BCD Point; + BCD Min; + BCD Sec; + BCD Frame; + BYTE Zero; + BCD PMin; + BCD PSec; + BCD PFrame; + WORD Crc; + BYTE Reserved[3]; + BYTE PChannel; + } QDATA; + + int i = scsi_len / 2368; + QDATA *data = (QDATA *)&((unsigned char *)scmd->addr)[2352]; + for (; i > 0; i--, data = (QDATA *)&((unsigned char *)data)[2368]) { + printf ("$%02x: $%02x $%02x | $%02x:$%02x:$%02x = %6ld | $%02x | $%02x:$%02x:$%02x = %6ld\n", + (int)data->ControlAdr, (int)*(UBYTE *)&data->Tno, (int)*(UBYTE *)&data->Point, + (int)*(UBYTE *)&data->Min, (int)*(UBYTE *)&data->Sec, (int)*(UBYTE *)&data->Frame, + BCDTime2Block_Pointer (&data->Min) + 150, + *(UBYTE *)&data->Zero, + *(UBYTE *)&data->PMin, *(UBYTE *)&data->PSec, *(UBYTE *)&data->PFrame, + BCDTime2Block_Pointer (&data->PMin)); + } + fflush (stdout); + } + #endif + scgp->scsibus = sdd->bus; scgp->target = sdd->target; scgp->lun = sdd->lun; - scsicmd (scgp); + scgp->cmdname = "???"; + scgp->curcmdname = "???"; - /* replace MODE_SELECT/SENSE_6 if they are not supported */ - if (scmd->scb.chk && - ((struct scsi_ext_sense *)&scmd->sense)->key == 0x5 && - ((struct scsi_ext_sense *)&scmd->sense)->sense_code == 0x20 && /* INVALID_COMMAND */ + /* replace MODE_SELECT/SENSE_6 if we access a ATAPI drive, + otherwise send it now */ + if (sdd->isatapi && (scmd->cdb.g0_cdb.cmd == MODE_SELECT_6 || scmd->cdb.g0_cdb.cmd == MODE_SENSE_6)) { uae_u8 buffer[256 + 2], *data = scmd->addr, *tmp; @@ -407,6 +473,8 @@ static void scsidev_do_scsi (struct scsi memcpy (&data[len], tmp, req_len - (tmp - buffer)); } } + } else { + scsicmd (scgp); } put_word (acmd + 18, scmd->error == SCG_FATAL ? 0 : scsi_cmd_len); /* fake scsi_CmdActual */ @@ -431,8 +499,15 @@ static void scsidev_do_scsi (struct scsi if (scmd->error != SCG_NO_ERROR || scmd->ux_errno != 0) { - put_byte (request + 31, 20); /* io_Error, but not specified */ - put_long (acmd + 8, 0); /* scsi_Actual */ + /* we might have been limited by the hosts DMA limits, + which is usually indicated by ENOMEM */ + if (scsi_len > (unsigned int)sdd->max_dma && + scmd->ux_errno == ENOMEM) { + put_byte (request + 31, (uae_u8)-4); /* IOERR_BADLENGTH */ + } else { + put_byte (request + 31, 20); /* io_Error, but not specified */ + put_long (acmd + 8, 0); /* scsi_Actual */ + } } else { put_byte (request + 31, 0); put_long (acmd + 8, scsi_len - scmd->resid); /* scsi_Actual */ @@ -440,7 +515,7 @@ static void scsidev_do_scsi (struct scsi } put_word (acmd + 28, sactual); -#ifndef SCSI_IS_THREAD_SAFE +#ifdef SCSI_IS_NOT_THREAD_SAFE uae_sem_post (&scgp_sem); #endif } @@ -509,8 +584,8 @@ static void *scsidev_penguin (void *sddv printf ("scsidev_penguin: sdd = 0x%x ready\n", sdd); #endif /* init SCSI */ - if (!(sdd->scgp = openscsi (NULL, sdd->bus, sdd->target, sdd->lun)) || - (sdd->max_dma = scsi_maxdma (sdd->scgp)) <= 0) { + if (!(sdd->scgp = openscsi (sdd->bus, sdd->target, sdd->lun)) || + (sdd->max_dma = scsi_bufsize (sdd->scgp, 512 * 1024)) <= 0) { sdd->thread_running = 0; uae_sem_post (&sdd->sync_sem); return 0; @@ -561,7 +636,7 @@ static uae_u32 scsidev_init (void) } /* init global SCSI */ - if (!(scgp = openscsi (NULL, -1, -1, -1))) { + if (!(scgp = openscsi (-1, -1, -1))) { return 0; } @@ -581,11 +656,13 @@ static uae_u32 scsidev_init (void) for (scgp->lun=0; scgp->lun < 8; scgp->lun++) { if (!inquiry (scgp, &inq, sizeof(inq))) { int aunit = BTL2UNIT(scgp->scsibus, scgp->target, scgp->lun); + struct scsidevdata *sdd; write_log (" %2.01d,%d (= %3.d): ", scgp->target, scgp->lun, aunit); print_product (&inq); + sdd = add_scsidev_data (scgp->scsibus, scgp->target, scgp->lun, aunit); + write_log (!sdd ? " - init failed ???" : sdd->isatapi ? " - ATAPI" : " - SCSI"); write_log ("\n"); - add_scsidev_data (scgp->scsibus, scgp->target, scgp->lun, aunit); } } } @@ -715,8 +792,11 @@ void scsidev_reset (void) int i; for (i = 0; i < num_drives; i++) { - write_comm_pipe (&drives[i].requests, 0, 1); - uae_sem_wait (&drives[i].sync); + if (!drives[i].thread_running) { + continue; + } + write_comm_pipe_int (&drives[i].requests, 0, 1); + uae_sem_wait (&drives[i].sync_sem); } num_drives = 0; }