Annotation of hatari/src/hdc.c, revision 1.1.1.16

1.1       root        1: /*
1.1.1.3   root        2:   Hatari - hdc.c
1.1       root        3: 
1.1.1.15  root        4:   This file is distributed under the GNU General Public License, version 2
                      5:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
1.1.1.3   root        7:   Low-level hard drive emulation
1.1       root        8: */
1.1.1.10  root        9: const char HDC_fileid[] = "Hatari hdc.c : " __DATE__ " " __TIME__;
1.1       root       10: 
                     11: #include "main.h"
1.1.1.3   root       12: #include "configuration.h"
1.1.1.6   root       13: #include "debugui.h"
1.1.1.7   root       14: #include "file.h"
1.1       root       15: #include "fdc.h"
                     16: #include "hdc.h"
1.1.1.14  root       17: #include "ioMem.h"
1.1.1.7   root       18: #include "log.h"
1.1       root       19: #include "memorySnapShot.h"
                     20: #include "mfp.h"
                     21: #include "stMemory.h"
1.1.1.6   root       22: #include "tos.h"
1.1.1.9   root       23: #include "statusbar.h"
                     24: 
1.1       root       25: 
                     26: /*
                     27:   ACSI emulation: 
                     28:   ACSI commands are six byte-packets sent to the
                     29:   hard drive controller (which is on the HD unit, not in the ST)
                     30: 
                     31:   While the hard drive is busy, DRQ is high, polling the DRQ during
                     32:   operation interrupts the current operation. The DRQ status can
                     33:   be polled non-destructively in GPIP.
1.1.1.7   root       34: 
1.1.1.15  root       35:   (For simplicity, the operation is finished immediately,
1.1       root       36:   this is a potential bug, but I doubt it is significant,
                     37:   we just appear to have a very fast hard drive.)
                     38: 
                     39:   The ACSI command set is a subset of the SCSI standard.
                     40:   (for details, see the X3T9.2 SCSI draft documents
                     41:   from 1985, for an example of writing ACSI commands,
                     42:   see the TOS DMA boot code) 
                     43: */
                     44: 
1.1.1.7   root       45: // #define DISALLOW_HDC_WRITE
                     46: // #define HDC_VERBOSE           /* display operations */
1.1       root       47: 
1.1.1.14  root       48: #define HDC_ReadInt16(a, i) (((unsigned) a[i] << 8) | a[i + 1])
                     49: #define HDC_ReadInt24(a, i) (((unsigned) a[i] << 16) | ((unsigned) a[i + 1] << 8) | a[i + 2])
                     50: #define HDC_ReadInt32(a, i) (((unsigned) a[i] << 24) | ((unsigned) a[i + 1] << 16) | ((unsigned) a[i + 2] << 8) | a[i + 3])
                     51: 
                     52: /**
1.1.1.16! root       53:  * Information about a ACSI/SCSI drive
1.1.1.14  root       54:  */
                     55: typedef struct {
1.1.1.16! root       56:        bool enabled;
        !            57:        FILE *image_file;
        !            58:        Uint32 nLastBlockAddr;      /* The specified sector number */
        !            59:        bool bSetLastBlockAddr;
        !            60:        Uint8 nLastError;
        !            61:        unsigned long hdSize;       /* Size of the hard disk in sectors */
        !            62: } SCSI_DEV;
        !            63: 
        !            64: /**
        !            65:  * Status of the ACSI/SCSI bus/controller including the current command block.
        !            66:  */
        !            67: typedef struct {
        !            68:        int target;
        !            69:        int byteCount;              /* number of command bytes received */
        !            70:        Uint8 command[16];
        !            71:        Uint8 opcode;
        !            72:        bool bDmaError;
        !            73:        short int returnCode;       /* return code from the HDC operation */
        !            74:        SCSI_DEV devs[8];
        !            75: } SCSI_CTRLR;
1.1.1.14  root       76: 
1.1       root       77: /* HDC globals */
1.1.1.16! root       78: SCSI_CTRLR AcsiBus;
1.1       root       79: int nPartitions = 0;
1.1.1.11  root       80: bool bAcsiEmuOn = false;
1.1.1.7   root       81: 
1.1       root       82: 
                     83: /* Our dummy INQUIRY response data */
1.1.1.7   root       84: static unsigned char inquiry_bytes[] =
1.1       root       85: {
1.1.1.7   root       86:        0,                /* device type 0 = direct access device */
                     87:        0,                /* device type qualifier (nonremovable) */
1.1.1.16! root       88:        1,                /* ACSI/SCSI version */
1.1.1.7   root       89:        0,                /* reserved */
1.1.1.16! root       90:        31,               /* length of the following data */
        !            91:        0, 0, 0,          /* Vendor specific data */
        !            92:        'H','a','t','a','r','i',' ',' ',    /* Vendor ID */
        !            93:        'E','m','u','l','a','t','e','d',    /* Product ID 1 */
        !            94:        'H','a','r','d','d','i','s','k',    /* Product ID 2 */
        !            95:        '0','1','8','0',                    /* Revision */
1.1       root       96: };
                     97: 
1.1.1.7   root       98: 
1.1       root       99: /*---------------------------------------------------------------------*/
1.1.1.8   root      100: /**
1.1.1.16! root      101:  * Return the LUN (logical unit number) specified in the current
        !           102:  * ACSI/SCSI command block.
1.1.1.14  root      103:  */
1.1.1.16! root      104: static unsigned char HDC_GetLUN(SCSI_CTRLR *ctr)
1.1.1.14  root      105: {
1.1.1.16! root      106:        return (ctr->command[1] & 0xE0) >> 5;
1.1.1.14  root      107: }
                    108: 
                    109: /**
1.1.1.16! root      110:  * Return the start sector (logical block address) specified in the
        !           111:  * current ACSI/SCSI command block.
1.1.1.8   root      112:  */
1.1.1.16! root      113: static unsigned long HDC_GetLBA(SCSI_CTRLR *ctr)
1.1.1.4   root      114: {
1.1.1.14  root      115:        /* offset = logical block address * 512 */
1.1.1.16! root      116:        if (ctr->opcode < 0x20)                         /* Class 0? */
        !           117:                return HDC_ReadInt24(ctr->command, 1) & 0x1FFFFF;
        !           118:        else
        !           119:                return HDC_ReadInt32(ctr->command, 2);  /* Class 1 */
1.1.1.14  root      120: }
1.1       root      121: 
1.1.1.14  root      122: /**
                    123:  * Return the count specified in the current ACSI command block.
                    124:  */
