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

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: FILE *hd_image_file = NULL;
                     51: int nPartitions = 0;
                     52: short int HDCSectorCount;
1.1.1.11! root       53: bool bAcsiEmuOn = false;
1.1.1.7   root       54: 
                     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 */
                     76:        'H','a','t','a','r','i',' ','E',       /* Vendor */
                     77:        'm','u','l','a','t','e','d',' ',       /* Model */
                     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: {
                    134: #ifdef HDC_VERBOSE
                    135:                fprintf(stderr,"Inquiry made.\n");
                    136: #endif
                    137: 
                    138:        inquiry_bytes[4] = HD_SECTORCOUNT(HDCCommand) - 8;
                    139:        memcpy(&STRam[FDC_ReadDMAAddress()], inquiry_bytes,
                    140:               HD_SECTORCOUNT(HDCCommand));
                    141: 
1.1.1.11! root      142:        FDC_SetDMAStatus(false);              /* no DMA error */
1.1.1.7   root      143:        FDC_AcknowledgeInterrupt();
                    144:        HDCCommand.returnCode = HD_STATUS_OK;
                    145:        nLastError = HD_REQSENS_OK;
1.1.1.11! root      146:        bSetLastBlockAddr = false;
1.1.1.7   root      147:        //FDCSectorCountRegister = 0;
                    148: }
                    149: 
                    150: 
                    151: /*---------------------------------------------------------------------*/
1.1.1.8   root      152: /**
                    153:  * Request sense - return some disk information
                    154:  */
1.1.1.7   root      155: static void HDC_Cmd_RequestSense(void)
1.1       root      156: {
1.1.1.7   root      157:        Uint32 nDmaAddr;
                    158:        int nRetLen;
                    159:        Uint8 retbuf[22];
                    160: 
                    161: #ifdef HDC_VERBOSE
                    162:        fprintf(stderr,"HDC: Request Sense.\n");
                    163: #endif
                    164: 
                    165:        nRetLen = HD_SECTORCOUNT(HDCCommand);
                    166: 
                    167:        if ((nRetLen < 4 && nRetLen != 0) || nRetLen > 22)
                    168:        {
1.1.1.9   root      169:                Log_Printf(LOG_WARN, "HDC: *** Strange REQUEST SENSE ***!\n");
1.1.1.7   root      170:        }
                    171: 
                    172:        /* Limit to sane length */
                    173:        if (nRetLen <= 0)
                    174:        {
                    175:                nRetLen = 4;
                    176:        }
                    177:        else if (nRetLen > 22)
                    178:        {
                    179:                nRetLen = 22;
                    180:        }
                    181: 
                    182:        nDmaAddr = FDC_ReadDMAAddress();
                    183: 
                    184:        memset(retbuf, 0, nRetLen);
                    185: 
                    186:        if (nRetLen <= 4)
                    187:        {
                    188:                retbuf[0] = nLastError;
                    189:                if (bSetLastBlockAddr)
                    190:                {
                    191:                        retbuf[0] |= 0x80;
                    192:                        retbuf[1] = nLastBlockAddr >> 16;
                    193:                        retbuf[2] = nLastBlockAddr >> 8;
                    194:                        retbuf[3] = nLastBlockAddr;
                    195:                }
                    196:        }
                    197:        else
                    198:        {
                    199:                retbuf[0] = 0x70;
                    200:                if (bSetLastBlockAddr)
                    201:                {
                    202:                        retbuf[0] |= 0x80;
                    203:                        retbuf[4] = nLastBlockAddr >> 16;
                    204:                        retbuf[5] = nLastBlockAddr >> 8;
                    205:                        retbuf[6] = nLastBlockAddr;
                    206:                }
                    207:                switch (nLastError)
                    208:                {
                    209:                 case HD_REQSENS_OK:  retbuf[2] = 0; break;
                    210:                 case HD_REQSENS_OPCODE:  retbuf[2] = 5; break;
                    211:                 case HD_REQSENS_INVADDR:  retbuf[2] = 5; break;
                    212:                 case HD_REQSENS_INVARG:  retbuf[2] = 5; break;
                    213:                 case HD_REQSENS_NODRIVE:  retbuf[2] = 2; break;
                    214:                 default: retbuf[2] = 4; break;
                    215:                }
                    216:                retbuf[7] = 14;
                    217:                retbuf[12] = nLastError;
                    218:                retbuf[19] = nLastBlockAddr >> 16;
                    219:                retbuf[20] = nLastBlockAddr >> 8;
                    220:                retbuf[21] = nLastBlockAddr;
                    221:        }
                    222: 
                    223:        /*
                    224:        fprintf(stderr,"*** Requested sense packet:\n");
                    225:        int i;
                    226:        for (i = 0; i<nRetLen; i++) fprintf(stderr,"%2x ",retbuf[i]);
                    227:        fprintf(stderr,"\n");
                    228:        */
                    229: 
                    230:        memcpy(&STRam[nDmaAddr], retbuf, nRetLen);
                    231: 
1.1.1.11! root      232:        FDC_SetDMAStatus(false);            /* no DMA error */
1.1.1.7   root      233:        FDC_AcknowledgeInterrupt();
                    234:        HDCCommand.returnCode = HD_STATUS_OK;
                    235:        //FDCSectorCountRegister = 0;
                    236: }
                    237: 
                    238: 
                    239: /*---------------------------------------------------------------------*/
