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