1.1.1.16! root      125: static int HDC_GetCount(SCSI_CTRLR *ctr)
1.1.1.14  root      126: {
1.1.1.16! root      127:        if (ctr->opcode < 0x20)
        !           128:                return ctr->command[4];                 /* Class 0 */
        !           129:        else
        !           130:                return HDC_ReadInt16(ctr->command, 7);  /* Class 1 */
1.1.1.14  root      131: }
1.1.1.7   root      132: 
1.1.1.14  root      133: /**
                    134:  * Return the control byte specified in the current ACSI command block.
                    135:  */
1.1.1.16! root      136: static inline Uint8 HDC_GetControl(SCSI_CTRLR *ctr)
1.1.1.14  root      137: {
1.1.1.16! root      138:        if (ctr->opcode < 0x20)
        !           139:                return ctr->command[5];                 /* Class 0 */
        !           140:        else
        !           141:                return ctr->command[9];                 /* Class 1 */
        !           142: }
        !           143: 
        !           144: /**
        !           145:  * Get info string for SCSI/ACSI command packets.
        !           146:  */
        !           147: static inline char *HDC_CmdInfoStr(SCSI_CTRLR *ctr)
        !           148: {
        !           149:        static char str[80];
        !           150: 
        !           151:        snprintf(str, sizeof(str), "t=%i, lun=%i, opc=%i, cnt=0x%x, ctrl=0x%x",
        !           152:                 ctr->target, HDC_GetLUN(ctr), ctr->opcode, HDC_GetCount(ctr),
        !           153:                 HDC_GetControl(ctr));
        !           154: 
        !           155:        return str;
1.1       root      156: }
                    157: 
1.1.1.7   root      158: 
1.1.1.8   root      159: /**
                    160:  * Seek - move to a sector
                    161:  */
1.1.1.16! root      162: static void HDC_Cmd_Seek(SCSI_CTRLR *ctr)
1.1       root      163: {
1.1.1.16! root      164:        SCSI_DEV *dev = &ctr->devs[ctr->target];
        !           165: 
        !           166:        dev->nLastBlockAddr = HDC_GetLBA(ctr);
        !           167: 
        !           168:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: SEEK (%s), LBA=%i.\n",
        !           169:                  HDC_CmdInfoStr(ctr), dev->nLastBlockAddr);
1.1       root      170: 
1.1.1.16! root      171:        if (dev->nLastBlockAddr < dev->hdSize &&
        !           172:            fseeko(dev->image_file, (off_t)dev->nLastBlockAddr * 512L, SEEK_SET) == 0)
1.1.1.7   root      173:        {
1.1.1.16! root      174:                ctr->returnCode = HD_STATUS_OK;
        !           175:                dev->nLastError = HD_REQSENS_OK;
1.1.1.7   root      176:        }
                    177:        else
                    178:        {
1.1.1.16! root      179:                ctr->returnCode = HD_STATUS_ERROR;
        !           180:                dev->nLastError = HD_REQSENS_INVADDR;
1.1.1.7   root      181:        }
1.1       root      182: 
1.1.1.16! root      183:        dev->bSetLastBlockAddr = true;
1.1       root      184: }
                    185: 
1.1.1.7   root      186: 
1.1.1.8   root      187: /**
                    188:  * Inquiry - return some disk information
                    189:  */
1.1.1.16! root      190: static void HDC_Cmd_Inquiry(SCSI_CTRLR *ctr)
1.1.1.7   root      191: {
1.1.1.16! root      192:        SCSI_DEV *dev = &ctr->devs[ctr->target];
1.1.1.12  root      193:        Uint32 nDmaAddr;
                    194:        int count;
                    195: 
1.1.1.14  root      196:        nDmaAddr = FDC_GetDMAAddress();
1.1.1.16! root      197:        count = HDC_GetCount(ctr);
1.1.1.12  root      198: 
1.1.1.16! root      199:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: INQUIRY (%s) to 0x%x.\n",
        !           200:                  HDC_CmdInfoStr(ctr), nDmaAddr);
1.1.1.7   root      201: 
1.1.1.12  root      202:        if (count > (int)sizeof(inquiry_bytes))
                    203:                count = sizeof(inquiry_bytes);
                    204: 
1.1.1.16! root      205:        /* For unsupported LUNs set the Peripheral Qualifier and the
        !           206:         * Peripheral Device Type according to the SCSI standard */
        !           207:        inquiry_bytes[0] = HDC_GetLUN(ctr) == 0 ? 0 : 0x7F;
        !           208: 
        !           209:        inquiry_bytes[4] = count - 5;
1.1.1.12  root      210: 
1.1.1.13  root      211:        if (STMemory_SafeCopy(nDmaAddr, inquiry_bytes, count, "HDC DMA inquiry"))
1.1.1.16! root      212:        {
        !           213:                ctr->returnCode = HD_STATUS_OK;
        !           214:        }
1.1.1.13  root      215:        else
1.1.1.16! root      216:        {
        !           217:                ctr->bDmaError = true;
        !           218:                ctr->returnCode = HD_STATUS_ERROR;
        !           219:        }
1.1.1.13  root      220: 
1.1.1.12  root      221:        FDC_WriteDMAAddress(nDmaAddr + count);
1.1.1.7   root      222: 
1.1.1.16! root      223:        dev->nLastError = HD_REQSENS_OK;
        !           224:        dev->bSetLastBlockAddr = false;
1.1.1.7   root      225: }
                    226: 
                    227: 
1.1.1.8   root      228: /**
                    229:  * Request sense - return some disk information
                    230:  */