1.1.1.8   root      240: /**
                    241:  * Mode sense - Get parameters from disk.
                    242:  * (Just enough to make the HDX tool from AHDI 5.0 happy)
                    243:  */
1.1.1.7   root      244: static void HDC_Cmd_ModeSense(void)
                    245: {
                    246:        Uint32 nDmaAddr;
                    247: 
                    248: #ifdef HDC_VERBOSE
                    249:        fprintf(stderr,"HDC: Mode Sense.\n");
                    250: #endif
                    251: 
                    252:        nDmaAddr = FDC_ReadDMAAddress();
                    253: 
                    254:        if (HDCCommand.command[2] == 0 && HD_SECTORCOUNT(HDCCommand) == 0x10)
                    255:        {
                    256:                size_t blocks;
                    257:                blocks = File_Length(ConfigureParams.HardDisk.szHardDiskImage) / 512;
                    258: 
                    259:                STRam[nDmaAddr+0] = 0;
                    260:                STRam[nDmaAddr+1] = 0;
                    261:                STRam[nDmaAddr+2] = 0;
                    262:                STRam[nDmaAddr+3] = 8;
                    263:                STRam[nDmaAddr+4] = 0;
                    264: 
                    265:                STRam[nDmaAddr+5] = blocks >> 16;  // Number of blocks, high (?)
                    266:                STRam[nDmaAddr+6] = blocks >> 8;   // Number of blocks, med (?)
                    267:                STRam[nDmaAddr+7] = blocks;        // Number of blocks, low (?)
                    268: 
                    269:                STRam[nDmaAddr+8] = 0;
                    270: 
                    271:                STRam[nDmaAddr+9] = 0;      // Block size in bytes, high
                    272:                STRam[nDmaAddr+10] = 2;     // Block size in bytes, med
                    273:                STRam[nDmaAddr+11] = 0;     // Block size in bytes, low
                    274: 
                    275:                STRam[nDmaAddr+12] = 0;
                    276:                STRam[nDmaAddr+13] = 0;
                    277:                STRam[nDmaAddr+14] = 0;
                    278:                STRam[nDmaAddr+15] = 0;
                    279: 
                    280:                HDCCommand.returnCode = HD_STATUS_OK;
                    281:                nLastError = HD_REQSENS_OK;
                    282:        }
                    283:        else
                    284:        {
1.1.1.9   root      285:                Log_Printf(LOG_TODO, "HDC: Unsupported MODE SENSE command\n");
1.1.1.7   root      286:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    287:                nLastError = HD_REQSENS_INVARG;
                    288:        }
                    289: 
1.1.1.11! root      290:        FDC_SetDMAStatus(false);            /* no DMA error */
1.1.1.7   root      291:        FDC_AcknowledgeInterrupt();
1.1.1.11! root      292:        bSetLastBlockAddr = false;
1.1.1.7   root      293:        //FDCSectorCountRegister = 0;
                    294: }
                    295: 
                    296: 
                    297: /*---------------------------------------------------------------------*/
