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

1.1       root        1: /*
1.1.1.3   root        2:   Hatari - hdc.c
1.1       root        3: 
1.1.1.3   root        4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   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.7   root       17: #include "log.h"
1.1       root       18: #include "memorySnapShot.h"
                     19: #include "mfp.h"
                     20: #include "stMemory.h"
1.1.1.6   root       21: #include "tos.h"
1.1.1.9   root       22: #include "statusbar.h"
                     23: 
1.1       root       24: 
                     25: /*
                     26:   ACSI emulation: 
                     27:   ACSI commands are six byte-packets sent to the
                     28:   hard drive controller (which is on the HD unit, not in the ST)
                     29: 
                     30:   While the hard drive is busy, DRQ is high, polling the DRQ during
                     31:   operation interrupts the current operation. The DRQ status can
                     32:   be polled non-destructively in GPIP.
1.1.1.7   root       33: 
1.1       root       34:   (For simplicity, the operation is finished immediatly,
                     35:   this is a potential bug, but I doubt it is significant,
                     36:   we just appear to have a very fast hard drive.)
                     37: 
                     38:   The ACSI command set is a subset of the SCSI standard.
                     39:   (for details, see the X3T9.2 SCSI draft documents
                     40:   from 1985, for an example of writing ACSI commands,
                     41:   see the TOS DMA boot code) 
                     42: */
                     43: 
1.1.1.7   root       44: // #define DISALLOW_HDC_WRITE
                     45: // #define HDC_VERBOSE           /* display operations */
                     46: // #define HDC_REALLY_VERBOSE    /* display command packets */
1.1       root       47: 
                     48: /* HDC globals */
                     49: HDCOMMAND HDCCommand;
                     50: int nPartitions = 0;
                     51: short int HDCSectorCount;
1.1.1.11  root       52: bool bAcsiEmuOn = false;
1.1.1.7   root       53: 
1.1.1.12! root       54: static FILE *hd_image_file = NULL;
1.1.1.7   root       55: static Uint32 nLastBlockAddr;
1.1.1.9   root       56: static bool bSetLastBlockAddr;
1.1.1.7   root       57: static Uint8 nLastError;
1.1       root       58: 
1.1.1.7   root       59: /*
1.1.1.4   root       60:   FDC registers used:
                     61:   - FDCSectorCountRegister
1.1.1.6   root       62:   - DiskControllerStatus_ff8604rd
1.1.1.4   root       63:   - DMAModeControl_ff8606wr
1.1       root       64: */
                     65: 
                     66: 
                     67: /* Our dummy INQUIRY response data */
1.1.1.7   root       68: static unsigned char inquiry_bytes[] =
1.1       root       69: {
1.1.1.7   root       70:        0,                /* device type 0 = direct access device */
                     71:        0,                /* device type qualifier (nonremovable) */
                     72:        1,                /* ANSI version */
                     73:        0,                /* reserved */
                     74:        26,               /* length of the following data */
                     75:        ' ', ' ', ' ',                         /* Vendor specific data */
1.1.1.12! root       76:        'H','a','t','a','r','i',' ',' ',       /* Vendor */
        !            77:        'E','m','u','l','a','t','e','d',       /* Model */
1.1.1.7   root       78:        ' ',' ',' ',' ',                       /* Revision */
                     79:        0,0,0,0,0,0,0,0,0,0                    /* ?? */
1.1       root       80: };
                     81: 
1.1.1.7   root       82: 
1.1       root       83: /*---------------------------------------------------------------------*/
1.1.1.8   root       84: /**
                     85:  * Return the file offset of the sector specified in the current
                     86:  * ACSI command block.
                     87:  */
1.1.1.4   root       88: static unsigned long HDC_GetOffset(void)
                     89: {
1.1.1.7   root       90:        unsigned long offset;
1.1       root       91: 
1.1.1.7   root       92:        /* construct the logical block adress */
                     93:        offset = ((HD_LBA_MSB(HDCCommand) << 16)
                     94:                  |  (HD_LBA_MID(HDCCommand)  << 8)
                     95:                  |  (HD_LBA_LSB(HDCCommand))) ;
                     96: 
                     97:        /* return value in bytes */
                     98:        return(offset * 512);
1.1       root       99: }
                    100: 
1.1.1.7   root      101: 
1.1       root      102: /*---------------------------------------------------------------------*/
1.1.1.8   root      103: /**
                    104:  * Seek - move to a sector
                    105:  */