1.1.1.16! root      231: static void HDC_Cmd_RequestSense(SCSI_CTRLR *ctr)
1.1       root      232: {
1.1.1.16! root      233:        SCSI_DEV *dev = &ctr->devs[ctr->target];
1.1.1.7   root      234:        Uint32 nDmaAddr;
                    235:        int nRetLen;
                    236:        Uint8 retbuf[22];
                    237: 
1.1.1.16! root      238:        nRetLen = HDC_GetCount(ctr);
1.1.1.7   root      239: 
1.1.1.16! root      240:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: REQUEST SENSE (%s).\n", HDC_CmdInfoStr(ctr));
1.1.1.7   root      241: 
                    242:        if ((nRetLen < 4 && nRetLen != 0) || nRetLen > 22)
                    243:        {
1.1.1.9   root      244:                Log_Printf(LOG_WARN, "HDC: *** Strange REQUEST SENSE ***!\n");
1.1.1.7   root      245:        }
                    246: 
                    247:        /* Limit to sane length */
                    248:        if (nRetLen <= 0)
                    249:        {
                    250:                nRetLen = 4;
                    251:        }
                    252:        else if (nRetLen > 22)
                    253:        {
                    254:                nRetLen = 22;
                    255:        }
                    256: 
1.1.1.14  root      257:        nDmaAddr = FDC_GetDMAAddress();
1.1.1.7   root      258: 
                    259:        memset(retbuf, 0, nRetLen);
                    260: 
                    261:        if (nRetLen <= 4)
                    262:        {
1.1.1.16! root      263:                retbuf[0] = dev->nLastError;
        !           264:                if (dev->bSetLastBlockAddr)
1.1.1.7   root      265:                {
                    266:                        retbuf[0] |= 0x80;
1.1.1.16! root      267:                        retbuf[1] = dev->nLastBlockAddr >> 16;
        !           268:                        retbuf[2] = dev->nLastBlockAddr >> 8;
        !           269:                        retbuf[3] = dev->nLastBlockAddr;
1.1.1.7   root      270:                }
                    271:        }
                    272:        else
                    273:        {
                    274:                retbuf[0] = 0x70;
1.1.1.16! root      275:                if (dev->bSetLastBlockAddr)
1.1.1.7   root      276:                {
                    277:                        retbuf[0] |= 0x80;
1.1.1.16! root      278:                        retbuf[4] = dev->nLastBlockAddr >> 16;
        !           279:                        retbuf[5] = dev->nLastBlockAddr >> 8;
        !           280:                        retbuf[6] = dev->nLastBlockAddr;
1.1.1.7   root      281:                }
1.1.1.16! root      282:                switch (dev->nLastError)
1.1.1.7   root      283:                {
                    284:                 case HD_REQSENS_OK:  retbuf[2] = 0; break;
                    285:                 case HD_REQSENS_OPCODE:  retbuf[2] = 5; break;
                    286:                 case HD_REQSENS_INVADDR:  retbuf[2] = 5; break;
                    287:                 case HD_REQSENS_INVARG:  retbuf[2] = 5; break;
1.1.1.16! root      288:                 case HD_REQSENS_INVLUN:  retbuf[2] = 5; break;
1.1.1.7   root      289:                 default: retbuf[2] = 4; break;
                    290:                }
                    291:                retbuf[7] = 14;
1.1.1.16! root      292:                retbuf[12] = dev->nLastError;
        !           293:                retbuf[19] = dev->nLastBlockAddr >> 16;
        !           294:                retbuf[20] = dev->nLastBlockAddr >> 8;
        !           295:                retbuf[21] = dev->nLastBlockAddr;
1.1.1.7   root      296:        }
                    297: 
                    298:        /*
                    299:        fprintf(stderr,"*** Requested sense packet:\n");
                    300:        int i;
                    301:        for (i = 0; i<nRetLen; i++) fprintf(stderr,"%2x ",retbuf[i]);
                    302:        fprintf(stderr,"\n");
                    303:        */
                    304: 
1.1.1.13  root      305:        if (STMemory_SafeCopy(nDmaAddr, retbuf, nRetLen, "HDC request sense"))
1.1.1.16! root      306:        {
        !           307:                ctr->returnCode = HD_STATUS_OK;
        !           308:        }
1.1.1.13  root      309:        else
1.1.1.16! root      310:        {
        !           311:                ctr->bDmaError = true;
        !           312:                ctr->returnCode = HD_STATUS_ERROR;
        !           313:        }
1.1.1.13  root      314: 
1.1.1.12  root      315:        FDC_WriteDMAAddress(nDmaAddr + nRetLen);
1.1.1.7   root      316: }
                    317: 
                    318: 
1.1.1.8   root      319: /**
                    320:  * Mode sense - Get parameters from disk.
                    321:  * (Just enough to make the HDX tool from AHDI 5.0 happy)
                    322:  */
1.1.1.16! root      323: static void HDC_Cmd_ModeSense(SCSI_CTRLR *ctr)
1.1.1.7   root      324: {
1.1.1.16! root      325:        SCSI_DEV *dev = &ctr->devs[ctr->target];
1.1.1.7   root      326:        Uint32 nDmaAddr;
                    327: 
1.1.1.16! root      328:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: MODE SENSE (%s).\n", HDC_CmdInfoStr(ctr));
1.1.1.7   root      329: 
1.1.1.14  root      330:        nDmaAddr = FDC_GetDMAAddress();
1.1.1.7   root      331: 
1.1.1.13  root      332:        if (!STMemory_ValidArea(nDmaAddr, 16))
                    333:        {
                    334:                Log_Printf(LOG_WARN, "HCD mode sense uses invalid RAM range 0x%x+%i\n", nDmaAddr, 16);
1.1.1.16! root      335:                ctr->bDmaError = true;
        !           336:                ctr->returnCode = HD_STATUS_ERROR;
1.1.1.13  root      337:        }
1.1.1.16! root      338:        else if (ctr->command[2] == 0 && HDC_GetCount(ctr) == 0x10)
1.1.1.7   root      339:        {
                    340:                size_t blocks;
1.1.1.16! root      341:                blocks = dev->hdSize;
1.1.1.7   root      342: 
                    343:                STRam[nDmaAddr+0] = 0;
                    344:                STRam[nDmaAddr+1] = 0;
                    345:                STRam[nDmaAddr+2] = 0;
                    346:                STRam[nDmaAddr+3] = 8;
                    347:                STRam[nDmaAddr+4] = 0;
                    348: 
                    349:                STRam[nDmaAddr+5] = blocks >> 16;  // Number of blocks, high (?)
                    350:                STRam[nDmaAddr+6] = blocks >> 8;   // Number of blocks, med (?)
                    351:                STRam[nDmaAddr+7] = blocks;        // Number of blocks, low (?)
                    352: 
                    353:                STRam[nDmaAddr+8] = 0;
                    354: 
                    355:                STRam[nDmaAddr+9] = 0;      // Block size in bytes, high
                    356:                STRam[nDmaAddr+10] = 2;     // Block size in bytes, med
                    357:                STRam[nDmaAddr+11] = 0;     // Block size in bytes, low
                    358: 
                    359:                STRam[nDmaAddr+12] = 0;
                    360:                STRam[nDmaAddr+13] = 0;
                    361:                STRam[nDmaAddr+14] = 0;
                    362:                STRam[nDmaAddr+15] = 0;
                    363: 
1.1.1.12  root      364:                FDC_WriteDMAAddress(nDmaAddr + 16);
                    365: 
1.1.1.16! root      366:                ctr->returnCode = HD_STATUS_OK;
        !           367:                dev->nLastError = HD_REQSENS_OK;
1.1.1.7   root      368:        }
                    369:        else
                    370:        {
1.1.1.9   root      371:                Log_Printf(LOG_TODO, "HDC: Unsupported MODE SENSE command\n");
1.1.1.16! root      372:                ctr->returnCode = HD_STATUS_ERROR;
        !           373:                dev->nLastError = HD_REQSENS_INVARG;
1.1.1.7   root      374:        }
                    375: 
1.1.1.16! root      376:        dev->bSetLastBlockAddr = false;
1.1.1.7   root      377: }
                    378: 
                    379: 