1.1.1.8   root      298: /**
                    299:  * Format drive.
                    300:  */
1.1.1.7   root      301: static void HDC_Cmd_FormatDrive(void)
                    302: {
                    303: #ifdef HDC_VERBOSE
                    304:        fprintf(stderr,"HDC: Format drive!\n");
                    305: #endif
                    306: 
                    307:        /* Should erase the whole image file here... */
                    308: 
1.1.1.11! root      309:        FDC_SetDMAStatus(false);            /* no DMA error */
1.1.1.7   root      310:        FDC_AcknowledgeInterrupt();
                    311:        HDCCommand.returnCode = HD_STATUS_OK;
                    312:        nLastError = HD_REQSENS_OK;
1.1.1.11! root      313:        bSetLastBlockAddr = false;
1.1.1.7   root      314:        //FDCSectorCountRegister = 0;
1.1       root      315: }
                    316: 
1.1.1.7   root      317: 
1.1       root      318: /*---------------------------------------------------------------------*/
1.1.1.8   root      319: /**
                    320:  * Write a sector off our disk - (seek implied)
                    321:  */
1.1.1.7   root      322: static void HDC_Cmd_WriteSector(void)
1.1       root      323: {
1.1.1.11! root      324:        int n = 0;
        !           325: 
1.1.1.7   root      326:        nLastBlockAddr = HDC_GetOffset();
1.1       root      327: 
1.1.1.7   root      328:        /* seek to the position */
                    329:        if (fseek(hd_image_file, nLastBlockAddr, SEEK_SET) != 0)
                    330:        {
                    331:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    332:                nLastError = HD_REQSENS_INVADDR;
                    333:        }
                    334:        else
                    335:        {
                    336:                /* write - if allowed */
1.1       root      337: #ifndef DISALLOW_HDC_WRITE
1.1.1.11! root      338:                n = fwrite(&STRam[FDC_ReadDMAAddress()], 512,
        !           339:                           HD_SECTORCOUNT(HDCCommand), hd_image_file);
1.1       root      340: #endif
1.1.1.11! root      341:                if (n == HD_SECTORCOUNT(HDCCommand))
        !           342:                {
        !           343:                        HDCCommand.returnCode = HD_STATUS_OK;
        !           344:                        nLastError = HD_REQSENS_OK;
        !           345:                }
        !           346:                else
        !           347:                {
        !           348:                        HDCCommand.returnCode = HD_STATUS_ERROR;
        !           349:                        nLastError = HD_REQSENS_WRITEERR;
        !           350:                }
        !           351: 
1.1.1.9   root      352:                /* Update DMA counter */
1.1.1.11! root      353:                FDC_WriteDMAAddress(FDC_ReadDMAAddress() + 512*n);
1.1.1.7   root      354:        }
1.1       root      355: 
1.1.1.11! root      356:        FDC_SetDMAStatus(false);              /* no DMA error */
1.1.1.7   root      357:        FDC_AcknowledgeInterrupt();
1.1.1.11! root      358:        bSetLastBlockAddr = true;
1.1.1.7   root      359:        //FDCSectorCountRegister = 0;
1.1       root      360: }
                    361: 
1.1.1.7   root      362: 
1.1       root      363: /*---------------------------------------------------------------------*/
1.1.1.8   root      364: /**
                    365:  * Read a sector off our disk - (implied seek)
                    366:  */