1.1.1.7   root      106: static void HDC_Cmd_Seek(void)
1.1       root      107: {
1.1.1.7   root      108:        nLastBlockAddr = HDC_GetOffset();
1.1       root      109: 
1.1.1.7   root      110:        if (fseek(hd_image_file, nLastBlockAddr, SEEK_SET) == 0)
                    111:        {
                    112:                HDCCommand.returnCode = HD_STATUS_OK;
                    113:                nLastError = HD_REQSENS_OK;
                    114:        }
                    115:        else
                    116:        {
                    117:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    118:                nLastError = HD_REQSENS_INVADDR;
                    119:        }
1.1       root      120: 
1.1.1.11  root      121:        FDC_SetDMAStatus(false);              /* no DMA error */
1.1.1.7   root      122:        FDC_AcknowledgeInterrupt();
1.1.1.11  root      123:        bSetLastBlockAddr = true;
1.1.1.7   root      124:        //FDCSectorCountRegister = 0;
1.1       root      125: }
                    126: 
1.1.1.7   root      127: 
1.1       root      128: /*---------------------------------------------------------------------*/
1.1.1.8   root      129: /**
                    130:  * Inquiry - return some disk information
                    131:  */
1.1.1.7   root      132: static void HDC_Cmd_Inquiry(void)
                    133: {
1.1.1.12! root      134:        Uint32 nDmaAddr;
        !           135:        int count;
        !           136: 
        !           137:        nDmaAddr = FDC_ReadDMAAddress();
        !           138:        count = HD_SECTORCOUNT(HDCCommand);
        !           139: 
1.1.1.7   root      140: #ifdef HDC_VERBOSE
1.1.1.12! root      141:        fprintf(stderr,"HDC: Inquiry, %i bytes to 0x%x.\n", count, nDmaAddr);
1.1.1.7   root      142: #endif
                    143: 
1.1.1.12! root      144:        if (count > (int)sizeof(inquiry_bytes))
        !           145:                count = sizeof(inquiry_bytes);
        !           146: 
        !           147:        inquiry_bytes[4] = count - 8;
        !           148: 
        !           149:        memcpy(&STRam[nDmaAddr], inquiry_bytes, count);
        !           150:        FDC_WriteDMAAddress(nDmaAddr + count);
1.1.1.7   root      151: 
1.1.1.11  root      152:        FDC_SetDMAStatus(false);              /* no DMA error */
1.1.1.7   root      153:        FDC_AcknowledgeInterrupt();
                    154:        HDCCommand.returnCode = HD_STATUS_OK;
                    155:        nLastError = HD_REQSENS_OK;
1.1.1.11  root      156:        bSetLastBlockAddr = false;
1.1.1.7   root      157:        //FDCSectorCountRegister = 0;
                    158: }
                    159: 
                    160: 
                    161: /*---------------------------------------------------------------------*/
1.1.1.8   root      162: /**
                    163:  * Request sense - return some disk information
                    164:  */