1.1.1.8   root      380: /**
                    381:  * Format drive.
                    382:  */
1.1.1.16! root      383: static void HDC_Cmd_FormatDrive(SCSI_CTRLR *ctr)
1.1.1.7   root      384: {
1.1.1.16! root      385:        SCSI_DEV *dev = &ctr->devs[ctr->target];
        !           386: 
        !           387:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: FORMAT DRIVE (%s).\n", HDC_CmdInfoStr(ctr));
1.1.1.7   root      388: 
                    389:        /* Should erase the whole image file here... */
                    390: 
1.1.1.16! root      391:        ctr->returnCode = HD_STATUS_OK;
        !           392:        dev->nLastError = HD_REQSENS_OK;
        !           393:        dev->bSetLastBlockAddr = false;
1.1       root      394: }
                    395: 
1.1.1.16! root      396: 
1.1.1.14  root      397: /**
                    398:  * Read capacity of our disk.
                    399:  */
1.1.1.16! root      400: static void HDC_Cmd_ReadCapacity(SCSI_CTRLR *ctr)
1.1.1.14  root      401: {
1.1.1.16! root      402:        SCSI_DEV *dev = &ctr->devs[ctr->target];
1.1.1.14  root      403:        Uint32 nDmaAddr = FDC_GetDMAAddress();
                    404: 
1.1.1.16! root      405:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: READ CAPACITY (%s) to 0x%x.\n",
        !           406:                  HDC_CmdInfoStr(ctr), nDmaAddr);
1.1.1.14  root      407: 
                    408:        /* seek to the position */
                    409:        if (STMemory_ValidArea(nDmaAddr, 8))
                    410:        {
1.1.1.16! root      411:                int nSectors = dev->hdSize - 1;
1.1.1.14  root      412:                STRam[nDmaAddr++] = (nSectors >> 24) & 0xFF;
                    413:                STRam[nDmaAddr++] = (nSectors >> 16) & 0xFF;
                    414:                STRam[nDmaAddr++] = (nSectors >> 8) & 0xFF;
                    415:                STRam[nDmaAddr++] = (nSectors) & 0xFF;
                    416:                STRam[nDmaAddr++] = 0x00;
                    417:                STRam[nDmaAddr++] = 0x00;
                    418:                STRam[nDmaAddr++] = 0x02;
                    419:                STRam[nDmaAddr++] = 0x00;
                    420: 
                    421:                /* Update DMA counter */
1.1.1.16! root      422:                FDC_WriteDMAAddress(nDmaAddr);
1.1.1.14  root      423: 
1.1.1.16! root      424:                ctr->returnCode = HD_STATUS_OK;
        !           425:                dev->nLastError = HD_REQSENS_OK;
1.1.1.14  root      426:        }
                    427:        else
                    428:        {
                    429:                Log_Printf(LOG_WARN, "HDC capacity read uses invalid RAM range 0x%x+%i\n", nDmaAddr, 8);
1.1.1.16! root      430:                ctr->bDmaError = true;
        !           431:                ctr->returnCode = HD_STATUS_ERROR;
        !           432:                dev->nLastError = HD_REQSENS_NOSECTOR;
1.1.1.14  root      433:        }
                    434: 
1.1.1.16! root      435:        dev->bSetLastBlockAddr = false;
1.1.1.14  root      436: }
                    437: 
1.1.1.7   root      438: 
1.1.1.8   root      439: /**
                    440:  * Write a sector off our disk - (seek implied)
                    441:  */
1.1.1.16! root      442: static void HDC_Cmd_WriteSector(SCSI_CTRLR *ctr)
1.1       root      443: {
1.1.1.16! root      444:        SCSI_DEV *dev = &ctr->devs[ctr->target];
        !           445:        Uint32 nDmaAddr = FDC_GetDMAAddress();
1.1.1.11  root      446:        int n = 0;
                    447: 
1.1.1.16! root      448:        dev->nLastBlockAddr = HDC_GetLBA(ctr);
        !           449: 
        !           450:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: WRITE SECTOR (%s) with LBA 0x%x from 0x%x.\n",
        !           451:                  HDC_CmdInfoStr(ctr), dev->nLastBlockAddr, nDmaAddr);
1.1       root      452: 
1.1.1.7   root      453:        /* seek to the position */
1.1.1.16! root      454:        if (dev->nLastBlockAddr >= dev->hdSize ||
        !           455:            fseeko(dev->image_file, (off_t)dev->nLastBlockAddr * 512L, SEEK_SET) != 0)
1.1.1.7   root      456:        {
1.1.1.16! root      457:                ctr->returnCode = HD_STATUS_ERROR;
        !           458:                dev->nLastError = HD_REQSENS_INVADDR;
1.1.1.7   root      459:        }
                    460:        else
                    461:        {
                    462:                /* write - if allowed */
1.1       root      463: #ifndef DISALLOW_HDC_WRITE
1.1.1.16! root      464:                if (STMemory_ValidArea(nDmaAddr, 512 * HDC_GetCount(ctr)))
1.1.1.13  root      465:                {
                    466:                        n = fwrite(&STRam[nDmaAddr], 512,
1.1.1.16! root      467:                                   HDC_GetCount(ctr), dev->image_file);
1.1.1.13  root      468:                }
                    469:                else
                    470:                {
                    471:                        Log_Printf(LOG_WARN, "HDC sector write uses invalid RAM range 0x%x+%i\n",
1.1.1.16! root      472:                                   nDmaAddr, 512 * HDC_GetCount(ctr));
        !           473:                        ctr->bDmaError = true;
1.1.1.13  root      474:                }
1.1       root      475: #endif
1.1.1.16! root      476:                if (n == HDC_GetCount(ctr))
1.1.1.11  root      477:                {
1.1.1.16! root      478:                        ctr->returnCode = HD_STATUS_OK;
        !           479:                        dev->nLastError = HD_REQSENS_OK;
1.1.1.11  root      480:                }
                    481:                else
                    482:                {
1.1.1.16! root      483:                        ctr->returnCode = HD_STATUS_ERROR;
        !           484:                        dev->nLastError = HD_REQSENS_WRITEERR;
1.1.1.11  root      485:                }
                    486: 
1.1.1.9   root      487:                /* Update DMA counter */
1.1.1.13  root      488:                FDC_WriteDMAAddress(nDmaAddr + 512*n);
1.1.1.7   root      489:        }
1.1       root      490: 
1.1.1.16! root      491:        dev->bSetLastBlockAddr = true;
1.1       root      492: }
                    493: 