1.1.1.7   root      367: static void HDC_Cmd_ReadSector(void)
1.1       root      368: {
1.1.1.11! root      369:        int n;
        !           370: 
1.1.1.7   root      371:        nLastBlockAddr = HDC_GetOffset();
1.1       root      372: 
                    373: #ifdef HDC_VERBOSE
1.1.1.7   root      374:        fprintf(stderr,"Reading %i sectors from 0x%x to addr: 0x%x\n",
                    375:                HD_SECTORCOUNT(HDCCommand), nLastBlockAddr, FDC_ReadDMAAddress());
1.1       root      376: #endif
                    377: 
1.1.1.7   root      378:        /* seek to the position */
                    379:        if (fseek(hd_image_file, nLastBlockAddr, SEEK_SET) != 0)
                    380:        {
                    381:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    382:                nLastError = HD_REQSENS_INVADDR;
                    383:        }
                    384:        else
                    385:        {
1.1.1.11! root      386:                n = fread(&STRam[FDC_ReadDMAAddress()], 512,
        !           387:                          HD_SECTORCOUNT(HDCCommand), hd_image_file);
        !           388:                if (n == HD_SECTORCOUNT(HDCCommand))
        !           389:                {
        !           390:                        HDCCommand.returnCode = HD_STATUS_OK;
        !           391:                        nLastError = HD_REQSENS_OK;
        !           392:                }
        !           393:                else
        !           394:                {
        !           395:                        HDCCommand.returnCode = HD_STATUS_ERROR;
        !           396:                        nLastError = HD_REQSENS_NOSECTOR;
        !           397:                }
1.1.1.9   root      398: 
                    399:                /* Update DMA counter */
1.1.1.11! root      400:                FDC_WriteDMAAddress(FDC_ReadDMAAddress() + 512*n);
1.1.1.7   root      401:        }
1.1       root      402: 
1.1.1.11! root      403:        FDC_SetDMAStatus(false);              /* no DMA error */
1.1.1.7   root      404:        FDC_AcknowledgeInterrupt();
1.1.1.11! root      405:        bSetLastBlockAddr = true;
1.1.1.7   root      406:        //FDCSectorCountRegister = 0;
1.1       root      407: }
                    408: 
1.1.1.7   root      409: 
1.1       root      410: /*---------------------------------------------------------------------*/
1.1.1.8   root      411: /**
                    412:  * Emulation routine for HDC command packets.
                    413:  */
1.1       root      414: void HDC_EmulateCommandPacket()
                    415: {
                    416: 
1.1.1.7   root      417:        switch(HD_OPCODE(HDCCommand))
                    418:        {
1.1       root      419: 
1.1.1.7   root      420:         case HD_READ_SECTOR:
                    421:                HDC_Cmd_ReadSector();
                    422:                break;
                    423:         case HD_WRITE_SECTOR:
                    424:                HDC_Cmd_WriteSector();
                    425:                break;
                    426: 
                    427:         case HD_INQUIRY:
                    428:                HDC_Cmd_Inquiry();
                    429:                break;
                    430: 
                    431:         case HD_SEEK:
                    432:                HDC_Cmd_Seek();
                    433:                break;
                    434: 
                    435:         case HD_SHIP:
                    436:                HDCCommand.returnCode = 0xFF;
                    437:                FDC_AcknowledgeInterrupt();
                    438:                break;
                    439: 
                    440:         case HD_REQ_SENSE:
                    441:                HDC_Cmd_RequestSense();
                    442:                break;
                    443: 
                    444:         case HD_MODESELECT:
1.1.1.9   root      445:                Log_Printf(LOG_TODO, "HDC: MODE SELECT call not implemented yet.\n");
1.1.1.7   root      446:                HDCCommand.returnCode = HD_STATUS_OK;
                    447:                nLastError = HD_REQSENS_OK;
1.1.1.11! root      448:                bSetLastBlockAddr = false;
        !           449:                FDC_SetDMAStatus(false);
1.1.1.7   root      450:                FDC_AcknowledgeInterrupt();
                    451:                break;
                    452: 
                    453:         case HD_MODESENSE:
                    454:                HDC_Cmd_ModeSense();
                    455:                break;
                    456: 
                    457:         case HD_FORMAT_DRIVE:
                    458:                HDC_Cmd_FormatDrive();
                    459:                break;
                    460: 
                    461:         /* as of yet unsupported commands */
                    462:         case HD_VERIFY_TRACK:
                    463:         case HD_FORMAT_TRACK:
                    464:         case HD_CORRECTION:
                    465: 
                    466:         default:
                    467:                HDCCommand.returnCode = HD_STATUS_ERROR;
                    468:                nLastError = HD_REQSENS_OPCODE;
1.1.1.11! root      469:                bSetLastBlockAddr = false;
1.1.1.7   root      470:                FDC_AcknowledgeInterrupt();
                    471:                break;
                    472:        }
1.1.1.9   root      473: 
                    474:        /* Update the led each time a command is processed */
                    475:        Statusbar_EnableHDLed();
1.1       root      476: }
                    477: 