1.1.1.7   root      165: static void HDC_Cmd_RequestSense(void)
1.1       root      166: {
1.1.1.7   root      167:        Uint32 nDmaAddr;
                    168:        int nRetLen;
                    169:        Uint8 retbuf[22];
                    170: 
                    171: #ifdef HDC_VERBOSE
                    172:        fprintf(stderr,"HDC: Request Sense.\n");
                    173: #endif
                    174: 
                    175:        nRetLen = HD_SECTORCOUNT(HDCCommand);
                    176: 
                    177:        if ((nRetLen < 4 && nRetLen != 0) || nRetLen > 22)
                    178:        {
1.1.1.9   root      179:                Log_Printf(LOG_WARN, "HDC: *** Strange REQUEST SENSE ***!\n");
1.1.1.7   root      180:        }
                    181: 
                    182:        /* Limit to sane length */
                    183:        if (nRetLen <= 0)
                    184:        {
                    185:                nRetLen = 4;
                    186:        }
                    187:        else if (nRetLen > 22)
                    188:        {
                    189:                nRetLen = 22;
                    190:        }
                    191: 
                    192:        nDmaAddr = FDC_ReadDMAAddress();
                    193: 
                    194:        memset(retbuf, 0, nRetLen);
                    195: 
                    196:        if (nRetLen <= 4)
                    197:        {
                    198:                retbuf[0] = nLastError;
                    199:                if (bSetLastBlockAddr)
                    200:                {
                    201:                        retbuf[0] |= 0x80;
                    202:                        retbuf[1] = nLastBlockAddr >> 16;
                    203:                        retbuf[2] = nLastBlockAddr >> 8;
                    204:                        retbuf[3] = nLastBlockAddr;
                    205:                }
                    206:        }
                    207:        else
                    208:        {
                    209:                retbuf[0] = 0x70;
                    210:                if (bSetLastBlockAddr)
                    211:                {
                    212:                        retbuf[0] |= 0x80;
                    213:                        retbuf[4] = nLastBlockAddr >> 16;
                    214:                        retbuf[5] = nLastBlockAddr >> 8;
                    215:                        retbuf[6] = nLastBlockAddr;
                    216:                }
                    217:                switch (nLastError)
                    218:                {
                    219:                 case HD_REQSENS_OK:  retbuf[2] = 0; break;
                    220:                 case HD_REQSENS_OPCODE:  retbuf[2] = 5; break;
                    221:                 case HD_REQSENS_INVADDR:  retbuf[2] = 5; break;
                    222:                 case HD_REQSENS_INVARG:  retbuf[2] = 5; break;
                    223:                 case HD_REQSENS_NODRIVE:  retbuf[2] = 2; break;
                    224:                 default: retbuf[2] = 4; break;
                    225:                }
                    226:                retbuf[7] = 14;
                    227:                retbuf[12] = nLastError;
                    228:                retbuf[19] = nLastBlockAddr >> 16;
                    229:                retbuf[20] = nLastBlockAddr >> 8;
                    230:                retbuf[21] = nLastBlockAddr;
                    231:        }
                    232: 
                    233:        /*
                    234:        fprintf(stderr,"*** Requested sense packet:\n");
                    235:        int i;
                    236:        for (i = 0; i<nRetLen; i++) fprintf(stderr,"%2x ",retbuf[i]);
                    237:        fprintf(stderr,"\n");
                    238:        */
                    239: 
                    240:        memcpy(&STRam[nDmaAddr], retbuf, nRetLen);
1.1.1.12! root      241:        FDC_WriteDMAAddress(nDmaAddr + nRetLen);
1.1.1.7   root      242: 
1.1.1.11  root      243:        FDC_SetDMAStatus(false);            /* no DMA error */
1.1.1.7   root      244:        FDC_AcknowledgeInterrupt();
                    245:        HDCCommand.returnCode = HD_STATUS_OK;
                    246:        //FDCSectorCountRegister = 0;
                    247: }
                    248: 
                    249: 
                    250: /*---------------------------------------------------------------------*/
1.1.1.8   root      251: /**
                    252:  * Mode sense - Get parameters from disk.
                    253:  * (Just enough to make the HDX tool from AHDI 5.0 happy)
                    254:  */
1.1.1.7   root      255: static void HDC_Cmd_ModeSense(void)
                    256: {
                    257:        Uint32 nDmaAddr;
                    258: 
                    259: #ifdef HDC_VERBOSE
                    260:        fprintf(stderr,"HDC: Mode Sense.\n");
                    261: #endif
                    262: 
                    263:        nDmaAddr = FDC_ReadDMAAddress();
                    264: 
                    265:        if (HDCCommand.command[2] == 0 && HD_SECTORCOUNT(HDCCommand) == 0x10)
                    266:        {
                    267:                size_t blocks;
                    268:                blocks = File_Length(ConfigureParams.HardDisk.szHardDiskImage) / 512;
                    269: 
                    270:                STRam[nDmaAddr+0] = 0;
                    271:                STRam[nDmaAddr+1] = 0;
                    272:                STRam[nDmaAddr+2] = 0;
                    273:                STRam[nDmaAddr+3] = 8;
                    274:                STRam[nDmaAddr+4] = 0;
                    275: 
                    276:                STRam[nDmaAddr+5] = blocks >> 16;  // Number of blocks, high (?)
                    277:                STRam[nDmaAddr+6] = blocks >> 8;   // Number of blocks, med (?)
                    278:                STRam[nDmaAddr+7] = blocks;        // Number of blocks, low (?)
                    279: 
                    280:                STRam[nDmaAddr+8] = 0;
                    281: 
                    282:                STRam[nDmaAddr+9] = 0;      // Block size in bytes, high
                    283:                STRam[nDmaAddr+10] = 2;     // Block size in bytes, med
                    284:                STRam[nDmaAddr+11] = 0;     // Block size in bytes, low
                    285: 
                    286:                STRam[nDmaAddr+12] = 0;
                    287:                STRam[nDmaAddr+13] = 0;
                    288:                STRam[nDmaAddr+14] = 0;
                    289:                STRam[nDmaAddr+15] = 0;
                    290: 
1.1.1.12! root      291:                FDC_WriteDMAAddress(nDmaAddr + 16);
        !           292: 
1.1.1.7   root      293:                HDCCommand.returnCode = HD_STATUS_OK;
                    294:                nLastError = HD_REQSENS_OK;
                    295:        }
                    296:        else
                    297:        {
1.1.1.9   root      298:                Log_Printf(LOG_TODO, "HDC: Unsupported MODE SENSE command\n");
1.1.1.7   root      299:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    300:                nLastError = HD_REQSENS_INVARG;
                    301:        }
                    302: 
1.1.1.11  root      303:        FDC_SetDMAStatus(false);            /* no DMA error */
1.1.1.7   root      304:        FDC_AcknowledgeInterrupt();
1.1.1.11  root      305:        bSetLastBlockAddr = false;
1.1.1.7   root      306:        //FDCSectorCountRegister = 0;
                    307: }
                    308: 
                    309: 
                    310: /*---------------------------------------------------------------------*/