1.1.1.7   root      494: 
1.1.1.8   root      495: /**
                    496:  * Read a sector off our disk - (implied seek)
                    497:  */
1.1.1.16! root      498: static void HDC_Cmd_ReadSector(SCSI_CTRLR *ctr)
1.1       root      499: {
1.1.1.16! root      500:        SCSI_DEV *dev = &ctr->devs[ctr->target];
        !           501:        Uint32 nDmaAddr = FDC_GetDMAAddress();
1.1.1.11  root      502:        int n;
                    503: 
1.1.1.16! root      504:        dev->nLastBlockAddr = HDC_GetLBA(ctr);
1.1       root      505: 
1.1.1.16! root      506:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: READ SECTOR (%s) with LBA 0x%x to 0x%x.\n",
        !           507:                  HDC_CmdInfoStr(ctr), dev->nLastBlockAddr, nDmaAddr);
1.1       root      508: 
1.1.1.7   root      509:        /* seek to the position */
1.1.1.16! root      510:        if (dev->nLastBlockAddr >= dev->hdSize ||
        !           511:            fseeko(dev->image_file, (off_t)dev->nLastBlockAddr * 512L, SEEK_SET) != 0)
1.1.1.7   root      512:        {
1.1.1.16! root      513:                ctr->returnCode = HD_STATUS_ERROR;
        !           514:                dev->nLastError = HD_REQSENS_INVADDR;
1.1.1.7   root      515:        }
                    516:        else
                    517:        {
1.1.1.16! root      518:                if (STMemory_ValidArea(nDmaAddr, 512 * HDC_GetCount(ctr)))
1.1.1.13  root      519:                {
                    520:                        n = fread(&STRam[nDmaAddr], 512,
1.1.1.16! root      521:                                   HDC_GetCount(ctr), dev->image_file);
1.1.1.13  root      522:                }
                    523:                else
                    524:                {
                    525:                        Log_Printf(LOG_WARN, "HDC sector read uses invalid RAM range 0x%x+%i\n",
1.1.1.16! root      526:                                   nDmaAddr, 512 * HDC_GetCount(ctr));
        !           527:                        ctr->bDmaError = true;
1.1.1.13  root      528:                        n = 0;
                    529:                }
1.1.1.16! root      530:                if (n == HDC_GetCount(ctr))
1.1.1.11  root      531:                {
1.1.1.16! root      532:                        ctr->returnCode = HD_STATUS_OK;
        !           533:                        dev->nLastError = HD_REQSENS_OK;
1.1.1.11  root      534:                }
                    535:                else
                    536:                {
1.1.1.16! root      537:                        ctr->returnCode = HD_STATUS_ERROR;
        !           538:                        dev->nLastError = HD_REQSENS_NOSECTOR;
1.1.1.11  root      539:                }
1.1.1.9   root      540: 
                    541:                /* Update DMA counter */
1.1.1.13  root      542:                FDC_WriteDMAAddress(nDmaAddr + 512*n);
1.1.1.7   root      543:        }
1.1       root      544: 
1.1.1.16! root      545:        dev->bSetLastBlockAddr = true;
1.1       root      546: }
                    547: 
1.1.1.7   root      548: 
1.1.1.8   root      549: /**
1.1.1.12  root      550:  * Test unit ready
                    551:  */
1.1.1.16! root      552: static void HDC_Cmd_TestUnitReady(SCSI_CTRLR *ctr)
1.1.1.12  root      553: {
1.1.1.16! root      554:        LOG_TRACE(TRACE_SCSI_CMD, "HDC: TEST UNIT READY (%s).\n", HDC_CmdInfoStr(ctr));
        !           555:        ctr->returnCode = HD_STATUS_OK;
1.1.1.12  root      556: }
                    557: 
                    558: 
                    559: /**
1.1.1.8   root      560:  * Emulation routine for HDC command packets.
                    561:  */
1.1.1.16! root      562: static void HDC_EmulateCommandPacket(SCSI_CTRLR *ctr)
1.1       root      563: {
1.1.1.16! root      564:        SCSI_DEV *dev = &ctr->devs[ctr->target];
1.1       root      565: 
1.1.1.16! root      566:        switch (ctr->opcode)
1.1.1.7   root      567:        {
1.1.1.12  root      568:         case HD_TEST_UNIT_RDY:
1.1.1.16! root      569:                HDC_Cmd_TestUnitReady(ctr);
1.1.1.12  root      570:                break;
                    571: 
1.1.1.16! root      572:         case HD_READ_CAPACITY1:
        !           573:                HDC_Cmd_ReadCapacity(ctr);
1.1.1.14  root      574:                break;
                    575: 
1.1.1.7   root      576:         case HD_READ_SECTOR:
1.1.1.14  root      577:         case HD_READ_SECTOR1:
1.1.1.16! root      578:                HDC_Cmd_ReadSector(ctr);
1.1.1.7   root      579:                break;
1.1.1.14  root      580: 
1.1.1.7   root      581:         case HD_WRITE_SECTOR:
1.1.1.14  root      582:         case HD_WRITE_SECTOR1:
1.1.1.16! root      583:                HDC_Cmd_WriteSector(ctr);
1.1.1.7   root      584:                break;
                    585: 
                    586:         case HD_INQUIRY:
1.1.1.16! root      587:                HDC_Cmd_Inquiry(ctr);
1.1.1.7   root      588:                break;
                    589: 
                    590:         case HD_SEEK:
1.1.1.16! root      591:                HDC_Cmd_Seek(ctr);
1.1.1.7   root      592:                break;
                    593: 
                    594:         case HD_SHIP:
1.1.1.16! root      595:                LOG_TRACE(TRACE_SCSI_CMD, "HDC: SHIP (%s).\n", HDC_CmdInfoStr(ctr));
        !           596:                ctr->returnCode = 0xFF;
1.1.1.7   root      597:                break;
                    598: 
                    599:         case HD_REQ_SENSE:
1.1.1.16! root      600:                HDC_Cmd_RequestSense(ctr);
1.1.1.7   root      601:                break;
                    602: 
                    603:         case HD_MODESELECT:
1.1.1.16! root      604:                LOG_TRACE(TRACE_SCSI_CMD, "HDC: MODE SELECT (%s) TODO!\n", HDC_CmdInfoStr(ctr));
        !           605:                ctr->returnCode = HD_STATUS_OK;
        !           606:                dev->nLastError = HD_REQSENS_OK;
        !           607:                dev->bSetLastBlockAddr = false;
1.1.1.7   root      608:                break;
                    609: 
                    610:         case HD_MODESENSE:
1.1.1.16! root      611:                HDC_Cmd_ModeSense(ctr);
1.1.1.7   root      612:                break;
                    613: 
                    614:         case HD_FORMAT_DRIVE:
1.1.1.16! root      615:                HDC_Cmd_FormatDrive(ctr);
1.1.1.7   root      616:                break;
                    617: 
                    618:         /* as of yet unsupported commands */
                    619:         case HD_VERIFY_TRACK:
                    620:         case HD_FORMAT_TRACK:
                    621:         case HD_CORRECTION:
                    622: 
                    623:         default:
1.1.1.16! root      624:                LOG_TRACE(TRACE_SCSI_CMD, "HDC: Unsupported command (%s)!\n", HDC_CmdInfoStr(ctr));
        !           625:                ctr->returnCode = HD_STATUS_ERROR;
        !           626:                dev->nLastError = HD_REQSENS_OPCODE;
        !           627:                dev->bSetLastBlockAddr = false;
1.1.1.7   root      628:                break;
                    629:        }
1.1.1.9   root      630: 
                    631:        /* Update the led each time a command is processed */
1.1.1.15  root      632:        Statusbar_EnableHDLed( LED_STATE_ON );
1.1       root      633: }
                    634: 
