Annotation of uae/src/scsidev.c, revision 1.1.1.10

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * a SCSI device
                      5:   *
                      6:   * Copyright 1995 Bernd Schmidt
                      7:   * Copyright 1999 Patrick Ohly
                      8:   */
                      9: 
                     10: #include "sysconfig.h"
                     11: #include "sysdeps.h"
                     12: 
1.1.1.6   root       13: #include "threaddep/thread.h"
1.1       root       14: #include "options.h"
                     15: #include "memory.h"
                     16: #include "custom.h"
                     17: #include "newcpu.h"
                     18: #include "disk.h"
                     19: #include "autoconf.h"
                     20: #include "filesys.h"
                     21: #include "execlib.h"
                     22: #include "native2amiga.h"
                     23: #include "scsidev.h"
                     24: 
1.1.1.4   root       25: #include <stdio.h>
                     26: 
1.1.1.3   root       27: /* the new libscg should always have a scsi_close */
                     28: #ifndef SCSI_CLOSE
                     29: #define SCSI_CLOSE
1.1       root       30: #endif
                     31: 
1.1.1.3   root       32: typedef int BOOL;
1.1       root       33: 
1.1.1.3   root       34: #include "scg/scgcmd.h"
                     35: #include "scg/scsitransp.h"
                     36: #include "scg/scsireg.h"
1.1       root       37: 
1.1.1.3   root       38: /* our configure does not have a seperate UAE_SCSIDEV_THREADS */
                     39: #if defined(UAE_FILESYS_THREADS) && !defined(SCSI_IS_NOT_THREAD_SAFE)
                     40: #define UAE_SCSIDEV_THREADS
                     41: #endif
1.1       root       42: 
1.1.1.3   root       43: #undef DEBUGME
1.1       root       44: 
                     45: /****************** generic SCSI stuff stolen from cdrecord and scsitransp.c ***********/
                     46: static int scsierr(SCSI *scgp)
                     47: {
                     48:     register struct scg_cmd *cp = scgp->scmd;
                     49: 
                     50:     if(cp->error != SCG_NO_ERROR ||
                     51:        cp->ux_errno != 0 || *(u_char *)&cp->scb != 0)
1.1.1.7   root       52:        return -1;
1.1       root       53:     return 0;
                     54: }
                     55: 
                     56: static int inquiry (SCSI *scgp, void *bp, int cnt)
                     57: {
                     58:     struct scg_cmd *scmd = scgp->scmd;
                     59: 
1.1.1.3   root       60:     memset(bp, cnt, '\0');
                     61:     memset((caddr_t)scmd, sizeof(*scmd), '\0');
1.1       root       62:     scmd->addr = bp;
                     63:     scmd->size = cnt;
                     64:     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
                     65:     scmd->cdb_len = SC_G0_CDBLEN;
                     66:     scmd->sense_len = CCS_SENSE_LEN;
                     67:     scmd->target = scgp->target;
                     68:     scmd->cdb.g0_cdb.cmd = SC_INQUIRY;
                     69:     scmd->cdb.g0_cdb.lun = scgp->lun;
                     70:     scmd->cdb.g0_cdb.count = cnt;
1.1.1.8   root       71: 
1.1       root       72:     scgp->cmdname = "inquiry";
                     73: 
                     74:     if (scsicmd(scgp) < 0)
1.1.1.7   root       75:        return (-1);
1.1       root       76:     return (0);
                     77: }
                     78: 
                     79: static void print_product(struct scsi_inquiry *ip)
                     80: {
                     81:     write_log ("'%.8s' ", ip->info);
                     82:     write_log ("'%.16s' ", ip->ident);
                     83:     write_log ("'%.4s' ", ip->revision);
                     84:     if (ip->add_len < 31) {
1.1.1.7   root       85:        write_log ("NON CCS ");
1.1       root       86:     }
                     87: }
                     88: 
1.1.1.3   root       89: /* get integer value from env or return default value, if unset */
                     90: static int getenvint (const char *varname, int def)