1.1.1.8   root      311: /**
                    312:  * Format drive.
                    313:  */
1.1.1.7   root      314: static void HDC_Cmd_FormatDrive(void)
                    315: {
                    316: #ifdef HDC_VERBOSE
                    317:        fprintf(stderr,"HDC: Format drive!\n");
                    318: #endif
                    319: 
                    320:        /* Should erase the whole image file here... */
                    321: 
1.1.1.11  root      322:        FDC_SetDMAStatus(false);            /* no DMA error */
1.1.1.7   root      323:        FDC_AcknowledgeInterrupt();
                    324:        HDCCommand.returnCode = HD_STATUS_OK;
                    325:        nLastError = HD_REQSENS_OK;
1.1.1.11  root      326:        bSetLastBlockAddr = false;
1.1.1.7   root      327:        //FDCSectorCountRegister = 0;
1.1       root      328: }
                    329: 
1.1.1.7   root      330: 
1.1       root      331: /*---------------------------------------------------------------------*/
1.1.1.8   root      332: /**
                    333:  * Write a sector off our disk - (seek implied)
                    334:  */
1.1.1.7   root      335: static void HDC_Cmd_WriteSector(void)
1.1       root      336: {
1.1.1.11  root      337:        int n = 0;
                    338: 
1.1.1.7   root      339:        nLastBlockAddr = HDC_GetOffset();
1.1       root      340: 
1.1.1.7   root      341:        /* seek to the position */
                    342:        if (fseek(hd_image_file, nLastBlockAddr, SEEK_SET) != 0)
                    343:        {
                    344:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    345:                nLastError = HD_REQSENS_INVADDR;
                    346:        }
                    347:        else
                    348:        {
                    349:                /* write - if allowed */
1.1       root      350: #ifndef DISALLOW_HDC_WRITE
1.1.1.11  root      351:                n = fwrite(&STRam[FDC_ReadDMAAddress()], 512,
                    352:                           HD_SECTORCOUNT(HDCCommand), hd_image_file);
1.1       root      353: #endif
1.1.1.11  root      354:                if (n == HD_SECTORCOUNT(HDCCommand))
                    355:                {
                    356:                        HDCCommand.returnCode = HD_STATUS_OK;
                    357:                        nLastError = HD_REQSENS_OK;
                    358:                }
                    359:                else
                    360:                {
                    361:                        HDCCommand.returnCode = HD_STATUS_ERROR;
                    362:                        nLastError = HD_REQSENS_WRITEERR;
                    363:                }
                    364: 
1.1.1.9   root      365:                /* Update DMA counter */
1.1.1.11  root      366:                FDC_WriteDMAAddress(FDC_ReadDMAAddress() + 512*n);
1.1.1.7   root      367:        }
1.1       root      368: 
1.1.1.11  root      369:        FDC_SetDMAStatus(false);              /* no DMA error */
1.1.1.7   root      370:        FDC_AcknowledgeInterrupt();
1.1.1.11  root      371:        bSetLastBlockAddr = true;
1.1.1.7   root      372:        //FDCSectorCountRegister = 0;
1.1       root      373: }
                    374: 