1.1.1.7   root      478: 
1.1       root      479: /*---------------------------------------------------------------------*/
1.1.1.8   root      480: /**
                    481:  * Debug routine for HDC command packets.
                    482:  */
1.1.1.7   root      483: #ifdef HDC_REALLY_VERBOSE
1.1       root      484: void HDC_DebugCommandPacket(FILE *hdlogFile)
                    485: {
1.1.1.7   root      486:        int opcode;
                    487:        static const char *psComNames[] =
                    488:        {
                    489:                "TEST UNIT READY",
                    490:                "REZERO",
                    491:                "???",
                    492:                "REQUEST SENSE",
                    493:                "FORMAT DRIVE",
                    494:                "VERIFY TRACK (?)",
                    495:                "FORMAT TRACK (?)",
                    496:                "REASSIGN BLOCK",
                    497:                "READ SECTOR(S)",
                    498:                "???",
                    499:                "WRITE SECTOR(S)",
                    500:                "SEEK",
                    501:                "???",
                    502:                "CORRECTION",
                    503:                "???",
                    504:                "TRANSLATE",
                    505:                "SET ERROR THRESHOLD",  /* 0x10 */
                    506:                "USAGE COUNTERS",
                    507:                "INQUIRY",
                    508:                "WRITE DATA BUFFER",
                    509:                "READ DATA BUFFER",
                    510:                "MODE SELECT",
                    511:                "???",
                    512:                "???",
                    513:                "EXTENDED READ",
                    514:                "READ TOC",
                    515:                "MODE SENSE",
                    516:                "SHIP",
                    517:                "RECEIVE DIAGNOSTICS",
                    518:                "SEND DIAGNOSTICS"
                    519:        };
                    520: 
                    521:        opcode = HD_OPCODE(HDCCommand);
                    522: 
                    523:        fprintf(hdlogFile,"----\n");
                    524: 
                    525:        if (opcode >= 0 && opcode <= (int)(sizeof(psComNames)/sizeof(psComNames[0])))
                    526:        {
                    527:                fprintf(hdlogFile, "HDC opcode 0x%x : %s\n",opcode,psComNames[opcode]);
                    528:        }
                    529:        else
                    530:        {
                    531:                fprintf(hdlogFile, "Unknown HDC opcode!! Value = 0x%x\n", opcode);
                    532:        }
                    533: 
                    534:        fprintf(hdlogFile, "Controller: %i\n", HD_CONTROLLER(HDCCommand));
                    535:        fprintf(hdlogFile, "Drive: %i\n", HD_DRIVENUM(HDCCommand));
                    536:        fprintf(hdlogFile, "LBA: 0x%lx\n", HDC_GetOffset());
                    537: 
                    538:        fprintf(hdlogFile, "Sector count: 0x%x\n", HD_SECTORCOUNT(HDCCommand));
                    539:        fprintf(hdlogFile, "HDC sector count: 0x%x\n", HDCSectorCount);
                    540:        //fprintf(hdlogFile, "FDC sector count: 0x%x\n", FDCSectorCountRegister);
                    541:        fprintf(hdlogFile, "Control byte: 0x%x\n", HD_CONTROL(HDCCommand));
1.1       root      542: }
1.1.1.7   root      543: #endif
                    544: 
1.1       root      545: 
                    546: /*---------------------------------------------------------------------*/