1.1.1.7   root      635: 
1.1       root      636: /*---------------------------------------------------------------------*/
1.1.1.8   root      637: /**
                    638:  * Print data about the hard drive image
                    639:  */
1.1.1.16! root      640: static void HDC_GetInfo(SCSI_DEV *dev)
1.1       root      641: {
1.1.1.7   root      642: /* Partition table contains hd size + 4 partition entries
                    643:  * (composed of flag byte, 3 char ID, start offset and size),
                    644:  * this is followed by bad sector list + count and the root sector checksum.
                    645:  * Before this there's the boot code and with ICD hd driver additional 8
                    646:  * partition entries (at offset 0x156).
                    647:  */
                    648: #define HD_PARTITIONTABLE_SIZE (4+4*12)
                    649: #define HD_PARTITIONTABLE_OFFSET 0x1C2
                    650:        long offset;
                    651:        unsigned char hdinfo[HD_PARTITIONTABLE_SIZE];
                    652:        int i;
1.1       root      653: 
1.1.1.16! root      654:        if (dev->image_file == NULL)
1.1.1.7   root      655:                return;
1.1.1.16! root      656:        offset = ftell(dev->image_file);
1.1.1.7   root      657: 
1.1.1.16! root      658:        fseek(dev->image_file, HD_PARTITIONTABLE_OFFSET, 0);
        !           659:        if (fread(hdinfo, HD_PARTITIONTABLE_SIZE, 1, dev->image_file) != 1)
1.1.1.11  root      660:        {
                    661:                perror("HDC_GetInfo");
                    662:                return;
                    663:        }
1.1       root      664: 
1.1.1.14  root      665: #ifdef HDC_VERBOSE
1.1.1.16! root      666:        fprintf(stderr, "Total disk size according to MBR: %i Mb\n",
        !           667:                HDC_ReadInt32(hdinfo, 0) >> 11);
1.1.1.7   root      668:        /* flags for each partition entry are zero if they are not valid */
                    669:        fprintf(stderr, "Partition 0 exists?: %s\n", (hdinfo[4] != 0)?"Yes":"No");
                    670:        fprintf(stderr, "Partition 1 exists?: %s\n", (hdinfo[4+12] != 0)?"Yes":"No");
                    671:        fprintf(stderr, "Partition 2 exists?: %s\n", (hdinfo[4+24] != 0)?"Yes":"No");
                    672:        fprintf(stderr, "Partition 3 exists?: %s\n", (hdinfo[4+36] != 0)?"Yes":"No");
1.1       root      673: #endif
                    674: 
1.1.1.7   root      675:        for(i=0;i<4;i++)
                    676:                if(hdinfo[4 + 12*i])
                    677:                        nPartitions++;
1.1       root      678: 
1.1.1.16! root      679:        fseek(dev->image_file, offset, 0);
1.1       root      680: }
                    681: 
1.1.1.7   root      682: 
1.1.1.8   root      683: /**
                    684:  * Open the disk image file, set partitions.
1.1       root      685:  */
1.1.1.12  root      686: bool HDC_Init(void)
1.1       root      687: {
1.1.1.16! root      688:        off_t filesize;
        !           689:        int i;
1.1       root      690: 
1.1.1.16! root      691:        memset(&AcsiBus, 0, sizeof(AcsiBus));
        !           692:        nPartitions = 0;
        !           693:        bAcsiEmuOn = false;
1.1.1.12  root      694: 
1.1.1.16! root      695:        for (i = 0; i < MAX_ACSI_DEVS; i++)
1.1.1.7   root      696:        {
1.1.1.16! root      697:                char *filename;
1.1.1.3   root      698: 
1.1.1.16! root      699:                if (!ConfigureParams.Acsi[i].bUseDevice)
        !           700:                        continue;
        !           701:                filename = ConfigureParams.Acsi[i].sDeviceFile;
        !           702: 
        !           703:                /* Check size for sanity - is the length a multiple of 512? */
        !           704:                filesize = File_Length(filename);
        !           705:                if (filesize <= 0 || (filesize & 0x1ff) != 0)
        !           706:                {
        !           707:                        Log_Printf(LOG_ERROR, "HD file '%s' has strange size!\n",
        !           708:                                   filename);
        !           709:                        continue;
        !           710:                }
        !           711:                AcsiBus.devs[i].hdSize = filesize / 512;
        !           712: 
        !           713:                AcsiBus.devs[i].image_file = fopen(filename, "rb+");
        !           714:                if (AcsiBus.devs[i].image_file == NULL)
        !           715:                {
        !           716:                        Log_Printf(LOG_ERROR, "Can not open HD file '%s'!\n",
        !           717:                                   filename);
        !           718:                        continue;
        !           719:                }
1.1.1.7   root      720: 
1.1.1.16! root      721:                HDC_GetInfo(&AcsiBus.devs[i]);
        !           722:                Log_Printf(LOG_INFO, "Hard drive image %s mounted.\n", filename);
        !           723:                AcsiBus.devs[i].enabled = true;
        !           724:                bAcsiEmuOn = true;
        !           725:        }
1.1.1.7   root      726: 
                    727:        /* set number of partitions */
                    728:        nNumDrives += nPartitions;
                    729: 
1.1.1.16! root      730:        return bAcsiEmuOn;
1.1       root      731: }
1.1.1.3   root      732: 
1.1.1.7   root      733: 
1.1       root      734: /*---------------------------------------------------------------------*/
1.1.1.8   root      735: /**
                    736:  * HDC_UnInit - close image file
                    737:  *
1.1       root      738:  */
1.1.1.4   root      739: void HDC_UnInit(void)
1.1       root      740: {
1.1.1.16! root      741:        int i;
        !           742: 
1.1.1.7   root      743:        if (!bAcsiEmuOn)
                    744:                return;
                    745: 
1.1.1.16! root      746:        for (i = 0; i < MAX_ACSI_DEVS; i++)
        !           747:        {
        !           748:                if (!AcsiBus.devs[i].enabled)
        !           749:                        continue;
        !           750:                fclose(AcsiBus.devs[i].image_file);
        !           751:                AcsiBus.devs[i].image_file = NULL;
        !           752:                AcsiBus.devs[i].enabled = false;
        !           753:        }
1.1.1.7   root      754: 
                    755:        nNumDrives -= nPartitions;
                    756:        nPartitions = 0;
1.1.1.11  root      757:        bAcsiEmuOn = false;
1.1       root      758: }
                    759: 