1.1.1.7   root      375: 
1.1       root      376: /*---------------------------------------------------------------------*/
1.1.1.8   root      377: /**
                    378:  * Read a sector off our disk - (implied seek)
                    379:  */
1.1.1.7   root      380: static void HDC_Cmd_ReadSector(void)
1.1       root      381: {
1.1.1.11  root      382:        int n;
                    383: 
1.1.1.7   root      384:        nLastBlockAddr = HDC_GetOffset();
1.1       root      385: 
                    386: #ifdef HDC_VERBOSE
1.1.1.7   root      387:        fprintf(stderr,"Reading %i sectors from 0x%x to addr: 0x%x\n",
                    388:                HD_SECTORCOUNT(HDCCommand), nLastBlockAddr, FDC_ReadDMAAddress());
1.1       root      389: #endif
                    390: 
1.1.1.7   root      391:        /* seek to the position */
                    392:        if (fseek(hd_image_file, nLastBlockAddr, SEEK_SET) != 0)
                    393:        {
                    394:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    395:                nLastError = HD_REQSENS_INVADDR;
                    396:        }
                    397:        else
                    398:        {
1.1.1.11  root      399:                n = fread(&STRam[FDC_ReadDMAAddress()], 512,
                    400:                          HD_SECTORCOUNT(HDCCommand), hd_image_file);
                    401:                if (n == HD_SECTORCOUNT(HDCCommand))
                    402:                {
                    403:                        HDCCommand.returnCode = HD_STATUS_OK;
                    404:                        nLastError = HD_REQSENS_OK;
                    405:                }
                    406:                else
                    407:                {
                    408:                        HDCCommand.returnCode = HD_STATUS_ERROR;
                    409:                        nLastError = HD_REQSENS_NOSECTOR;
                    410:                }
1.1.1.9   root      411: 
                    412:                /* Update DMA counter */
1.1.1.11  root      413:                FDC_WriteDMAAddress(FDC_ReadDMAAddress() + 512*n);
1.1.1.7   root      414:        }
1.1       root      415: 
1.1.1.11  root      416:        FDC_SetDMAStatus(false);              /* no DMA error */
1.1.1.7   root      417:        FDC_AcknowledgeInterrupt();
1.1.1.11  root      418:        bSetLastBlockAddr = true;
1.1.1.7   root      419:        //FDCSectorCountRegister = 0;
1.1       root      420: }
                    421: 
1.1.1.7   root      422: 
1.1       root      423: /*---------------------------------------------------------------------*/
1.1.1.8   root      424: /**
1.1.1.12! root      425:  * Test unit ready
        !           426:  */
        !           427: static void HDC_Cmd_TestUnitReady(void)
        !           428: {
        !           429:        FDC_SetDMAStatus(false);            /* no DMA error */
        !           430:        FDC_AcknowledgeInterrupt();
        !           431:        HDCCommand.returnCode = HD_STATUS_OK;
        !           432: }
        !           433: 
        !           434: 
        !           435: /*---------------------------------------------------------------------*/
        !           436: /**
1.1.1.8   root      437:  * Emulation routine for HDC command packets.
                    438:  */