1.1.1.8   root      547: /**
                    548:  * Print data about the hard drive image
                    549:  */
1.1.1.4   root      550: static void HDC_GetInfo(void)
1.1       root      551: {
1.1.1.7   root      552: /* Partition table contains hd size + 4 partition entries
                    553:  * (composed of flag byte, 3 char ID, start offset and size),
                    554:  * this is followed by bad sector list + count and the root sector checksum.
                    555:  * Before this there's the boot code and with ICD hd driver additional 8
                    556:  * partition entries (at offset 0x156).
                    557:  */
                    558: #define HD_PARTITIONTABLE_SIZE (4+4*12)
                    559: #define HD_PARTITIONTABLE_OFFSET 0x1C2
                    560:        long offset;
                    561:        unsigned char hdinfo[HD_PARTITIONTABLE_SIZE];
                    562:        int i;
1.1.1.2   root      563: #ifdef HDC_VERBOSE
1.1.1.7   root      564:        unsigned long size;
1.1.1.2   root      565: #endif
1.1       root      566: 
1.1.1.7   root      567:        nPartitions = 0;
                    568:        if (hd_image_file == NULL)
                    569:                return;
                    570:        offset = ftell(hd_image_file);
                    571: 
                    572:        fseek(hd_image_file, HD_PARTITIONTABLE_OFFSET, 0);
1.1.1.11! root      573:        if (fread(hdinfo, HD_PARTITIONTABLE_SIZE, 1, hd_image_file) != 1)
        !           574:        {
        !           575:                perror("HDC_GetInfo");
        !           576:                return;
        !           577:        }
1.1       root      578: 
                    579: #ifdef HDC_VERBOSE
1.1.1.7   root      580:        size = (((unsigned long) hdinfo[0] << 24)
                    581:                | ((unsigned long) hdinfo[1] << 16)
                    582:                | ((unsigned long) hdinfo[2] << 8)
                    583:                | ((unsigned long) hdinfo[3]));
                    584: 
                    585:        fprintf(stderr, "Total disk size %li Mb\n", size>>11);
                    586:        /* flags for each partition entry are zero if they are not valid */
                    587:        fprintf(stderr, "Partition 0 exists?: %s\n", (hdinfo[4] != 0)?"Yes":"No");
                    588:        fprintf(stderr, "Partition 1 exists?: %s\n", (hdinfo[4+12] != 0)?"Yes":"No");
                    589:        fprintf(stderr, "Partition 2 exists?: %s\n", (hdinfo[4+24] != 0)?"Yes":"No");
                    590:        fprintf(stderr, "Partition 3 exists?: %s\n", (hdinfo[4+36] != 0)?"Yes":"No");
1.1       root      591: #endif
                    592: 
1.1.1.7   root      593:        for(i=0;i<4;i++)
                    594:                if(hdinfo[4 + 12*i])
                    595:                        nPartitions++;
1.1       root      596: 
1.1.1.7   root      597:        fseek(hd_image_file, offset, 0);
1.1       root      598: }
                    599: 
