|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.