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