1.1       root       91: {
1.1.1.3   root       92:     const char *val = getenv (varname);
                     93:     return val ? atoi (val) : def;
                     94: }
                     95: 
                     96: /* wrapper for the underlying combination of scsi_smalloc()/scsi_open() */
                     97: static SCSI *openscsi (int scsibus, int target, int lun)
                     98: {
                     99:     SCSI *scgp = scsi_smalloc ();
                    100:     if (!scgp) {
1.1.1.7   root      101:        return NULL;
1.1       root      102:     }
1.1.1.3   root      103: 
                    104:     scgp->debug = getenvint ("UAE_SCSI_DEBUG", 0);
                    105:     scgp->kdebug = getenvint ("UAE_SCSI_KDEBUG", 0);
                    106:     scgp->silent = getenvint ("UAE_SCSI_SILENT", 1);
1.1.1.4   root      107:         scgp->verbose = getenvint ("UAE_SCSI_VERBOSE", 0);
1.1.1.3   root      108:     scgp->scsibus = scsibus;
1.1       root      109:     scgp->target = target;
                    110:     scgp->lun = lun;
1.1.1.3   root      111: 
                    112:     if (!scsi_open(scgp, NULL, scsibus, target, lun)) {
1.1.1.7   root      113:        scsi_sfree (scgp);
                    114:        return NULL;
1.1.1.3   root      115:     } else {
1.1.1.7   root      116:        return scgp;
1.1.1.8   root      117:     }
1.1       root      118: }
                    119: 
                    120: static void closescsi (SCSI *scgp)
                    121: {
                    122:     scsi_close (scgp);
1.1.1.3   root      123:     scsi_sfree (scgp);
1.1       root      124: }
                    125: 
                    126: /********************* start of our own code ************************/
                    127: 
                    128: static int opencount = 0;
                    129: static SCSI *scgp; /* SCSI handle which is to be used by the main thread */
                    130: uae_sem_t scgp_sem;
                    131: 
                    132: 
                    133: /****************** unit handling *******************/
                    134: 
                    135: struct scsidevdata {
                    136:     int bus, target, lun; /* the real values */
                    137:     int aunit;            /* Amiga unit number, by default calculated like that: */
                    138: #define BTL2UNIT(bus, target, lun) \
                    139:       (2 * (bus) + (target) / 8) * 100 + \
                    140:       (lun) * 10 + \
                    141:       (target % 8)
                    142:     SCSI *scgp;
                    143:     long max_dma;
1.1.1.3   root      144:     int isatapi;
1.1       root      145: #ifdef UAE_SCSIDEV_THREADS
                    146:     /* Threading stuff */
                    147:     smp_comm_pipe requests;
1.1.1.6   root      148:     uae_thread_id tid;
1.1       root      149:     int thread_running;
                    150:     uae_sem_t sync_sem;
                    151: #endif
                    152: };
                    153: 
                    154: #define MAX_DRIVES 16
                    155: static struct scsidevdata drives[MAX_DRIVES];
                    156: static int num_drives;
                    157: static struct scsidevdata *get_scsidev_data (int unit)
                    158: {
                    159:     int i;
                    160: 
                    161:     for (i = 0; i < num_drives; i++) {
1.1.1.7   root      162:        if (unit == drives[i].aunit) {
                    163:            return &drives[i];
                    164:        }
1.1       root      165:     }
                    166:     return NULL;
                    167: }
                    168: 
                    169: static struct scsidevdata *add_scsidev_data (int bus, int target, int lun, int aunit)
                    170: {
                    171:     if (num_drives + 1 < MAX_DRIVES) {
1.1.1.7   root      172:        memset(&drives[num_drives], 0, sizeof(drives[num_drives]));
                    173:        drives[num_drives].bus = bus;
                    174:        drives[num_drives].target = target;
                    175:        drives[num_drives].lun = lun;
                    176:        drives[num_drives].aunit = aunit;
1.1.1.3   root      177: #if !defined(UAE_SCSIDEV_THREADS)
1.1.1.7   root      178:        drives[num_drives].scgp = scgp;
                    179:        drives[num_drives].max_dma = scsi_bufsize (scgp, 512 * 1024);
1.1       root      180: #endif
1.1.1.7   root      181:        /* check if this drive is an ATAPI drive */
                    182:        scgp->scsibus = bus;
                    183:        scgp->target = target;
                    184:        scgp->lun = lun;
                    185:        drives[num_drives].isatapi = scsi_isatapi (scgp);
                    186:        return &drives[num_drives++];
1.1       root      187:     }
                    188: 
                    189:     return NULL;
                    190: }
                    191: 
1.1.1.6   root      192: static void *scsidev_thread(void *);
1.1       root      193: static int start_thread (struct scsidevdata *sdd)
                    194: {
                    195: #ifdef UAE_SCSIDEV_THREADS
                    196:     if (sdd->thread_running)
1.1.1.7   root      197:        return 1;
1.1       root      198:     init_comm_pipe (&sdd->requests, 10, 1);
                    199:     uae_sem_init (&sdd->sync_sem, 0, 0);
1.1.1.6   root      200:     uae_start_thread (scsidev_thread, sdd, &sdd->tid);
1.1       root      201:     uae_sem_wait (&sdd->sync_sem);
                    202:     return sdd->thread_running;
                    203: #else
                    204:     return 1;
                    205: #endif
                    206: }