1.1.1.7   root      760: 
1.1       root      761: /*---------------------------------------------------------------------*/
1.1.1.8   root      762: /**
1.1.1.14  root      763:  * Reset command status.
                    764:  */
                    765: void HDC_ResetCommandStatus(void)
                    766: {
1.1.1.16! root      767:        if (ConfigureParams.System.nMachineType != MACHINE_FALCON)
        !           768:                AcsiBus.returnCode = 0;
1.1.1.14  root      769: }
                    770: 
                    771: 
                    772: /**
1.1.1.16! root      773:  * Process HDC command packets (SCSI/ACSI) bytes.
1.1.1.14  root      774:  */
1.1.1.16! root      775: static void HDC_WriteCommandPacket(SCSI_CTRLR *ctr, Uint8 b)
1.1.1.14  root      776: {
1.1.1.16! root      777:        SCSI_DEV *dev = &ctr->devs[ctr->target];
        !           778: 
        !           779:        /* Abort if the target device is not enabled */
        !           780:        if (!dev->enabled)
        !           781:        {
        !           782:                ctr->returnCode = HD_STATUS_ERROR;
        !           783:                return;
        !           784:        }
        !           785: 
        !           786:        /* Extract ACSI/SCSI opcode */
        !           787:        if (ctr->byteCount == 0)
        !           788:        {
        !           789:                ctr->opcode = b;
        !           790:                ctr->bDmaError = false;
        !           791:        }
1.1.1.14  root      792: 
1.1.1.16! root      793:        /* Successfully received one byte, and increase the byte-count */
        !           794:        if (ctr->byteCount < (int)sizeof(ctr->command))
        !           795:                ctr->command[ctr->byteCount] = b;
        !           796:        ++ctr->byteCount;
        !           797: 
        !           798:        /* have we received a complete 6-byte class 0 or 10-byte class 1 packet yet? */
        !           799:        if ((ctr->opcode < 0x20 && ctr->byteCount >= 6) ||
        !           800:            (ctr->opcode < 0x60 && ctr->byteCount >= 10))
        !           801:        {
        !           802:                /* We currently only support LUN 0, however INQUIRY must
        !           803:                 * always be handled, see SCSI standard */
        !           804:                if (HDC_GetLUN(ctr) == 0 || ctr->opcode == HD_INQUIRY)
        !           805:                {
        !           806:                        HDC_EmulateCommandPacket(ctr);
        !           807:                }
        !           808:                else
        !           809:                {
        !           810:                        Log_Printf(LOG_WARN, "HDC: Access to non-existing LUN."
        !           811:                                   " Command = 0x%02x\n", ctr->opcode);
        !           812:                        dev->nLastError = HD_REQSENS_INVLUN;
        !           813:                        /* REQUEST SENSE is still handled for invalid LUNs */
        !           814:                        if (ctr->opcode == HD_REQ_SENSE)
        !           815:                                HDC_Cmd_RequestSense(ctr);
        !           816:                        else
        !           817:                                ctr->returnCode = HD_STATUS_ERROR;
        !           818:                }
        !           819: 
        !           820:                ctr->byteCount = 0;
        !           821:        }
        !           822:        else if (ctr->opcode >= 0x60)
        !           823:        {
        !           824:                /* Commands >= 0x60 are not supported right now */
        !           825:                ctr->returnCode = HD_STATUS_ERROR;
        !           826:                dev->nLastError = HD_REQSENS_OPCODE;
        !           827:                dev->bSetLastBlockAddr = false;
        !           828:                if (ctr->byteCount == 10)
        !           829:                {
        !           830:                        LOG_TRACE(TRACE_SCSI_CMD, "HDC: Unsupported command (%s).\n",
        !           831:                                  HDC_CmdInfoStr(ctr));
        !           832:                }
        !           833:        }
        !           834:        else
        !           835:        {
        !           836:                ctr->returnCode = HD_STATUS_OK;
        !           837:        }
        !           838: }
1.1.1.14  root      839: 
                    840: /*---------------------------------------------------------------------*/
1.1.1.16! root      841: 
        !           842: static struct ncr5380_regs
        !           843: {
        !           844:        Uint8 initiator_cmd;
        !           845:        Uint8 current_bus_status;
        !           846:        Uint8 bus_and_status;
        !           847: } ncr_regs;
        !           848: 