1.1.1.12! root      439: static void HDC_EmulateCommandPacket(void)
1.1       root      440: {
                    441: 
1.1.1.7   root      442:        switch(HD_OPCODE(HDCCommand))
                    443:        {
1.1       root      444: 
1.1.1.12! root      445:         case HD_TEST_UNIT_RDY:
        !           446:                HDC_Cmd_TestUnitReady();
        !           447:                break;
        !           448: 
1.1.1.7   root      449:         case HD_READ_SECTOR:
                    450:                HDC_Cmd_ReadSector();
                    451:                break;
                    452:         case HD_WRITE_SECTOR:
                    453:                HDC_Cmd_WriteSector();
                    454:                break;
                    455: 
                    456:         case HD_INQUIRY:
                    457:                HDC_Cmd_Inquiry();
                    458:                break;
                    459: 
                    460:         case HD_SEEK:
                    461:                HDC_Cmd_Seek();
                    462:                break;
                    463: 
                    464:         case HD_SHIP:
                    465:                HDCCommand.returnCode = 0xFF;
                    466:                FDC_AcknowledgeInterrupt();
                    467:                break;
                    468: 
                    469:         case HD_REQ_SENSE:
                    470:                HDC_Cmd_RequestSense();
                    471:                break;
                    472: 
                    473:         case HD_MODESELECT:
1.1.1.9   root      474:                Log_Printf(LOG_TODO, "HDC: MODE SELECT call not implemented yet.\n");
1.1.1.7   root      475:                HDCCommand.returnCode = HD_STATUS_OK;
                    476:                nLastError = HD_REQSENS_OK;
1.1.1.11  root      477:                bSetLastBlockAddr = false;
                    478:                FDC_SetDMAStatus(false);
1.1.1.7   root      479:                FDC_AcknowledgeInterrupt();
                    480:                break;
                    481: 
                    482:         case HD_MODESENSE:
                    483:                HDC_Cmd_ModeSense();
                    484:                break;
                    485: 
                    486:         case HD_FORMAT_DRIVE:
                    487:                HDC_Cmd_FormatDrive();
                    488:                break;
                    489: 
                    490:         /* as of yet unsupported commands */
                    491:         case HD_VERIFY_TRACK:
                    492:         case HD_FORMAT_TRACK:
                    493:         case HD_CORRECTION:
                    494: 
                    495:         default:
                    496:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    497:                nLastError = HD_REQSENS_OPCODE;
1.1.1.11  root      498:                bSetLastBlockAddr = false;
1.1.1.7   root      499:                FDC_AcknowledgeInterrupt();
                    500:                break;
                    501:        }
1.1.1.9   root      502: 
                    503:        /* Update the led each time a command is processed */
                    504:        Statusbar_EnableHDLed();
1.1       root      505: }
                    506: 
1.1.1.7   root      507: 
1.1       root      508: /*---------------------------------------------------------------------*/
1.1.1.8   root      509: /**
                    510:  * Debug routine for HDC command packets.
                    511:  */
1.1.1.7   root      512: #ifdef HDC_REALLY_VERBOSE
1.1.1.12! root      513: static void HDC_DebugCommandPacket(FILE *hdlogFile)
1.1       root      514: {
1.1.1.7   root      515:        int opcode;
                    516:        static const char *psComNames[] =
                    517:        {
                    518:                "TEST UNIT READY",
                    519:                "REZERO",
                    520:                "???",
                    521:                "REQUEST SENSE",
                    522:                "FORMAT DRIVE",
                    523:                "VERIFY TRACK (?)",
                    524:                "FORMAT TRACK (?)",
                    525:                "REASSIGN BLOCK",
                    526:                "READ SECTOR(S)",
                    527:                "???",
                    528:                "WRITE SECTOR(S)",
                    529:                "SEEK",
                    530:                "???",
                    531:                "CORRECTION",
                    532:                "???",
                    533:                "TRANSLATE",
                    534:                "SET ERROR THRESHOLD",  /* 0x10 */
                    535:                "USAGE COUNTERS",
                    536:                "INQUIRY",
                    537:                "WRITE DATA BUFFER",
                    538:                "READ DATA BUFFER",
                    539:                "MODE SELECT",
                    540:                "???",
                    541:                "???",
                    542:                "EXTENDED READ",
                    543:                "READ TOC",
                    544:                "MODE SENSE",
                    545:                "SHIP",
                    546:                "RECEIVE DIAGNOSTICS",
                    547:                "SEND DIAGNOSTICS"
                    548:        };
                    549: 
                    550:        opcode = HD_OPCODE(HDCCommand);
                    551: 
                    552:        fprintf(hdlogFile,"----\n");
                    553: 
                    554:        if (opcode >= 0 && opcode <= (int)(sizeof(psComNames)/sizeof(psComNames[0])))
                    555:        {
                    556:                fprintf(hdlogFile, "HDC opcode 0x%x : %s\n",opcode,psComNames[opcode]);
                    557:        }
                    558:        else
                    559:        {
                    560:                fprintf(hdlogFile, "Unknown HDC opcode!! Value = 0x%x\n", opcode);
                    561:        }
                    562: 
1.1.1.12! root      563:        fprintf(hdlogFile, "Target: %i\n", HD_TARGET(HDCCommand));
        !           564:        fprintf(hdlogFile, "Device: %i\n", HD_DEVICE(HDCCommand));
        !           565:        fprintf(hdlogFile, "LBA: 0x%lx\n", HDC_GetOffset()/512);
1.1.1.7   root      566: 
                    567:        fprintf(hdlogFile, "Sector count: 0x%x\n", HD_SECTORCOUNT(HDCCommand));
                    568:        fprintf(hdlogFile, "HDC sector count: 0x%x\n", HDCSectorCount);
                    569:        //fprintf(hdlogFile, "FDC sector count: 0x%x\n", FDCSectorCountRegister);
                    570:        fprintf(hdlogFile, "Control byte: 0x%x\n", HD_CONTROL(HDCCommand));
1.1       root      571: }
1.1.1.7   root      572: #endif
                    573: 