1.1.1.8   root      207: 
1.1       root      208: /************* Exec device functions ****************/
                    209: 
                    210: 
                    211: static uae_u32 scsidev_open (void)
                    212: {
1.1.1.10! root      213:     uaecptr tmp1 = m68k_areg (regs, 1); /* IOReq */
1.1       root      214:     uae_u32 unit = m68k_dreg (regs, 0);
                    215:     struct scsidevdata *sdd;
                    216: 
                    217: #ifdef DEBUGME
                    218:     printf("scsidev_open(0x%x, %d)\n", tmp1, unit);
                    219: #endif
                    220: 
                    221:     /* Check unit number */
                    222:     if ((sdd = get_scsidev_data (unit)) &&
1.1.1.7   root      223:        start_thread (sdd)) {
1.1       root      224:        opencount++;
1.1.1.10! root      225:        put_word (m68k_areg (regs, 6)+32, get_word (m68k_areg (regs, 6)+32) + 1);
1.1       root      226:        put_long (tmp1 + 24, unit); /* io_Unit */
                    227:        put_byte (tmp1 + 31, 0); /* io_Error */
                    228:        put_byte (tmp1 + 8, 7); /* ln_type = NT_REPLYMSG */
                    229:        return 0;
                    230:     }
                    231: 
                    232:     put_long (tmp1 + 20, (uae_u32)-1);
                    233:     put_byte (tmp1 + 31, (uae_u8)-1);
                    234:     return (uae_u32)-1;
                    235: }
                    236: 
                    237: static uae_u32 scsidev_close (void)
                    238: {
                    239: #ifdef DEBUGME
                    240:     printf("scsidev_close()\n");
                    241: #endif
                    242: 
                    243:     opencount--;
1.1.1.10! root      244:     put_word (m68k_areg (regs, 6) + 32, get_word (m68k_areg (regs, 6) + 32) - 1);
1.1       root      245: 
                    246:     return 0;
                    247: }
                    248: 
                    249: static uae_u32 scsidev_expunge (void)
                    250: {
                    251:  #ifdef DEBUGME
                    252:     printf("scsidev_expunge()\n");
                    253: #endif
                    254:     return 0; /* Simply ignore this one... */
                    255: }
                    256: 
                    257: #define MODE_SELECT_6  0x15
                    258: #define MODE_SENSE_6   0x1A
                    259: #ifndef MODE_SENSE_10
                    260: #define MODE_SELECT_10 0x55
                    261: #define MODE_SENSE_10  0x5A
                    262: #endif
                    263: 
1.1.1.4   root      264: 
                    265: #ifdef DEBUG_CDR
                    266: /* please ignore this code - it can be used to debug raw CD-R writing... */
                    267: 
                    268: /*
                    269: ** convert time in (BCD) min:sec:frame to block address
                    270: */
                    271: typedef signed char BYTE;
                    272: typedef unsigned char UBYTE;
                    273: typedef long LONG;
                    274: typedef BYTE BCD;
                    275: typedef BYTE WORD[2];
                    276: #define BCD_DEC(x) (((x) >> 4) * 10 + ((x) & 0xF))
                    277: static LONG TestNegativeTime(LONG block)
                    278: {
                    279:     /* block -151 == 99:59:74
                    280:        -150 == 100:00:00 = 00:00:00 */
                    281:     if (block > (97 * 60 * 75))
                    282:     {
1.1.1.7   root      283:        /* must be a negative block */
                    284:        block -= 100 * 60 * 75;
1.1.1.4   root      285:     }
                    286:     return block;
                    287: }
                    288: static LONG BCDTime2Block(UBYTE min, UBYTE sec, UBYTE frame)
                    289: {
                    290:     return(TestNegativeTime((LONG)((BCD_DEC(min) * 60 + BCD_DEC(sec)) * 75 + BCD_DEC(frame) - 2 * 75)));
                    291: }
                    292: static LONG Time2Block(UBYTE min, UBYTE sec, UBYTE frame)
                    293: {
                    294:     return(TestNegativeTime((LONG)((min * 60 + sec) * 75 + frame - 2 * 75)));
                    295: }
                    296: static LONG BCDTime2Block_Pointer (UBYTE *p)
                    297: {
                    298:     return BCDTime2Block (p[0], p[1], p[2]);
                    299: }
                    300: static LONG Time2Block_Pointer (UBYTE *p)
                    301: {
                    302:     return Time2Block (p[0], p[1], p[2]);
                    303: }
                    304: #endif
                    305: 
