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