1.1       root      574: 
                    575: /*---------------------------------------------------------------------*/
1.1.1.8   root      576: /**
                    577:  * Print data about the hard drive image
                    578:  */
1.1.1.4   root      579: static void HDC_GetInfo(void)
1.1       root      580: {
1.1.1.7   root      581: /* Partition table contains hd size + 4 partition entries
                    582:  * (composed of flag byte, 3 char ID, start offset and size),
                    583:  * this is followed by bad sector list + count and the root sector checksum.
                    584:  * Before this there's the boot code and with ICD hd driver additional 8
                    585:  * partition entries (at offset 0x156).
                    586:  */
                    587: #define HD_PARTITIONTABLE_SIZE (4+4*12)
                    588: #define HD_PARTITIONTABLE_OFFSET 0x1C2
                    589:        long offset;
                    590:        unsigned char hdinfo[HD_PARTITIONTABLE_SIZE];
                    591:        int i;
1.1.1.2   root      592: #ifdef HDC_VERBOSE
1.1.1.7   root      593:        unsigned long size;
1.1.1.2   root      594: #endif
1.1       root      595: 
1.1.1.7   root      596:        nPartitions = 0;
                    597:        if (hd_image_file == NULL)
                    598:                return;
                    599:        offset = ftell(hd_image_file);
                    600: 
                    601:        fseek(hd_image_file, HD_PARTITIONTABLE_OFFSET, 0);
1.1.1.11  root      602:        if (fread(hdinfo, HD_PARTITIONTABLE_SIZE, 1, hd_image_file) != 1)
                    603:        {
                    604:                perror("HDC_GetInfo");
                    605:                return;
                    606:        }
1.1       root      607: 
                    608: #ifdef HDC_VERBOSE
1.1.1.7   root      609:        size = (((unsigned long) hdinfo[0] << 24)
                    610:                | ((unsigned long) hdinfo[1] << 16)
                    611:                | ((unsigned long) hdinfo[2] << 8)
                    612:                | ((unsigned long) hdinfo[3]));
                    613: 
                    614:        fprintf(stderr, "Total disk size %li Mb\n", size>>11);
                    615:        /* flags for each partition entry are zero if they are not valid */
                    616:        fprintf(stderr, "Partition 0 exists?: %s\n", (hdinfo[4] != 0)?"Yes":"No");
                    617:        fprintf(stderr, "Partition 1 exists?: %s\n", (hdinfo[4+12] != 0)?"Yes":"No");
                    618:        fprintf(stderr, "Partition 2 exists?: %s\n", (hdinfo[4+24] != 0)?"Yes":"No");
                    619:        fprintf(stderr, "Partition 3 exists?: %s\n", (hdinfo[4+36] != 0)?"Yes":"No");
1.1       root      620: #endif
                    621: 
1.1.1.7   root      622:        for(i=0;i<4;i++)
                    623:                if(hdinfo[4 + 12*i])
                    624:                        nPartitions++;
1.1       root      625: 
1.1.1.7   root      626:        fseek(hd_image_file, offset, 0);
1.1       root      627: }
                    628: 