1.1       root      306: static void scsidev_do_scsi (struct scsidevdata *sdd, uaecptr request)
                    307: {
                    308:     SCSI *scgp = sdd->scgp;
                    309:     struct scg_cmd *scmd = scgp->scmd;
                    310:     uaecptr acmd = get_long (request + 40);
                    311:     uaecptr scsi_data = get_long (acmd + 0);
                    312:     uae_u32 scsi_len = get_long (acmd + 4);
                    313:     uaecptr scsi_cmd = get_long (acmd + 12);
                    314:     uae_u16 scsi_cmd_len = get_word (acmd + 16);
                    315:     uae_u8 scsi_flags = get_byte (acmd + 20);
                    316:     uaecptr scsi_sense = get_long (acmd + 22);
                    317:     uae_u16 scsi_sense_len = get_word (acmd + 26);
                    318:     int sactual = 0;
                    319:     addrbank *bank_data = &get_mem_bank (scsi_data);
                    320:     addrbank *bank_cmd  = &get_mem_bank (scsi_cmd);
                    321: 
                    322:     /* do transfer directly to and from Amiga memory */
                    323:     if (!bank_data || !bank_data->check (scsi_data, scsi_len) ||
1.1.1.7   root      324:        !bank_cmd  || !bank_cmd->check (scsi_cmd, scsi_cmd_len)) {
                    325:        put_byte (request + 31, (uae_u8)-5); /* IOERR_BADADDRESS */
                    326:        return;
1.1       root      327:     }
                    328: 
1.1.1.3   root      329: #ifdef SCSI_IS_NOT_THREAD_SAFE
1.1       root      330:     uae_sem_wait (&scgp_sem);
                    331: #endif
                    332: 
1.1.1.4   root      333:         scmd->timeout = 80 * 60; /* the Amiga does not tell us how long the timeout shall be, so make it _very_ long (specified in seconds) */
1.1       root      334:     scmd->addr = bank_data->xlateaddr (scsi_data);
                    335:     scmd->size = scsi_len;
                    336:     scmd->flags = ((scsi_flags & 1) ? SCG_RECV_DATA : 0) | SCG_DISRE_ENA;
                    337:     scmd->cdb_len = scsi_cmd_len;
                    338:     memcpy(&scmd->cdb, bank_cmd->xlateaddr (scsi_cmd), scsi_cmd_len);
                    339:     scmd->target = sdd->target;
                    340:     scmd->sense_len = (scsi_flags & 4) ? 4 : /* SCSIF_OLDAUTOSENSE */
1.1.1.7   root      341:        (scsi_flags & 2) ? scsi_sense_len : /* SCSIF_AUTOSENSE */
                    342:        -1;
1.1       root      343:     scmd->sense_count = 0;
                    344:     *(uae_u8 *)&scmd->scb = 0;
                    345: 
1.1.1.4   root      346:     #ifdef DEBUG_CDR
                    347:     /* please ignore this code - it can be used to debug raw CD-R writing... */
                    348:     if (!(scsi_len % 2368)) {
1.1.1.7   root      349:        /* Structure for generating bytes 2353...2368 if writing in ultra raw mode */
                    350:        typedef struct QDATAtag {
                    351:            BYTE ControlAdr;
                    352:            BCD Tno;
                    353:            BCD Point;
                    354:            BCD Min;
                    355:            BCD Sec;
                    356:            BCD Frame;
                    357:            BYTE Zero;
                    358:            BCD PMin;
                    359:            BCD PSec;
                    360:            BCD PFrame;
                    361:            WORD Crc;
                    362:            BYTE Reserved[3];
                    363:            BYTE PChannel;
                    364:        } QDATA;
                    365: 
                    366:        int i = scsi_len / 2368;
                    367:        QDATA *data = (QDATA *)&((unsigned char *)scmd->addr)[2352];
                    368:        for (; i > 0; i--, data = (QDATA *)&((unsigned char *)data)[2368]) {
                    369:            printf ("$%02x: $%02x $%02x | $%02x:$%02x:$%02x = %6ld | $%02x | $%02x:$%02x:$%02x = %6ld\n",
                    370:                    (int)data->ControlAdr, (int)*(UBYTE *)&data->Tno, (int)*(UBYTE *)&data->Point,
                    371:                    (int)*(UBYTE *)&data->Min, (int)*(UBYTE *)&data->Sec, (int)*(UBYTE *)&data->Frame,
                    372:                    BCDTime2Block_Pointer (&data->Min) + 150,
                    373:                    *(UBYTE *)&data->Zero,
                    374:                    *(UBYTE *)&data->PMin, *(UBYTE *)&data->PSec, *(UBYTE *)&data->PFrame,
                    375:                    BCDTime2Block_Pointer (&data->PMin));
                    376:        }
                    377:        fflush (stdout);
1.1.1.3   root      378:     }
1.1.1.4   root      379:     #endif
1.1.1.8   root      380: 
1.1       root      381:     scgp->scsibus = sdd->bus;
                    382:     scgp->target  = sdd->target;
                    383:     scgp->lun     = sdd->lun;
1.1.1.4   root      384:     scgp->cmdname = "???";
                    385:     scgp->curcmdname = "???";
1.1       root      386: 
1.1.1.3   root      387:     /* replace MODE_SELECT/SENSE_6 if we access a ATAPI drive,
                    388:        otherwise send it now */
                    389:     if (sdd->isatapi &&
1.1.1.7   root      390:        (scmd->cdb.g0_cdb.cmd == MODE_SELECT_6 ||
                    391:         scmd->cdb.g0_cdb.cmd == MODE_SENSE_6)) {
                    392:        uae_u8 buffer[256 + 2], *data = scmd->addr, *tmp;
                    393:        int len = 0, page_len, i;
                    394:        int do_it = 1;
                    395:        uae_u8 sp = scmd->cdb.g0_cdb.high_addr & 1;
                    396:        uae_u8 alloc_len = scmd->cdb.g0_cdb.count;
                    397:        uae_u8 pcf_page_code = scmd->cdb.g0_cdb.mid_addr;
                    398:        uae_u8 cmd = scmd->cdb.g0_cdb.cmd;
                    399: 
                    400:        memset (&scmd->cdb.g1_cdb, 0, sizeof(scmd->cdb.g1_cdb));
                    401:        if (cmd == MODE_SELECT_6) {
                    402:            /* expand parameter list */
                    403:            tmp = data;
                    404:            buffer[len++] = *tmp++;      /* first byte, should be 0 */
                    405:            buffer[len++] = 0;           /* reserved */
                    406:            buffer[len++] = *tmp++;      /* medium type */
                    407:            buffer[len++] = 0; *tmp++;   /* ignore host application code */
                    408:            for (i = 0; i < 4; i++) {
                    409:                buffer[len++] = 0;
                    410:            }
                    411:            if (*tmp) {
                    412:                /* skip block descriptor */
                    413:                tmp += 8;
                    414:            }
                    415:            tmp++;
                    416:            page_len = scsi_len - (tmp - data);
                    417:            if (page_len > 0) {
                    418:                memcpy (&buffer[len], tmp, page_len);
                    419:                len += page_len;
                    420: 
                    421:                scmd->cdb.g1_cdb.cmd = MODE_SELECT_10;
                    422:                scmd->cdb.g1_cdb.lun = sdd->lun;
                    423:                scmd->cdb.g1_cdb.res = 1 << 3; /* PF bit */
                    424:                scmd->cdb.g1_cdb.reladr = sp;
                    425:                scmd->cdb.g1_cdb.count[0] = len >> 8;
                    426:                scmd->cdb.g1_cdb.count[1] = len;
                    427:            } else {
                    428:                do_it = 0;
                    429:                scmd->error = 0;
                    430:                *(uae_u8 *)&scmd->scb = 0;
                    431:                scmd->ux_errno = 0;
                    432:            }
                    433:        } else {
                    434:            /* MODE_SENSE_6 */
                    435:            len = alloc_len + 2;
                    436:            scmd->cdb.g1_cdb.cmd = MODE_SENSE_10;
                    437:            scmd->cdb.g1_cdb.lun = sdd->lun;
                    438:            scmd->cdb.g1_cdb.addr[0] = pcf_page_code;
                    439:            scmd->cdb.g1_cdb.count[0] = len >> 8;
                    440:            scmd->cdb.g1_cdb.count[1] = len;
                    441:        }
                    442:        if (do_it) {
                    443:            scmd->cdb_len = 10;
                    444:            scmd->addr = buffer;
                    445:            scmd->size = len;
                    446:            scmd->sense_count = 0;
                    447:            *(uae_u8 *)&scmd->scb = 0;
1.1.1.8   root      448: 
1.1.1.7   root      449:            scsicmd (scgp);
                    450: 
                    451:            if (cmd == MODE_SENSE_6 &&
                    452:                !scmd->error &&
                    453:                !scmd->ux_errno &&
                    454:                !*(uae_u8 *)&scmd->scb) {
                    455:                int req_len = len;
1.1.1.8   root      456: 
1.1.1.7   root      457:                /* compress result */
                    458:                tmp = buffer;
                    459:                len = 0;
                    460:                tmp++;                 /* skip first byte of length - should better be zero */
                    461:                data[len++] = *tmp++;  /* mode data length */
                    462:                data[len++] = *tmp++;  /* medium type */
                    463:                data[len++] = 0;       /* host application type */
                    464:                data[len++] = 0;       /* block descr length */
                    465:                tmp += 4;
                    466:                if (*tmp) {
                    467:                    /* skip block descr - should not happen */
                    468:                    tmp += *tmp;
                    469:                }
                    470:                tmp++;
                    471:                memcpy (&data[len], tmp, req_len - (tmp - buffer));
                    472:            }
                    473:        }
1.1.1.3   root      474:     } else {
1.1.1.7   root      475:        scsicmd (scgp);
1.1       root      476:     }
1.1.1.8   root      477: 
1.1       root      478:     put_word (acmd + 18, scmd->error == SCG_FATAL ? 0 : scsi_cmd_len); /* fake scsi_CmdActual */
                    479:     put_byte (acmd + 21, *(uae_u8 *)&scmd->scb); /* scsi_Status */
                    480:     if (*(uae_u8 *)&scmd->scb) {
1.1.1.7   root      481:        put_byte (request + 31, 45); /* HFERR_BadStatus */
1.1       root      482: 
1.1.1.7   root      483:        /* copy sense? */
                    484:        for (sactual = 0;
                    485:             scsi_sense && sactual < scsi_sense_len && sactual < scmd->sense_count;
                    486:             sactual++) {
                    487:            put_byte (scsi_sense + sactual, scmd->u_sense.cmd_sense[sactual]);
                    488:        }
                    489:        put_long (acmd + 8, 0); /* scsi_Actual */
1.1       root      490:     } else {
1.1.1.7   root      491:        int i;
1.1.1.8   root      492: 
1.1.1.7   root      493:        for (i = 0; i < scsi_sense_len; i++) {
                    494:            put_byte (scsi_sense + i, 0);
                    495:        }
                    496:        sactual = 0;
                    497: 
                    498:        if (scmd->error != SCG_NO_ERROR ||
                    499:            scmd->ux_errno != 0) {
                    500:            /* we might have been limited by the hosts DMA limits,
                    501:               which is usually indicated by ENOMEM */
                    502:            if (scsi_len > (unsigned int)sdd->max_dma &&
                    503:                scmd->ux_errno == ENOMEM) {
                    504:                put_byte (request + 31, (uae_u8)-4); /* IOERR_BADLENGTH */
                    505:            } else {
                    506:                put_byte (request + 31, 20); /* io_Error, but not specified */
                    507:                put_long (acmd + 8, 0); /* scsi_Actual */
                    508:            }
                    509:        } else {
                    510:            put_byte (request + 31, 0);
                    511:            put_long (acmd + 8, scsi_len - scmd->resid); /* scsi_Actual */
                    512:        }
1.1       root      513:     }
                    514:     put_word (acmd + 28, sactual);
                    515: 
1.1.1.3   root      516: #ifdef SCSI_IS_NOT_THREAD_SAFE
1.1       root      517:     uae_sem_post (&scgp_sem);
                    518: #endif
                    519: }
                    520: 
                    521: static void scsidev_do_io (struct scsidevdata *sdd, uaecptr request)
                    522: {
                    523:     uae_u32 tmp2, dataptr, offset;
1.1.1.8   root      524: 
1.1       root      525:     tmp2 = get_word (request+28); /* io_Command */
                    526:     switch (tmp2) {
                    527:      case 28:
1.1.1.7   root      528:        /* HD_SCSICMD */
                    529:        scsidev_do_scsi (sdd, request);
                    530:        break;
1.1       root      531:      default:
                    532:        /* Command not understood. */
                    533:        put_byte (request+31, (uae_u8)-3); /* io_Error */
                    534:        break;
                    535:     }
                    536: #ifdef DEBUGME
                    537:     printf ("scsidev: did io: sdd     = 0x%x\n", sdd);
                    538:     printf ("scsidev: did io: request = %08lx\n", (unsigned long)request);
1.1.1.10! root      539:     printf ("scsidev: did io: error   = %d\n", (int)get_word (request+31));
1.1       root      540: #endif
                    541: }
                    542: 
                    543: 
                    544: static uae_u32 scsidev_beginio (void)
                    545: {
1.1.1.10! root      546:     uae_u32 request = m68k_areg (regs, 1);
1.1       root      547:     int unit = get_long (request + 24);
                    548:     struct scsidevdata *sdd = get_scsidev_data (unit);
                    549: 
                    550: #ifdef DEBUGME
                    551:     printf ("scsidev_begin_io: sdd     = 0x%x\n", sdd);
                    552:     printf ("scsidev_begin_io: request = %08lx\n", (unsigned long)request);
1.1.1.10! root      553:     printf ("scsidev_begin_io: cmd     = %d\n", (int)get_word (request+28));
1.1       root      554: #endif
                    555: 
                    556:     put_byte (request+8, NT_MESSAGE);
                    557:     put_byte (request+31, 0); /* no error yet */
                    558: 
                    559: #ifdef UAE_SCSIDEV_THREADS
                    560:     {
1.1.1.7   root      561:        uae_pt data;
1.1       root      562: 
1.1.1.7   root      563:        /* clear IOF_QUICK */
                    564:        put_byte (request+30, get_byte (request+30) & ~1);
                    565:        /* forward to unit thread */
                    566:        write_comm_pipe_u32 (&sdd->requests, request, 1);
                    567:        return 0;
1.1       root      568:     }
                    569: #else
                    570:     put_byte (request+30, get_byte (request+30) & ~1);
                    571:     scsidev_do_io (sdd, request);
                    572:     return get_byte (request+31); /* do we really have to return io_Error? */
                    573: #endif
                    574: }
                    575: 
                    576: #ifdef UAE_SCSIDEV_THREADS
