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

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

unix.superglobalmegacorp.com

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