1.1.1.7   root      629: 
1.1       root      630: /*---------------------------------------------------------------------*/
1.1.1.8   root      631: /**
                    632:  * Open the disk image file, set partitions.
1.1       root      633:  */
1.1.1.12! root      634: bool HDC_Init(void)
1.1       root      635: {
1.1.1.12! root      636:        char *filename;
1.1.1.11  root      637:        bAcsiEmuOn = false;
1.1       root      638: 
1.1.1.12! root      639:        if (!ConfigureParams.HardDisk.bUseHardDiskImage)
        !           640:                return false;
        !           641:        filename = ConfigureParams.HardDisk.szHardDiskImage;
        !           642: 
1.1.1.7   root      643:        /* Sanity check - is file length a multiple of 512? */
                    644:        if (File_Length(filename) & 0x1ff)
                    645:        {
                    646:                Log_Printf(LOG_ERROR, "HD file '%s' has strange size!\n", filename);
1.1.1.11  root      647:                return false;
1.1.1.7   root      648:        }
1.1.1.3   root      649: 
1.1.1.7   root      650:        if ((hd_image_file = fopen(filename, "rb+")) == NULL)
                    651:        {
                    652:                Log_Printf(LOG_ERROR, "Can not open HD file '%s'!\n", filename);
1.1.1.11  root      653:                return false;
1.1.1.7   root      654:        }
                    655: 
                    656:        HDC_GetInfo();
                    657: 
                    658:        /* set number of partitions */
                    659:        nNumDrives += nPartitions;
                    660: 
1.1.1.11  root      661:        bAcsiEmuOn = true;
1.1.1.12! root      662:        HDCCommand.byteCount = 0;
1.1.1.7   root      663: 
1.1.1.12! root      664:        printf("Hard drive image %s mounted.\n", filename);
1.1.1.11  root      665:        return true;
1.1       root      666: }
1.1.1.3   root      667: 
1.1.1.7   root      668: 
1.1       root      669: /*---------------------------------------------------------------------*/
1.1.1.8   root      670: /**
                    671:  * HDC_UnInit - close image file
                    672:  *
1.1       root      673:  */
1.1.1.4   root      674: void HDC_UnInit(void)
1.1       root      675: {
1.1.1.7   root      676:        if (!bAcsiEmuOn)
                    677:                return;
                    678: 
                    679:        fclose(hd_image_file);
                    680:        hd_image_file = NULL;
                    681: 
                    682:        nNumDrives -= nPartitions;
                    683:        nPartitions = 0;
1.1.1.11  root      684:        bAcsiEmuOn = false;
1.1       root      685: }
                    686: 
1.1.1.7   root      687: 
1.1       root      688: /*---------------------------------------------------------------------*/
1.1.1.8   root      689: /**
                    690:  * Process HDC command packets, called when bytes are 
                    691:  * written to $FFFF8606 and the HDC (not the FDC) is selected.
                    692:  */
1.1.1.4   root      693: void HDC_WriteCommandPacket(void)
1.1       root      694: {
1.1.1.7   root      695:        /* is HDC emulation enabled? */
                    696:        if (!bAcsiEmuOn)
                    697:                return;
                    698: 
                    699:        /* command byte sent, store it. */
1.1.1.12! root      700:        HDCCommand.command[HDCCommand.byteCount] = (DiskControllerWord_ff8604wr&0xFF);
        !           701: 
        !           702:        /* We only support one target with ID 0 */
        !           703:        if (HD_TARGET(HDCCommand) != 0)
        !           704:        {
        !           705:                //FDC_SetDMAStatus(true);
        !           706:                //FDC_AcknowledgeInterrupt();
        !           707:                //FDCSectorCountRegister = 0;
        !           708:                /* If there's no controller, the interrupt line stays high */
        !           709:                HDCCommand.returnCode = HD_STATUS_ERROR;
        !           710:                MFP_GPIP |= 0x20;
        !           711:                return;
        !           712:        }
        !           713: 
        !           714:        /* Successfully received one byte, so increase the byte-count */
        !           715:        ++HDCCommand.byteCount;
1.1.1.7   root      716: 
                    717:        /* have we received a complete 6-byte packet yet? */
                    718:        if (HDCCommand.byteCount >= 6)
                    719:        {
1.1       root      720: #ifdef HDC_REALLY_VERBOSE
1.1.1.7   root      721:                HDC_DebugCommandPacket(stderr);
1.1       root      722: #endif
1.1.1.7   root      723:                /* If it's aimed for our drive, emulate it! */
1.1.1.12! root      724:                if (HD_DEVICE(HDCCommand) == 0)
1.1.1.7   root      725:                {
1.1.1.12! root      726:                        HDC_EmulateCommandPacket();
1.1.1.7   root      727:                }
                    728:                else
                    729:                {
1.1.1.12! root      730:                        Log_Printf(LOG_WARN, "HDC: Access to non-existing drive.\n");
1.1.1.7   root      731:                        HDCCommand.returnCode = HD_STATUS_ERROR;
                    732:                }
                    733: 
                    734:                HDCCommand.byteCount = 0;
                    735:        }
                    736:        else
                    737:        {
1.1.1.12! root      738:                FDC_AcknowledgeInterrupt();
        !           739:                FDC_SetDMAStatus(false);
        !           740:                HDCCommand.returnCode = HD_STATUS_OK;
1.1.1.7   root      741:        }
1.1       root      742: }

unix.superglobalmegacorp.com

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