1.1.1.6   root      577: static void *scsidev_thread (void *sddv)
1.1       root      578: {
                    579:     struct scsidevdata *sdd = sddv;
                    580: 
                    581: #ifdef DEBUGME
                    582:     printf ("scsidev_penguin: sdd  = 0x%x ready\n", sdd);
1.1.1.8   root      583: #endif
1.1       root      584:     /* init SCSI */
1.1.1.3   root      585:     if (!(sdd->scgp = openscsi (sdd->bus, sdd->target, sdd->lun)) ||
1.1.1.7   root      586:        (sdd->max_dma = scsi_bufsize (sdd->scgp, 512 * 1024)) <= 0) {
                    587:        sdd->thread_running = 0;
                    588:        uae_sem_post (&sdd->sync_sem);
                    589:        return 0;
1.1       root      590:     }
                    591:     sdd->thread_running = 1;
                    592:     uae_sem_post (&sdd->sync_sem);
                    593: 
                    594:     for (;;) {
                    595:        uaecptr request;
                    596: 
                    597:        request = (uaecptr)read_comm_pipe_u32_blocking (&sdd->requests);
                    598: #ifdef DEBUGME
1.1.1.7   root      599:        printf ("scsidev_penguin: sdd  = 0x%x\n", sdd);
                    600:        printf ("scsidev_penguin: req  = %08lx\n", (unsigned long)request);
1.1.1.10! root      601:        printf ("scsidev_penguin: cmd  = %d\n", (int)get_word (request+28));
1.1       root      602: #endif
1.1.1.7   root      603:        if (!request) {
                    604:            printf ("scsidev_penguin: going down with 0x%x\n", sdd->sync_sem);
1.1       root      605:            /* Death message received. */
1.1.1.7   root      606:            sdd->thread_running = 0;
1.1       root      607:            uae_sem_post (&sdd->sync_sem);
                    608:            /* Die.  */
                    609:            return 0;
                    610:        }
                    611: 
1.1.1.7   root      612:        scsidev_do_io (sdd, request);
                    613:        uae_ReplyMsg (request);
1.1       root      614:     }
                    615:     return 0;
                    616: }
                    617: #endif
                    618: 
                    619: 
                    620: static uae_u32 scsidev_abortio (void)
                    621: {
                    622:     return (uae_u32)-3;
                    623: }
                    624: 
                    625: static uae_u32 scsidev_init (void)
                    626: {
                    627: #ifdef DEBUGME
                    628:     printf("scsidev_init()\n");
                    629: #endif
1.1.1.8   root      630: 
1.1       root      631:     if (scgp) {
1.1.1.7   root      632:        /* we still have everything in place */
                    633:        return m68k_dreg (regs, 0); /* device base */
1.1       root      634:     }
1.1.1.8   root      635: 
1.1       root      636:     /* init global SCSI */
1.1.1.3   root      637:     if (!(scgp = openscsi (-1, -1, -1))) {
1.1.1.7   root      638:        return 0;
1.1       root      639:     }
                    640: 
                    641:     uae_sem_init (&scgp_sem, 0, 1);
                    642: 
                    643:     /* add all units we find */
                    644:     for (scgp->scsibus=0; scgp->scsibus < 8; scgp->scsibus++) {
1.1.1.7   root      645:        if (!scsi_havebus(scgp, scgp->scsibus))
                    646:            continue;
                    647:        printf("scsibus%d:\n", scgp->scsibus);
                    648:        for (scgp->target=0; scgp->target < 16; scgp->target++) {
                    649:            struct scsi_inquiry inq;
                    650:            scgp->lun = 0;
                    651:            if (inquiry (scgp, &inq, sizeof(inq))) {
                    652:                continue;
                    653:            }
                    654:            for (scgp->lun=0; scgp->lun < 8; scgp->lun++) {
                    655:                if (!inquiry (scgp, &inq, sizeof(inq))) {
                    656:                    int aunit = BTL2UNIT(scgp->scsibus, scgp->target, scgp->lun);
                    657:                    struct scsidevdata *sdd;
1.1.1.8   root      658: 
1.1.1.7   root      659:                    write_log ("   %2.01d,%d (= %3.d): ", scgp->target, scgp->lun, aunit);
                    660:                    print_product (&inq);
                    661:                    sdd = add_scsidev_data (scgp->scsibus, scgp->target, scgp->lun, aunit);
                    662:                    write_log (!sdd ? " - init failed ???" : sdd->isatapi ? " - ATAPI" : " - SCSI");
                    663:                    write_log ("\n");
1.1       root      664:                }
1.1.1.7   root      665:            }
                    666:        }
1.1       root      667:     }
                    668:     return m68k_dreg (regs, 0); /* device base */
                    669: }
                    670: 
                    671: static uaecptr ROM_scsidev_resname = 0,
                    672:     ROM_scsidev_resid = 0,
                    673:     ROM_scsidev_init = 0;
                    674: 
                    675: uaecptr scsidev_startup (uaecptr resaddr)
                    676: {
                    677: #ifdef DEBUGME
                    678:     printf("scsidev_startup(0x%x)\n", resaddr);
                    679: #endif
                    680:     /* Build a struct Resident. This will set up and initialize
                    681:      * the uaescsi.device */
1.1.1.10! root      682:     put_word (resaddr + 0x0, 0x4AFC);
        !           683:     put_long (resaddr + 0x2, resaddr);
        !           684:     put_long (resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
        !           685:     put_word (resaddr + 0xA, 0x8101); /* RTF_AUTOINIT|RTF_COLDSTART; Version 1 */
        !           686:     put_word (resaddr + 0xC, 0x0305); /* NT_DEVICE; pri 05 */
        !           687:     put_long (resaddr + 0xE, ROM_scsidev_resname);
        !           688:     put_long (resaddr + 0x12, ROM_scsidev_resid);
        !           689:     put_long (resaddr + 0x16, ROM_scsidev_init); /* calls scsidev_init */
1.1       root      690:     resaddr += 0x1A;
                    691: 
                    692:     return resaddr;
                    693: }
                    694: 
                    695: void scsidev_install (void)
                    696: {
                    697:     uae_u32 functable, datatable;
                    698:     uae_u32 initcode, openfunc, closefunc, expungefunc;
                    699:     uae_u32 beginiofunc, abortiofunc;
                    700: 
                    701: #ifdef DEBUGME
                    702:     printf("scsidev_install(): 0x%x\n", here ());
                    703: #endif
                    704: 
                    705:     ROM_scsidev_resname = ds ("uaescsi.device");
                    706:     ROM_scsidev_resid = ds ("UAE scsi.device 0.1");
                    707: 
                    708:     /* initcode */
                    709:     initcode = here ();
                    710:     calltrap (deftrap (scsidev_init)); dw (RTS);
1.1.1.8   root      711: 
1.1       root      712:     /* Open */
                    713:     openfunc = here ();
                    714:     calltrap (deftrap (scsidev_open)); dw (RTS);
                    715: 
                    716:     /* Close */
                    717:     closefunc = here ();
                    718:     calltrap (deftrap (scsidev_close)); dw (RTS);
                    719: 
                    720:     /* Expunge */
                    721:     expungefunc = here ();
                    722:     calltrap (deftrap (scsidev_expunge)); dw (RTS);
                    723: 
                    724:     /* BeginIO */
                    725:     beginiofunc = here ();
                    726:     calltrap (deftrap (scsidev_beginio));
                    727: #ifndef UAE_SCSIDEV_THREADS
                    728:     /* don't reply when using threads - native2amiga's Reply() does that */
                    729:     dw (0x48E7); dw (0x8002); /* movem.l d0/a6,-(a7) */
                    730:     dw (0x0829); dw (0); dw (30); /* btst #0,30(a1) */
                    731:     dw (0x6608); /* bne.b +8 */
                    732:     dw (0x2C78); dw (0x0004); /* move.l 4,a6 */
                    733:     dw (0x4EAE); dw (-378); /* jsr ReplyMsg(a6) */
                    734:     dw (0x4CDF); dw (0x4001); /* movem.l (a7)+,d0/a6 */
                    735: #endif
                    736:     dw (RTS);
                    737: 
                    738:     /* AbortIO */
                    739:     abortiofunc = here ();
                    740:     calltrap (deftrap (scsidev_abortio)); dw (RTS);
                    741: 
                    742:     /* FuncTable */
                    743:     functable = here ();
                    744:     dl (openfunc); /* Open */
                    745:     dl (closefunc); /* Close */
                    746:     dl (expungefunc); /* Expunge */
                    747:     dl (EXPANSION_nullfunc); /* Null */
                    748:     dl (beginiofunc); /* BeginIO */
                    749:     dl (abortiofunc); /* AbortIO */
                    750:     dl (0xFFFFFFFFul); /* end of table */
                    751: 
                    752:     /* DataTable */
                    753:     datatable = here ();
                    754:     dw (0xE000); /* INITBYTE */
                    755:     dw (0x0008); /* LN_TYPE */
                    756:     dw (0x0300); /* NT_DEVICE */
                    757:     dw (0xC000); /* INITLONG */
                    758:     dw (0x000A); /* LN_NAME */
                    759:     dl (ROM_scsidev_resname);
                    760:     dw (0xE000); /* INITBYTE */
                    761:     dw (0x000E); /* LIB_FLAGS */
                    762:     dw (0x0600); /* LIBF_SUMUSED | LIBF_CHANGED */
                    763:     dw (0xD000); /* INITWORD */
                    764:     dw (0x0014); /* LIB_VERSION */
                    765:     dw (0x0004); /* 0.4 */
                    766:     dw (0xD000); /* INITWORD */
                    767:     dw (0x0016); /* LIB_REVISION */
                    768:     dw (0x0000); /* end of table already ??? */
                    769:     dw (0xC000); /* INITLONG */
                    770:     dw (0x0018); /* LIB_IDSTRING */
                    771:     dl (ROM_scsidev_resid);
                    772:     dw (0x0000); /* end of table */
                    773: 
                    774:     ROM_scsidev_init = here ();
                    775:     dl (0x00000100); /* size of device base */
                    776:     dl (functable);
                    777:     dl (datatable);
                    778:     dl (initcode);
                    779: }
                    780: 
                    781: void scsidev_reset (void)
                    782: {
                    783: #ifdef DEBUGME
                    784:     printf("scsidev_reset()\n");
                    785: #endif
                    786: 
                    787: #ifdef SCSI_CLOSE
                    788: #ifdef UAE_SCSIDEV_THREADS
                    789:     {
1.1.1.7   root      790:        int i;
1.1       root      791: 
1.1.1.7   root      792:        for (i = 0; i < num_drives; i++) {
                    793:            if (!drives[i].thread_running) {
                    794:                continue;
                    795:            }
                    796:            write_comm_pipe_int (&drives[i].requests, 0, 1);
                    797:            uae_sem_wait (&drives[i].sync_sem);
                    798:        }
                    799:        num_drives = 0;
1.1       root      800:     }
                    801: #endif
1.1.1.8   root      802: 
1.1       root      803:     if (scgp) {
1.1.1.7   root      804:        closescsi (scgp);
                    805:        scgp = NULL;
1.1       root      806:     }
                    807: #endif
1.1.1.8   root      808: 
1.1       root      809:     opencount = 0;
                    810: }
                    811: 
                    812: void scsidev_start_threads (void)
                    813: {
                    814: #ifdef DEBUGME
                    815:     printf("scsidev_start_threads()\n");
                    816: #endif
                    817: }
                    818: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.