1.1.1.7   root      600: 
1.1       root      601: /*---------------------------------------------------------------------*/
1.1.1.8   root      602: /**
                    603:  * Open the disk image file, set partitions.
1.1       root      604:  */
1.1.1.9   root      605: bool HDC_Init(char *filename)
1.1       root      606: {
1.1.1.11! root      607:        bAcsiEmuOn = false;
1.1       root      608: 
1.1.1.7   root      609:        /* Sanity check - is file length a multiple of 512? */
                    610:        if (File_Length(filename) & 0x1ff)
                    611:        {
                    612:                Log_Printf(LOG_ERROR, "HD file '%s' has strange size!\n", filename);
1.1.1.11! root      613:                return false;
1.1.1.7   root      614:        }
1.1.1.3   root      615: 
1.1.1.7   root      616: 
                    617:        if ((hd_image_file = fopen(filename, "rb+")) == NULL)
                    618:        {
                    619:                Log_Printf(LOG_ERROR, "Can not open HD file '%s'!\n", filename);
1.1.1.11! root      620:                return false;
1.1.1.7   root      621:        }
                    622: 
                    623:        HDC_GetInfo();
                    624: 
                    625:        /* set number of partitions */
                    626:        nNumDrives += nPartitions;
                    627: 
1.1.1.11! root      628:        bAcsiEmuOn = true;
1.1.1.7   root      629: 
1.1.1.11! root      630:        return true;
1.1       root      631: }
1.1.1.3   root      632: 
1.1.1.7   root      633: 
1.1       root      634: /*---------------------------------------------------------------------*/
1.1.1.8   root      635: /**
                    636:  * HDC_UnInit - close image file
                    637:  *
1.1       root      638:  */
1.1.1.4   root      639: void HDC_UnInit(void)
1.1       root      640: {
1.1.1.7   root      641:        if (!bAcsiEmuOn)
                    642:                return;
                    643: 
                    644:        fclose(hd_image_file);
                    645:        hd_image_file = NULL;
                    646: 
                    647:        nNumDrives -= nPartitions;
                    648:        nPartitions = 0;
1.1.1.11! root      649:        bAcsiEmuOn = false;
1.1       root      650: }
                    651: 
1.1.1.7   root      652: 
1.1       root      653: /*---------------------------------------------------------------------*/
1.1.1.8   root      654: /**
                    655:  * Process HDC command packets, called when bytes are 
                    656:  * written to $FFFF8606 and the HDC (not the FDC) is selected.
                    657:  */
1.1.1.4   root      658: void HDC_WriteCommandPacket(void)
1.1       root      659: {
1.1.1.7   root      660:        /* is HDC emulation enabled? */
                    661:        if (!bAcsiEmuOn)
                    662:                return;
                    663: 
                    664:        /* command byte sent, store it. */
                    665:        HDCCommand.command[HDCCommand.byteCount++] =  (DiskControllerWord_ff8604wr&0xFF);
                    666: 
                    667:        /* have we received a complete 6-byte packet yet? */
                    668:        if (HDCCommand.byteCount >= 6)
                    669:        {
1.1       root      670: 
                    671: #ifdef HDC_REALLY_VERBOSE
1.1.1.7   root      672:                HDC_DebugCommandPacket(stderr);
1.1       root      673: #endif
                    674: 
1.1.1.7   root      675:                /* If it's aimed for our drive, emulate it! */
                    676:                if ((HD_CONTROLLER(HDCCommand)) == 0)
                    677:                {
                    678:                        if (HD_DRIVENUM(HDCCommand) == 0)
                    679:                                HDC_EmulateCommandPacket();
                    680:                        else
                    681:                                Log_Printf(LOG_WARN, "HDC: Program tries to access illegal drive.\n");
                    682:                }
                    683:                else
                    684:                {
                    685:                        /* No drive/controller */
1.1.1.11! root      686:                        FDC_SetDMAStatus(true);
1.1.1.7   root      687:                        //FDC_AcknowledgeInterrupt();
                    688:                        HDCCommand.returnCode = HD_STATUS_ERROR;
                    689:                        //FDCSectorCountRegister = 0;
                    690:                        MFP_GPIP |= 0x20;
                    691:                }
                    692: 
                    693:                HDCCommand.byteCount = 0;
                    694:        }
                    695:        else
                    696:        {
                    697:                if (HD_CONTROLLER(HDCCommand) == 0)
                    698:                {
                    699:                        FDC_AcknowledgeInterrupt();
1.1.1.11! root      700:                        FDC_SetDMAStatus(false);
1.1.1.7   root      701:                        HDCCommand.returnCode = HD_STATUS_OK;
                    702:                }
                    703:                else
                    704:                {
                    705:                        /* If there's no controller, the interrupt line stays high */
                    706:                        HDCCommand.returnCode = HD_STATUS_ERROR;
                    707:                        MFP_GPIP |= 0x20;
                    708:                }
                    709:        }
1.1       root      710: }

unix.superglobalmegacorp.com

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