1.1.1.14  root      849: /**
1.1.1.16! root      850:  * Emulate external reset "pin": Clear registers etc.
1.1.1.14  root      851:  */
1.1.1.16! root      852: void Ncr5380_Reset(void)
1.1.1.14  root      853: {
1.1.1.16! root      854:        ncr_regs.initiator_cmd &= 0x7f;
1.1.1.14  root      855: }
                    856: 
                    857: /**
1.1.1.16! root      858:  * Write a command byte to the NCR 5380 SCSI controller
1.1.1.8   root      859:  */
1.1.1.16! root      860: static void Ncr5380_WriteByte(int addr, Uint8 byte)
1.1       root      861: {
1.1.1.16! root      862:        switch (addr)
1.1.1.14  root      863:        {
1.1.1.16! root      864:        case 0:                 /* Output Data register */
        !           865:                ncr_regs.current_bus_status |= 0x40;
        !           866:                break;
        !           867:        case 1:                 /* Initiator Command register */
        !           868:                ncr_regs.initiator_cmd = byte;
        !           869:                break;
        !           870:        case 2:                 /* Mode register */
        !           871:                break;
        !           872:        case 3:                 /* Target Command register */
        !           873:                break;
        !           874:        case 4:                 /* Select Enable register */
        !           875:                break;
        !           876:        case 5:                 /* Start DMA Send register */
        !           877:                break;
        !           878:        case 6:                 /* Start DMA Target Receive register */
        !           879:                break;
        !           880:        case 7:                 /* Start DMA Initiator Receive register */
        !           881:                break;
        !           882:        default:
        !           883:                fprintf(stderr, "Unexpected NCR5380 address\n");
1.1.1.14  root      884:        }
1.1.1.16! root      885: }
1.1.1.12  root      886: 
1.1.1.16! root      887: /**
        !           888:  * Read a command byte from the NCR 5380 SCSI controller
        !           889:  */
        !           890: static Uint8 Ncr5380_ReadByte(int addr)
        !           891: {
        !           892:        switch (addr)
1.1.1.12  root      893:        {
1.1.1.16! root      894:        case 0:                 /* Current SCSI Data register */
        !           895:                break;
        !           896:        case 1:                 /* Initiator Command register */
        !           897:                return ncr_regs.initiator_cmd & 0x9f;
        !           898:        case 2:                 /* Mode register */
        !           899:                break;
        !           900:        case 3:                 /* Target Command register */
        !           901:                break;
        !           902:        case 4:                 /* Current SCSI Bus Status register */
        !           903:                if (ncr_regs.current_bus_status & 0x40) /* BUSY? */
        !           904:                        ncr_regs.current_bus_status |= 0x20;
        !           905:                else
        !           906:                        ncr_regs.current_bus_status &= ~0x20;
        !           907:                if (ncr_regs.initiator_cmd & 0x80)      /* ASSERT RST? */
        !           908:                        ncr_regs.current_bus_status |= 0x80;
        !           909:                else
        !           910:                        ncr_regs.current_bus_status &= ~0x80;
        !           911:                if (ncr_regs.initiator_cmd & 0x04)      /* ASSERT BUSY? */
        !           912:                        ncr_regs.current_bus_status |= 0x40;
        !           913:                else
        !           914:                        ncr_regs.current_bus_status &= ~0x40;
        !           915:                return ncr_regs.current_bus_status;
        !           916:        case 5:                 /* Bus and Status register */
        !           917:                return ncr_regs.bus_and_status;
        !           918:        case 6:                 /* Input Data register */
        !           919:                break;
        !           920:        case 7:                 /* Reset Parity/Interrupts register */
        !           921:                /* Reset PARITY ERROR, IRQ REQUEST and BUSY ERROR bits */
        !           922:                ncr_regs.bus_and_status &= 0xcb;
        !           923:                return 0;  /* TODO: Is this return value ok? */
        !           924:        default:
        !           925:                fprintf(stderr, "Unexpected NCR5380 address\n");
1.1.1.12  root      926:        }
                    927: 
1.1.1.16! root      928:        return 0;
        !           929: }
1.1.1.7   root      930: 
1.1.1.16! root      931: 
        !           932: static void Acsi_WriteCommandByte(int addr, Uint8 byte)
        !           933: {
        !           934:        /* When the A1 pin is pushed to 0, we want to start a new command */
        !           935:        if ((addr & 2) == 0)
1.1.1.7   root      936:        {
1.1.1.16! root      937:                AcsiBus.byteCount = 0;
        !           938:                AcsiBus.target = ((byte & 0xE0) >> 5);
        !           939:                /* Only process the first byte if it is not
        !           940:                 * an extended ICD command marker byte */
        !           941:                if ((byte & 0x1F) != 0x1F)
1.1.1.7   root      942:                {
1.1.1.16! root      943:                        HDC_WriteCommandPacket(&AcsiBus, byte & 0x1F);
1.1.1.7   root      944:                }
                    945:                else
                    946:                {
1.1.1.16! root      947:                        AcsiBus.returnCode = HD_STATUS_OK;
        !           948:                        AcsiBus.bDmaError = false;
1.1.1.7   root      949:                }
1.1.1.16! root      950:        }
        !           951:        else
        !           952:        {
        !           953:                /* Process normal command byte */
        !           954:                HDC_WriteCommandPacket(&AcsiBus, byte);
        !           955:        }
1.1.1.7   root      956: 
1.1.1.16! root      957:        if (AcsiBus.devs[AcsiBus.target].enabled)
        !           958:        {
        !           959:                FDC_SetDMAStatus(AcsiBus.bDmaError);    /* Mark DMA error */
        !           960:                FDC_SetIRQ(FDC_IRQ_SOURCE_HDC);
1.1.1.7   root      961:        }
                    962:        else
                    963:        {
1.1.1.16! root      964:                /* If there's no target, the interrupt line stays high */
        !           965:                MFP_GPIP |= 0x20;
1.1.1.7   root      966:        }
1.1       root      967: }
1.1.1.16! root      968: 
        !           969: /**
        !           970:  * Called when command bytes have been written to $FFFF8606 and
        !           971:  * the HDC (not the FDC) is selected.
        !           972:  */
        !           973: void HDC_WriteCommandByte(int addr, Uint8 byte)
        !           974: {
        !           975:        // fprintf(stderr, "HDC: Write cmd byte addr=%i, byte=%02x\n", addr, byte);
        !           976: 
        !           977:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
        !           978:                Ncr5380_WriteByte(addr, byte);
        !           979:        else if (bAcsiEmuOn)
        !           980:                Acsi_WriteCommandByte(addr, byte);
        !           981: }
        !           982: 
        !           983: /**
        !           984:  * Get command byte.
        !           985:  */
        !           986: short int HDC_ReadCommandByte(int addr)
        !           987: {
        !           988:        Uint16 ret;
        !           989:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
        !           990:                ret = Ncr5380_ReadByte(addr);
        !           991:        else
        !           992:                ret = AcsiBus.returnCode;       /* ACSI status */
        !           993:        return ret;
        !           994: }

unix.superglobalmegacorp.com

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