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

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.7 ! root        9: const char HDC_rcsid[] = "Hatari $Id: hdc.c,v 1.16 2006/08/13 23:33:32 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: /*---------------------------------------------------------------------*/
                     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: /*---------------------------------------------------------------------*/
                    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: /*---------------------------------------------------------------------*/
                    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: /*---------------------------------------------------------------------*/
        !           150: /*
        !           151:   Request sense - return some disk information
        !           152: */
        !           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: /*---------------------------------------------------------------------*/
        !           238: /*
        !           239:   Mode sense - Get parameters from disk.
        !           240:   (Just enough to make the HDX tool from AHDI 5.0 happy)
        !           241: */
        !           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: /*---------------------------------------------------------------------*/
        !           296: /*
        !           297:   Format drive.
        !           298: */
        !           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: /*---------------------------------------------------------------------*/
                    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: /*---------------------------------------------------------------------*/
                    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: /*---------------------------------------------------------------------*/
                    384: /*
                    385:   Emulation routine for HDC command packets.
                    386: */
                    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: /*---------------------------------------------------------------------*/
                    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: /*---------------------------------------------------------------------*/
                    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: /*---------------------------------------------------------------------*/
                    568: /*
                    569:   Open the disk image file, set partitions.
                    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: /*---------------------------------------------------------------------*/
                    601: /*
                    602:   HDC_UnInit - close image file
1.1.1.7 ! root      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: /*---------------------------------------------------------------------*/
                    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.