|
|
1.1 root 1: /*
2: Hatari
3:
4: Floppy Disc Controller(FDC) emulation. We need to simulate the movement of the head of the
5: floppy disc drive to accurately perform the FDC commands, such as 'Step'. The is important
6: for ST demo disc images. We have to go into a lot of details - including the start up/stop
7: of the drive motor.
8: To help with this emulation, we keep our own internal commands which are checked each HBL
9: to perform the transfer of data from our disc image into the ST RAM area by simulating the
10: DMA.
11: */
12:
13: #include "main.h"
14: #include "debug.h"
15: #include "decode.h"
16: #include "dialog.h"
17: #include "fdc.h"
1.1.1.3 ! root 18: #include "hdc.h"
1.1 root 19: #include "floppy.h"
20: #include "ikbd.h"
21: #include "m68000.h"
22: #include "memorySnapShot.h"
23: #include "mfp.h"
24: #include "misc.h"
25: #include "psg.h"
26: #include "stMemory.h"
27:
1.1.1.3 ! root 28:
1.1 root 29: /*
30: Floppy Disc Controller
31:
32: Programmable Sound Generator (YM-2149)
33:
34: 0xff8800(even byte) - PSG Register Data (Read, used for parallel port)
35: - PSG Register Select (Write)
36:
37: Write to bits 0-3 to select PSG register to use(then write data to 0xfff8802)
38: Value Register
39:
40: 0000 Channel A Fine Tune
41: 0001 Channel A Coarse Tune
42: 0010 Channel B Fine Tune
43: 0011 Channel B Coarse Tune
44: 0100 Channel C Fine Tune
45: 0101 Channel C Coarse Tune
46: 0110 Noise Generator Control
47: 0111 Mixer Control - I/O enable
48: 1000 Channel A Amplitude
49: 1001 Channel B Amplitude
50: 1010 Channel C Amplitude
51: 1011 Envelope Period Fine Tune
52: 1100 Envelope Peroid Coarse Tune
53: 1101 Envelope Shape
54: 1110 I/O Port A Select (Write only)
55: 1111 I/O Port B Select
56:
57: 0xfff8802(even byte) - Bits according to 0xff8800 Register select
58:
59: 1110(Register 14) - I/O Port A
60: Bit 0 - Floppy side 0/1
61: Bit 1 - Floppy drive 0 select
62: Bit 2 - Floppy drive 1 select
63: Bit 3 - RS232 Ready to send (RTS)
64: Bit 4 - RS232 Data Terminal Ready (DTR)
65: Bit 5 - Centronics Strobe
66: Bit 6 - General Purpose Output
67: Bit 7 - Reserved
68:
69: ACSI DMA and Floppy Disc Controller(FDC)
70: 0xff8604 - information from file '1772.info.txt, by David Gahris' (register r0)
71: (write) - Disk controller
72: (read) - Disk controller status
73: Bit 0 - Busy. This bit is 1 when the 177x is busy. This bit is 0 when the 177x is free for CPU commands.
74: Bit 1 - Index / Data Request. On Type I commands, this bit is high during the index pulse that occurs once
75: per disk rotation. This bit is low at all times other than the index pulse. For Type II and III commands,
76: Bit 1 high signals the CPU to handle the data register in order to maintain a continuous flow of data.
77: Bit 1 is high when the data register is full during a read or when the data register is empty during a write.
78: "Worst case service time" for Data Request is 23.5 cycles.
79: Bit 2 - Track Zero / Lost Data. After Type I commands, this bit is 0 if the mechanism is at track zero.
80: This bit is 1 if the head is not at track zero. After Type II or III commands, this bit is 1 if the
81: CPU did not respond to Data Request (Status bit 1) in time for the 177x to maintain a continuous data flow.
82: This bit is 0 if the CPU responded promptly to Data Request.
83: Bit 3 - CRC Error. This bit is high if a sector CRC on disk does not match the CRC which the 177x
84: computed from the data. The CRC polynomial is x^16+x^12+x^5+1. If the stored CRC matches the newly
85: calculated CRC, the CRC Error bit is low. If this bit and the Record Not Found bit are set, the error
86: was in an ID field. If this bit is set but Record Not Found is clear, the error was in a data field.
87: Bit 4 - Record Not Found. This bit is set if the 177x cannot find the track, sector, or side which
88: the CPU requested. Otherwise, this bit is clear.
89: Bit 5 - Spin-up / Record Type. For Type I commands, this bit is low during the 6-revolution motor
90: spin-up time. This bit is high after spin-up. For Type II and Type III commands, Bit 5 low
91: indicates a normal data mark. Bit 5 high indicates a deleted data mark.
92: Bit 6 - Write Protect. This bit is not used during reads. During writes, this bit is high when the disk is write protected.
93: Bit 7 - Motor On. This bit is high when the drive motor is on, and low when the motor is off.
94:
95: 0xff8606 - DMA Status(read), DMA Mode Control(write) - NOTE bits 0,9-15 are not used
96: Bit 1 - FDC Pin A0 (See below)
97: Bit 2 - FDC Pin A1
98: Bit 3 - FDC/HDC Register Select
99: Bit 4 - FDC/Sector count select
100: Bit 5 - Reserved
101: Bit 6 - Enable/Disable DMA
102: Bit 7 - HDC/FDC
103: Bit 8 - Read/Write
104:
105: A1 A0 Read Write(bit 8==1)
106: 0 0 Status Command
107: 0 1 Track Register Track Register
108: 1 0 Sector Register Sector Register
109: 1 1 Data Register Data Register
110:
111:
112: This handles any read/writes to the FDC and PSG. FDC commands are then sent through to read/write
113: disc sector code. We have full documents on 1772 FDC, but they use r0,r1,r2,r3 etc.. which are
114: not seen at first glance as Atari access them via the A0,A1 bits. Once this is understood it
115: is all relativly easy as a lot of information can be ignored as we are using disc images and
116: not actual discs. We do NOT support the reading of the PC's A: drive - newer PC's cannot read
117: an ST single sided disc, ST discs are very old and so are dirty which gets onto the PC drive heads
118: and ruins them and also support for disc sector access under Windows is... well not well documented!
119:
120: According to the documentation INTRQ is generated at the completion of each command(causes an interrupt
121: in the MFP). INTRQ is reset by reading the status register OR by loading a new command. So, does this
122: mean the GPIP? Or does it actually CANCEL the interrupt? Can this be done?
123: */
124:
125: #define ENABLE_FLOPPY_SAVING /* Save to floppies */
126:
127: unsigned short int DiscControllerStatus_ff8604rd; /* 0xff8604 (read) */
128: unsigned short int DiscControllerWord_ff8604wr; /* 0xff8604 (write) */
129: unsigned short int DMAStatus_ff8606rd; /* 0xff8606 (read) */
130: unsigned short int DMAModeControl_ff8606wr,DMAModeControl_ff8606wr_prev; /* 0xff8606 (write,store prev for 'toggle' checks) */
131:
132: unsigned short int FDCCommandRegister;
133: short int FDCTrackRegister,FDCSectorRegister,FDCDataRegister;
134: short int FDCSectorCountRegister;
135: int FDCEmulationCommand; /* FDC emulation command currently being exceuted */
136: int FDCEmulationRunning; /* Running command under above */
137: int FDCStepDirection; /* +Track on 'Step' command */
138: short int DiscControllerByte; /* Used to pass parameter back to assembler */
139: BOOL bDMAWaiting; /* Is DMA waiting to copy? */
140: int bMotorOn; /* Is motor on? */
141: int MotorSlowingCount; /* Counter used to slow motor before stopping */
142:
143: short int nReadWriteTrack; /* Parameters used in sector read/writes */
144: short int nReadWriteSector;
145: short int nReadWriteSide;
146: short int nReadWriteDev;
147: unsigned short int nReadWriteSectorsPerTrack;
148: short int nReadWriteSectors;
149:
150: unsigned char DMASectorWorkSpace[NUMBYTESPERSECTOR]; /* Workspace used to copy to/from for floppy DMA */
151:
1.1.1.2 root 152:
153: /*-----------------------------------------------------------------------*/
1.1 root 154: /*
155: Reset variables used in FDC
156: */
157: void FDC_Reset(void)
158: {
1.1.1.2 root 159: /* Clear out FDC registers */
1.1 root 160: DiscControllerStatus_ff8604rd = 0;
161: DiscControllerWord_ff8604wr = 0;
162: DMAStatus_ff8606rd = 0x01;
163: DMAModeControl_ff8606wr = DMAModeControl_ff8606wr_prev = 0;
164: FDC_ResetDMAStatus();
165: FDCCommandRegister = 0;
166: FDCTrackRegister = 0;
167: FDCSectorRegister = 1;
168: FDCDataRegister = 0;
169: FDCSectorCountRegister = 0;
170:
171: FDCEmulationCommand = FDCEMU_CMD_NULL; /* FDC emulation command currently being exceuted */
172: FDCEmulationRunning = FDCEMU_RUN_NULL; /* Running command under above */
173:
174: FDCStepDirection = 1; /* +Track on 'Step' command */
175: bDMAWaiting = FALSE; /* No DMA waiting */
176: bMotorOn = FALSE; /* Motor off */
177: MotorSlowingCount = 0; /* Counter for motor slowing down before stopping */
178: }
179:
1.1.1.2 root 180:
181: /*-----------------------------------------------------------------------*/
1.1 root 182: /*
183: Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
184: */
185: void FDC_MemorySnapShot_Capture(BOOL bSave)
186: {
1.1.1.2 root 187: /* Save/Restore details */
1.1 root 188: MemorySnapShot_Store(&DiscControllerStatus_ff8604rd,sizeof(DiscControllerStatus_ff8604rd));
189: MemorySnapShot_Store(&DiscControllerWord_ff8604wr,sizeof(DiscControllerWord_ff8604wr));
190: MemorySnapShot_Store(&DMAStatus_ff8606rd,sizeof(DMAStatus_ff8606rd));
191: MemorySnapShot_Store(&DMAModeControl_ff8606wr,sizeof(DMAModeControl_ff8606wr));
192: MemorySnapShot_Store(&DMAModeControl_ff8606wr_prev,sizeof(DMAModeControl_ff8606wr_prev));
193: MemorySnapShot_Store(&FDCCommandRegister,sizeof(FDCCommandRegister));
194: MemorySnapShot_Store(&FDCTrackRegister,sizeof(FDCTrackRegister));
195: MemorySnapShot_Store(&FDCSectorRegister,sizeof(FDCSectorRegister));
196: MemorySnapShot_Store(&FDCDataRegister,sizeof(FDCDataRegister));
197: MemorySnapShot_Store(&FDCSectorCountRegister,sizeof(FDCSectorCountRegister));
198: MemorySnapShot_Store(&FDCEmulationCommand,sizeof(FDCEmulationCommand));
199: MemorySnapShot_Store(&FDCEmulationRunning,sizeof(FDCEmulationRunning));
200: MemorySnapShot_Store(&FDCStepDirection,sizeof(FDCStepDirection));
201: MemorySnapShot_Store(&DiscControllerByte,sizeof(DiscControllerByte));
202: MemorySnapShot_Store(&bDMAWaiting,sizeof(bDMAWaiting));
203: MemorySnapShot_Store(&bMotorOn,sizeof(bMotorOn));
204: MemorySnapShot_Store(&MotorSlowingCount,sizeof(MotorSlowingCount));
205: MemorySnapShot_Store(&nReadWriteTrack,sizeof(nReadWriteTrack));
206: MemorySnapShot_Store(&nReadWriteSector,sizeof(nReadWriteSector));
207: MemorySnapShot_Store(&nReadWriteSide,sizeof(nReadWriteSide));
208: MemorySnapShot_Store(&nReadWriteDev,sizeof(nReadWriteDev));
209: MemorySnapShot_Store(&nReadWriteSectorsPerTrack,sizeof(nReadWriteSectorsPerTrack));
210: MemorySnapShot_Store(&nReadWriteSectors,sizeof(nReadWriteSectors));
211: MemorySnapShot_Store(DMASectorWorkSpace,sizeof(DMASectorWorkSpace));
212: }
213:
1.1.1.2 root 214:
215: /*-----------------------------------------------------------------------*/
1.1 root 216: /*
217: Turn floppy motor on
218: */
219: void FDC_TurnMotorOn(void)
220: {
221: bMotorOn = TRUE; /* Turn motor on */
222: MotorSlowingCount = 0;
223: }
224:
1.1.1.2 root 225:
226: /*-----------------------------------------------------------------------*/
1.1 root 227: /*
228: Turn floppy motor off(this sets a count as it takes a set amount of time for the motor to slow to a halt)
229: */
230: void FDC_TurnMotorOff(void)
231: {
232: MotorSlowingCount = 10; /* Set timer so takes 'x' HBLs before turn off... */
233: }
234:
1.1.1.2 root 235:
236: /*-----------------------------------------------------------------------*/
1.1 root 237: /*
238: Update floppy drive motor each HBL, to simulate slowing down and stopping for drive; needed for New Zealand Story(PP_001)
239: */
240: void FDC_UpdateMotor(void)
241: {
1.1.1.2 root 242: /* Is drive slowing down? Decrement counter */
1.1 root 243: if (MotorSlowingCount>0) {
244: MotorSlowingCount--;
245:
246: if (MotorSlowingCount==0)
247: bMotorOn = FALSE; /* Motor finally stopped */
248: }
249: }
250:
1.1.1.2 root 251:
252: /*-----------------------------------------------------------------------*/
1.1 root 253: /*
254: Reset DMA Status (RD 0xff8606)
255:
256: This is done by 'toggling' bit 8 of the DMA Mode Control register
257: */
258: void FDC_ResetDMAStatus(void)
259: {
260: DMAStatus_ff8606rd = 0; /* Clear out */
261:
262: FDCSectorCountRegister = 0;
263: FDC_SetDMAStatus(FALSE); /* Set no error */
1.1.1.3 ! root 264:
! 265: HDCSectorCount = 0;
! 266: HDCCommand.byteCount = 0; /* Reset HDC command status */
! 267: HDCCommand.returnCode = 0xFF;
1.1 root 268: }
269:
1.1.1.2 root 270:
271: /*-----------------------------------------------------------------------*/
1.1 root 272: /*
273: Set DMA Status (RD 0xff8606)
274:
275: NOTE FDC Doc's are incorrect - Bit 0 is '0' on error (See TOS floprd, Ninja III etc...)
276: Look like Atari(yet again) connected the hardware up differently to the spec'
277:
278: Bit 0 - _Error Status (0=Error)
279: Bit 1 - _Sector Count Zero Status (0=Sector Count Zero)
280: Bit 2 - _Data Request Inactive Status
281: */
282: void FDC_SetDMAStatus(BOOL bError)
283: {
284: DMAStatus_ff8606rd &= 0x1; /* Clear(except for error) */
285:
1.1.1.2 root 286: /* Set error condition - NOTE this is incorrect in the FDC Doc's! */
1.1 root 287: if (!bError)
288: DMAStatus_ff8606rd |= 0x1;
289:
1.1.1.2 root 290: /* Set zero sector count */
1.1.1.3 ! root 291:
! 292: if (DMAModeControl_ff8606wr&0x08) /* Get which sector count? */
! 293: DMAStatus_ff8606rd |= (HDCSectorCount)?0:0x2; /* HDC */
! 294: else
! 295: DMAStatus_ff8606rd |= (FDCSectorCountRegister)?0x2:0; /* FDC */
! 296: /* Perhaps the DRQ should be set here */
1.1 root 297: }
298:
1.1.1.2 root 299:
300: /*-----------------------------------------------------------------------*/
1.1 root 301: /*
302: Read DMA Status (RD 0xff8606)
303: */
304: long FDC_ReadDMAStatus(void)
305: {
306: return (0xffff0000|DMAStatus_ff8606rd);
307: }
308:
1.1.1.2 root 309:
310: /*-----------------------------------------------------------------------*/
1.1 root 311: /*
312: */
313: void FDC_UpdateDiscDrive(void)
314: {
315: /* Set details for current selecte drive */
316: nReadWriteDev = FDC_FindFloppyDrive();
317:
318: if (EmulationDrives[nReadWriteDev].bDiscInserted)
319: Floppy_FindDiscDetails(EmulationDrives[nReadWriteDev].pBuffer,EmulationDrives[nReadWriteDev].nImageBytes,&nReadWriteSectorsPerTrack,NULL);
320: }
321:
1.1.1.2 root 322:
323: /*-----------------------------------------------------------------------*/
1.1 root 324: /*
325: When write to 0xff8606 (DMA Mode Control) check bit '8' toggle. This causes DMA status reset
326: */
327: void FDC_CheckForDMAStatusReset(void)
328: {
329: /* Test for 'toggle' of _read/_write bit '8' */
330: if ((DMAModeControl_ff8606wr_prev ^ DMAModeControl_ff8606wr)&0x0100)
331: FDC_ResetDMAStatus();
332: }
333:
1.1.1.2 root 334:
335: /*-----------------------------------------------------------------------*/
1.1 root 336: /*
337: Set disc controller status (RD 0xff8604)
338: */
339: void FDC_SetDiscControllerStatus(void)
340: {
341: /* Update disc */
342: FDC_UpdateDiscDrive();
343:
344: /* Clear out to default */
345: DiscControllerStatus_ff8604rd = 0;
346:
347: /* ONLY do this if we are running a Type I command */
348: if ((FDCCommandRegister&0x80)==0) { /* Type I - Restore,Seek,Step,Step-In,Step-Out */
349: if (FDCTrackRegister==0)
350: DiscControllerStatus_ff8604rd |= 0x4; /* Bit 2 - Track Zero, '0' if head is NOT at zero */
351: }
352:
353: /* If no disc inserted, tag as error */
354: if (!EmulationDrives[nReadWriteDev].bDiscInserted)
355: DiscControllerStatus_ff8604rd |= 0x10; /* RNF - Record not found, ie no disc in drive */
356: }
357:
1.1.1.2 root 358:
359: /*-----------------------------------------------------------------------*/
1.1 root 360: /*
361: Return device for FDC, check PORTA bits 1,2(0=on,1=off)
362: */
363: int FDC_FindFloppyDrive(void)
364: {
365: /* Check Drive A first */
366: if ((PSGRegisters[PSG_REG_IO_PORTA]&0x2)==0)
1.1.1.2 root 367: return(0); /* Device 0 (A:) */
1.1 root 368: /* If off, check Drive B */
369: if ((PSGRegisters[PSG_REG_IO_PORTA]&0x4)==0)
1.1.1.2 root 370: return(1); /* Device 1 (B:) */
1.1 root 371:
372: /* None appear to be selected so default to Drive A */
1.1.1.2 root 373: return(0); /* Device 0 (A:) */
1.1 root 374: }
375:
1.1.1.2 root 376:
377: /*-----------------------------------------------------------------------*/
1.1 root 378: /*
379: Acknowledge FDC interrupt
380: */
381: void FDC_AcknowledgeInterrupt(void)
382: {
1.1.1.2 root 383: /* Acknowledge in MFP circuit, pass bit, enable, pending */
1.1 root 384: MFP_InputOnChannel(MFP_FDCHDC_BIT,MFP_IERB,&MFP_IPRB);
385: MFP_GPIP &= ~0x20;
386: }
387:
1.1.1.2 root 388:
389: /*-----------------------------------------------------------------------*/
1.1 root 390: /*
391: Copy parameters for disc sector/s read/write
392: */
393: void FDC_SetReadWriteParameters(int nSectors)
394: {
1.1.1.2 root 395: /* Copy read/write details so we can modify them */
1.1 root 396: nReadWriteTrack = FDCTrackRegister;
397: nReadWriteSector = FDCSectorRegister;
398: nReadWriteSide = (~PSGRegisters[PSG_REG_IO_PORTA]) & 0x01;
399: nReadWriteSectors = nSectors;
1.1.1.2 root 400: /* Update disc */
1.1 root 401: FDC_UpdateDiscDrive();
402: }
403:
1.1.1.2 root 404:
405: /*-----------------------------------------------------------------------*/
1.1 root 406: /*
407: Update floppy drive on each HBL(approx' 512 cycles)
408: */
409: void FDC_UpdateHBL(void)
410: {
1.1.1.2 root 411: /* Do we have a DMA ready to copy? */
1.1 root 412: if (bDMAWaiting) {
1.1.1.2 root 413: /* Yes, copy it */
1.1 root 414: FDC_DMADataFromFloppy();
1.1.1.2 root 415: /* Signal done */
1.1 root 416: bDMAWaiting = FALSE;
417: }
418:
1.1.1.2 root 419: /* Update drive motor */
1.1 root 420: FDC_UpdateMotor();
421:
1.1.1.2 root 422: /* Is FDC active? */
1.1 root 423: if (FDCEmulationCommand!=FDCEMU_CMD_NULL) {
1.1.1.2 root 424: /* Which command are we running? */
1.1 root 425: switch(FDCEmulationCommand) {
426: case FDCEMU_CMD_RESTORE:
427: FDC_UpdateRestoreCmd();
428: break;
429: case FDCEMU_CMD_SEEK:
430: FDC_UpdateSeekCmd();
431: break;
432: case FDCEMU_CMD_STEP:
433: FDC_UpdateStepCmd();
434: break;
435: case FDCEMU_CMD_STEPIN:
436: FDC_UpdateStepInCmd();
437: break;
438: case FDCEMU_CMD_STEPOUT:
439: FDC_UpdateStepOutCmd();
440: break;
441:
442: case FDCEMU_CMD_READSECTORS:
443: case FDCEMU_CMD_READMULTIPLESECTORS:
444: FDC_UpdateReadSectorsCmd();
445: break;
446: case FDCEMU_CMD_WRITESECTORS:
447: case FDCEMU_CMD_WRITEMULTIPLESECTORS:
448: FDC_UpdateWriteSectorsCmd();
449: break;
450: }
451:
1.1.1.2 root 452: /* Set disc controller status (RD 0xff8604) */
1.1 root 453: FDC_SetDiscControllerStatus();
454: }
455: }
456:
1.1.1.2 root 457:
458: /*-----------------------------------------------------------------------*/
1.1 root 459: /*
460: Run 'RESTORE' command
461: */
462: void FDC_UpdateRestoreCmd(void)
463: {
1.1.1.2 root 464: /* Which command is running? */
1.1 root 465: switch (FDCEmulationRunning) {
466: case FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO:
1.1.1.2 root 467: /* Are we at track zero? */
1.1 root 468: if (FDCTrackRegister>0)
469: FDCTrackRegister--; /* Move towards track zero */
470: else {
471: FDCTrackRegister = 0; /* We're there */
472: FDCEmulationRunning = FDCEMU_RUN_RESTORE_COMPLETE;
473: }
474: break;
475: case FDCEMU_RUN_RESTORE_COMPLETE:
1.1.1.2 root 476: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 477: FDC_AcknowledgeInterrupt();
1.1.1.2 root 478: /* Set error */
1.1 root 479: FDC_SetDMAStatus(FALSE); /* No DMA error */
1.1.1.2 root 480: /* Done */
1.1 root 481: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 482: /* Turn motor off */
1.1 root 483: FDC_TurnMotorOff();
484: break;
485: }
486: }
487:
1.1.1.2 root 488:
489: /*-----------------------------------------------------------------------*/
1.1 root 490: /*
491: Run 'SEEK' command
492: */
493: void FDC_UpdateSeekCmd(void)
494: {
1.1.1.2 root 495: /* Which command is running? */
1.1 root 496: switch (FDCEmulationRunning) {
497: case FDCEMU_RUN_SEEK_TOTRACK:
1.1.1.2 root 498: /* Are we at the selected track? */
1.1 root 499: if (FDCTrackRegister==FDCDataRegister)
500: FDCEmulationRunning = FDCEMU_RUN_SEEK_COMPLETE;
501: else {
1.1.1.2 root 502: /* No, seek towards track */
1.1 root 503: if (FDCDataRegister<FDCTrackRegister)
504: FDCTrackRegister--;
505: else
506: FDCTrackRegister++;
507: }
508: break;
509: case FDCEMU_RUN_SEEK_COMPLETE:
1.1.1.2 root 510: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 511: FDC_AcknowledgeInterrupt();
1.1.1.2 root 512: /* Set error */
513: FDC_SetDMAStatus(FALSE); /* No DMA error */
514: /* Done */
1.1 root 515: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 516: /* Turn motor off */
1.1 root 517: FDC_TurnMotorOff();
518: break;
519: }
520: }
521:
1.1.1.2 root 522:
523: /*-----------------------------------------------------------------------*/
1.1 root 524: /*
525: Run 'STEP' command
526: */
527: void FDC_UpdateStepCmd(void)
528: {
1.1.1.2 root 529: /* Which command is running? */
1.1 root 530: switch (FDCEmulationRunning) {
531: case FDCEMU_RUN_STEP_ONCE:
1.1.1.2 root 532: /* Move head by one track in same direction as last step */
1.1 root 533: FDCTrackRegister += FDCStepDirection;
534: if (FDCTrackRegister<0) /* Limit to stop */
535: FDCTrackRegister = 0;
536:
537: FDCEmulationRunning = FDCEMU_RUN_STEP_COMPLETE;
538: break;
539: case FDCEMU_RUN_STEP_COMPLETE:
1.1.1.2 root 540: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 541: FDC_AcknowledgeInterrupt();
1.1.1.2 root 542: /* Set error */
1.1 root 543: FDC_SetDMAStatus(FALSE); /* No DMA error */
1.1.1.2 root 544: /* Done */
1.1 root 545: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 546: /* Turn motor off */
1.1 root 547: FDC_TurnMotorOff();
548: break;
549: }
550: }
551:
1.1.1.2 root 552:
553: /*-----------------------------------------------------------------------*/
1.1 root 554: /*
555: Run 'STEP IN' command
556: */
557: void FDC_UpdateStepInCmd(void)
558: {
1.1.1.2 root 559: /* Which command is running? */
1.1 root 560: switch (FDCEmulationRunning) {
561: case FDCEMU_RUN_STEPIN_ONCE:
562: FDCTrackRegister++;
563:
564: FDCEmulationRunning = FDCEMU_RUN_STEPIN_COMPLETE;
565: break;
566: case FDCEMU_RUN_STEPIN_COMPLETE:
1.1.1.2 root 567: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 568: FDC_AcknowledgeInterrupt();
1.1.1.2 root 569: /* Set error */
1.1 root 570: FDC_SetDMAStatus(FALSE); /* No DMA error */
1.1.1.2 root 571: /* Done */
1.1 root 572: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 573: /* Turn motor off */
1.1 root 574: FDC_TurnMotorOff();
575: break;
576: }
577: }
578:
1.1.1.2 root 579:
580: /*-----------------------------------------------------------------------*/
1.1 root 581: /*
582: Run 'STEP OUT' command
583: */
584: void FDC_UpdateStepOutCmd(void)
585: {
1.1.1.2 root 586: /* Which command is running? */
1.1 root 587: switch (FDCEmulationRunning) {
588: case FDCEMU_RUN_STEPOUT_ONCE:
589: FDCTrackRegister--;
1.1.1.2 root 590: if (FDCTrackRegister<0) /* Limit to stop */
1.1 root 591: FDCTrackRegister = 0;
592:
593: FDCEmulationRunning = FDCEMU_RUN_STEPOUT_COMPLETE;
594: break;
595: case FDCEMU_RUN_STEPOUT_COMPLETE:
1.1.1.2 root 596: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 597: FDC_AcknowledgeInterrupt();
1.1.1.2 root 598: /* Set error */
599: FDC_SetDMAStatus(FALSE); /* No DMA error */
600: /* Done */
1.1 root 601: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 602: /* Turn motor off */
1.1 root 603: FDC_TurnMotorOff();
604: break;
605: }
606: }
607:
1.1.1.2 root 608:
609: /*-----------------------------------------------------------------------*/
1.1 root 610: /*
611: Run 'READ SECTOR/S' command
612: */
613: void FDC_UpdateReadSectorsCmd(void)
614: {
1.1.1.2 root 615: /* Which command is running? */
1.1 root 616: switch (FDCEmulationRunning) {
617: case FDCEMU_RUN_READSECTORS_READDATA:
1.1.1.2 root 618: /* Read in a sector */
1.1 root 619: if (FDC_ReadSectorFromFloppy()) { /* Read a single sector through DMA */
620: FDCSectorCountRegister--; /* Decrement FDCSectorCount */
621: if (FDCSectorCountRegister<=0)
622: FDCSectorCountRegister = 0;
623:
1.1.1.2 root 624: /* Have we finished? */
1.1 root 625: nReadWriteSectors--;
626: if (nReadWriteSectors<=0)
627: FDCEmulationRunning = FDCEMU_RUN_READSECTORS_COMPLETE;
628:
629: bDMAWaiting = TRUE;
630: }
631: else {
1.1.1.2 root 632: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 633: FDC_AcknowledgeInterrupt();
1.1.1.2 root 634: /* Set error */
1.1 root 635: FDC_SetDMAStatus(TRUE); /* DMA error */
1.1.1.2 root 636: /* Done */
1.1 root 637: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 638: /* Turn motor off */
1.1 root 639: FDC_TurnMotorOff();
640: }
641: break;
642: case FDCEMU_RUN_READSECTORS_COMPLETE:
1.1.1.2 root 643: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 644: FDC_AcknowledgeInterrupt();
1.1.1.2 root 645: /* Set error */
1.1 root 646: FDC_SetDMAStatus(FALSE); /* No DMA error */
1.1.1.2 root 647: /* Done */
1.1 root 648: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 649: /* Turn motor off */
1.1 root 650: FDC_TurnMotorOff();
651: break;
652: }
653: }
654:
1.1.1.2 root 655:
656: /*-----------------------------------------------------------------------*/
1.1 root 657: /*
658: Run 'WRITE SECTOR/S' command
659: */
660: void FDC_UpdateWriteSectorsCmd(void)
661: {
1.1.1.2 root 662: /* Which command is running? */
1.1 root 663: switch (FDCEmulationRunning) {
664: case FDCEMU_RUN_WRITESECTORS_WRITEDATA:
1.1.1.2 root 665: /* Write out a sector */
1.1 root 666: if (FDC_WriteSectorFromFloppy()) { /* Write a single sector through DMA */
1.1.1.2 root 667: /* Decrement FDCsector count */
1.1 root 668: FDCSectorCountRegister--; /* Decrement FDCSectorCount */
669: if (FDCSectorCountRegister<=0)
670: FDCSectorCountRegister = 0;
671:
1.1.1.2 root 672: /* Have we finished? */
1.1 root 673: nReadWriteSectors--;
674: if (nReadWriteSectors<=0)
675: FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_COMPLETE;
676:
1.1.1.2 root 677: /* Update DMA pointer */
1.1 root 678: FDC_WriteDMAAddress(FDC_ReadDMAAddress()+NUMBYTESPERSECTOR);
679: }
680: else {
1.1.1.2 root 681: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 682: FDC_AcknowledgeInterrupt();
1.1.1.2 root 683: /* Set error */
1.1 root 684: FDC_SetDMAStatus(TRUE); /* DMA error */
1.1.1.2 root 685: /* Done */
1.1 root 686: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 687: /* Turn motor off */
1.1 root 688: FDC_TurnMotorOff();
689: }
690: break;
691: case FDCEMU_RUN_WRITESECTORS_COMPLETE:
1.1.1.2 root 692: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 693: FDC_AcknowledgeInterrupt();
1.1.1.2 root 694: /* Set error */
1.1 root 695: FDC_SetDMAStatus(FALSE); /* No DMA error */
1.1.1.2 root 696: /* Done */
1.1 root 697: FDCEmulationCommand = FDCEMU_CMD_NULL;
1.1.1.2 root 698: /* Turn motor off */
1.1 root 699: FDC_TurnMotorOff();
700: break;
701: }
702: }
703:
1.1.1.2 root 704:
705: /*-----------------------------------------------------------------------*/
1.1 root 706: /*
707: Type I Commands
708:
709: Restore, Seek, Step, Step-In and Step-Out
710: */
711:
1.1.1.2 root 712:
713: /*-----------------------------------------------------------------------*/
1.1 root 714: void FDC_TypeI_Restore(void)
715: {
1.1.1.2 root 716: /* Set emulation to seek to track zero */
1.1 root 717: FDCEmulationCommand = FDCEMU_CMD_RESTORE;
718: FDCEmulationRunning = FDCEMU_RUN_RESTORE_SEEKTOTRACKZERO;
719:
720: FDC_SetDiscControllerStatus();
721: }
722:
1.1.1.2 root 723:
724: /*-----------------------------------------------------------------------*/
1.1 root 725: void FDC_TypeI_Seek(void)
726: {
1.1.1.2 root 727: /* Set emulation to seek to chosen track */
1.1 root 728: FDCEmulationCommand = FDCEMU_CMD_SEEK;
729: FDCEmulationRunning = FDCEMU_RUN_SEEK_TOTRACK;
730:
731: FDC_SetDiscControllerStatus();
732: }
733:
1.1.1.2 root 734:
735: /*-----------------------------------------------------------------------*/
1.1 root 736: void FDC_TypeI_Step(void)
737: {
1.1.1.2 root 738: /* Set emulation to step(same direction as last seek executed, eg 'FDCStepDirection') */
1.1 root 739: FDCEmulationCommand = FDCEMU_CMD_STEP;
740: FDCEmulationRunning = FDCEMU_RUN_STEP_ONCE;
741:
742: FDC_SetDiscControllerStatus();
743: }
744:
1.1.1.2 root 745:
746: /*-----------------------------------------------------------------------*/
1.1 root 747: void FDC_TypeI_StepIn(void)
748: {
1.1.1.2 root 749: /* Set emulation to step in(Set 'FDCStepDirection') */
1.1 root 750: FDCEmulationCommand = FDCEMU_CMD_STEPIN;
751: FDCEmulationRunning = FDCEMU_RUN_STEPIN_ONCE;
1.1.1.2 root 752: FDCStepDirection = 1; /* Increment track*/
1.1 root 753:
754: FDC_SetDiscControllerStatus();
755: }
756:
1.1.1.2 root 757:
758: /*-----------------------------------------------------------------------*/
1.1 root 759: void FDC_TypeI_StepOut(void)
760: {
1.1.1.2 root 761: /* Set emulation to step out(Set 'FDCStepDirection') */
1.1 root 762: FDCEmulationCommand = FDCEMU_CMD_STEPOUT;
763: FDCEmulationRunning = FDCEMU_RUN_STEPOUT_ONCE;
1.1.1.2 root 764: FDCStepDirection = -1; /* Decrement track */
1.1 root 765:
766: FDC_SetDiscControllerStatus();
767: }
768:
1.1.1.2 root 769:
770: /*-----------------------------------------------------------------------*/
1.1 root 771: /*
772: Type II Commands
773:
774: Read Sector, Read Multiple Sectors, Write Sector, Write Multiple Sectors
775: */
776:
1.1.1.2 root 777:
778: /*-----------------------------------------------------------------------*/
1.1 root 779: void FDC_TypeII_ReadSector(void)
780: {
1.1.1.2 root 781: /* Set emulation to read a single sector */
1.1 root 782: FDCEmulationCommand = FDCEMU_CMD_READSECTORS;
783: FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
1.1.1.2 root 784: /* Set reading parameters */
785: FDC_SetReadWriteParameters(1); /* Read in a single sector */
1.1 root 786:
787: FDC_SetDiscControllerStatus();
788: }
789:
1.1.1.2 root 790:
791: /*-----------------------------------------------------------------------*/
1.1 root 792: void FDC_TypeII_ReadMultipleSectors(void)
793: {
1.1.1.2 root 794: /* Set emulation to read sectors */
1.1 root 795: FDCEmulationCommand = FDCEMU_CMD_READMULTIPLESECTORS;
796: FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
1.1.1.2 root 797: /* Set reading parameters */
798: FDC_SetReadWriteParameters(FDCSectorCountRegister); /* Read multiple sectors */
1.1 root 799:
800: FDC_SetDiscControllerStatus();
801: }
802:
1.1.1.2 root 803:
804: /*-----------------------------------------------------------------------*/
1.1 root 805: void FDC_TypeII_WriteSector(void)
806: {
1.1.1.2 root 807: /* Set emulation to write a single sector */
1.1 root 808: FDCEmulationCommand = FDCEMU_CMD_WRITESECTORS;
809: FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
1.1.1.2 root 810: /* Set writing parameters */
811: FDC_SetReadWriteParameters(1); /* Write out a single sector */
1.1 root 812:
813: FDC_SetDiscControllerStatus();
814: }
815:
1.1.1.2 root 816:
817: /*-----------------------------------------------------------------------*/
1.1 root 818: void FDC_TypeII_WriteMultipleSectors(void)
819: {
1.1.1.2 root 820: /* Set emulation to write sectors */
1.1 root 821: FDCEmulationCommand = FDCEMU_CMD_WRITEMULTIPLESECTORS;
822: FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
1.1.1.2 root 823: /* Set witing parameters */
824: FDC_SetReadWriteParameters(FDCSectorCountRegister); /* Write multiple sectors */
1.1 root 825:
826: FDC_SetDiscControllerStatus();
827: }
828:
1.1.1.2 root 829:
830: /*-----------------------------------------------------------------------*/
1.1 root 831: /*
832: Type III Commands
833:
834: Read Address, Read Track, Write Track
835: */
836:
1.1.1.2 root 837:
838: /*-----------------------------------------------------------------------*/
1.1 root 839: void FDC_TypeIII_ReadAddress(void)
840: {
841: }
842:
1.1.1.2 root 843:
844: /*-----------------------------------------------------------------------*/
1.1 root 845: void FDC_TypeIII_ReadTrack(void)
846: {
1.1.1.2 root 847: /* Set emulation to read a single track */
1.1 root 848: FDCEmulationCommand = FDCEMU_CMD_READSECTORS;
849: FDCEmulationRunning = FDCEMU_RUN_READSECTORS_READDATA;
1.1.1.2 root 850: /* Set reading parameters */
851: FDC_SetReadWriteParameters(nReadWriteSectorsPerTrack); /* Read whole track */
1.1 root 852:
853: FDC_SetDiscControllerStatus();
854: }
855:
1.1.1.2 root 856:
857: /*-----------------------------------------------------------------------*/
1.1 root 858: void FDC_TypeIII_WriteTrack(void)
859: {
1.1.1.2 root 860: /* Set emulation to write a single track */
1.1 root 861: FDCEmulationCommand = FDCEMU_CMD_WRITESECTORS;
862: FDCEmulationRunning = FDCEMU_RUN_WRITESECTORS_WRITEDATA;
1.1.1.2 root 863: /* Set writing parameters */
864: FDC_SetReadWriteParameters(nReadWriteSectorsPerTrack); /* Write whole track */
1.1 root 865:
866: FDC_SetDiscControllerStatus();
867: }
868:
1.1.1.2 root 869:
870: /*-----------------------------------------------------------------------*/
1.1 root 871: /*
872: Type IV Commands
873:
874: Force Interrupt
875: */
876:
1.1.1.2 root 877:
878: /*-----------------------------------------------------------------------*/
1.1 root 879: void FDC_TypeIV_ForceInterrupt(BOOL bCauseCPUInterrupt)
880: {
1.1.1.2 root 881: /* Acknowledge interrupt, move along there's nothing more to see */
1.1 root 882: if (bCauseCPUInterrupt)
883: FDC_AcknowledgeInterrupt();
884:
1.1.1.2 root 885: /* Reset FDC */
1.1 root 886: FDCEmulationCommand = FDCEMU_CMD_NULL;
887: FDCEmulationRunning = FDCEMU_RUN_NULL;
888: }
889:
1.1.1.2 root 890:
891: /*-----------------------------------------------------------------------*/
1.1 root 892: /*
893: Execute Type I commands
894: */
895: void FDC_ExecuteTypeICommands(void)
896: {
897: MFP_GPIP |= 0x20;
898:
1.1.1.2 root 899: /* Check Type I Command */
1.1 root 900: switch(FDCCommandRegister&0xf0) {
1.1.1.2 root 901: case 0x00: /* Restore */
1.1 root 902: FDC_TypeI_Restore();
903: break;
1.1.1.2 root 904: case 0x10: /* Seek */
1.1 root 905: FDC_TypeI_Seek();
906: break;
1.1.1.2 root 907: case 0x20: /* Step */
1.1 root 908: case 0x30:
909: FDC_TypeI_Step();
910: break;
1.1.1.2 root 911: case 0x40: /* Step-In */
1.1 root 912: case 0x50:
913: FDC_TypeI_StepIn();
914: break;
1.1.1.2 root 915: case 0x60: /* Step-Out */
1.1 root 916: case 0x70:
917: FDC_TypeI_StepOut();
918: break;
919: }
920:
1.1.1.2 root 921: /* Signal motor on as we need to execute command */
1.1 root 922: FDC_TurnMotorOn();
923: }
924:
1.1.1.2 root 925:
926: /*-----------------------------------------------------------------------*/
1.1 root 927: /*
928: Execute Type II commands
929: */
930: void FDC_ExecuteTypeIICommands(void)
931: {
932: MFP_GPIP |= 0x20;
933:
1.1.1.2 root 934: /* Check Type II Command */
1.1 root 935: switch(FDCCommandRegister&0xf0) {
1.1.1.2 root 936: case 0x80: /* Read Sector */
1.1 root 937: FDC_TypeII_ReadSector();
938: break;
1.1.1.2 root 939: case 0x90: /* Read Sectors */
1.1 root 940: FDC_TypeII_ReadMultipleSectors();
941: break;
1.1.1.2 root 942: case 0xa0: /* Write Sector */
1.1 root 943: FDC_TypeII_WriteSector();
944: break;
1.1.1.2 root 945: case 0xb0: /* Write Sectors */
1.1 root 946: FDC_TypeII_WriteMultipleSectors();
947: break;
948: }
949:
1.1.1.2 root 950: /* Signal motor on as we need to execute command */
1.1 root 951: FDC_TurnMotorOn();
952: }
953:
1.1.1.2 root 954:
955: /*-----------------------------------------------------------------------*/
1.1 root 956: /*
957: Execute Type III commands
958: */
959: void FDC_ExecuteTypeIIICommands(void)
960: {
961: MFP_GPIP |= 0x20;
962:
1.1.1.2 root 963: /* Check Type III Command */
1.1 root 964: switch(FDCCommandRegister&0xf0) {
1.1.1.2 root 965: case 0xc0: /* Read Address */
1.1 root 966: FDC_TypeIII_ReadAddress();
967: break;
1.1.1.2 root 968: case 0xe0: /* Read Track */
1.1 root 969: FDC_TypeIII_ReadTrack();
970: break;
1.1.1.2 root 971: case 0xf0: /* Write Track */
1.1 root 972: FDC_TypeIII_WriteTrack();
973: break;
974: }
975:
1.1.1.2 root 976: /* Signal motor on as we need to execute command */
1.1 root 977: FDC_TurnMotorOn();
978: }
979:
1.1.1.2 root 980:
981: /*-----------------------------------------------------------------------*/
1.1 root 982: /*
983: Execute Type IV commands
984: */
985: void FDC_ExecuteTypeIVCommands(void)
986: {
987: if (FDCCommandRegister!=0xD8) /* Is an 'immediate interrupt command'? don't reset interrupt */
988: MFP_GPIP |= 0x20;
989:
1.1.1.2 root 990: /* Check Type IV Command */
1.1 root 991: if ((FDCCommandRegister&0x0c)==0) /* I3 and I2 are clear? If so we don't need a CPU interrupt */
992: FDC_TypeIV_ForceInterrupt(FALSE); /* Force Interrupt - no interrupt */
993: else
994: FDC_TypeIV_ForceInterrupt(TRUE); /* Force Interrupt */
995: }
996:
1.1.1.2 root 997:
998: /*-----------------------------------------------------------------------*/
1.1 root 999: /*
1000: Find FDC command type and execute
1001: */
1002: void FDC_ExecuteCommand(void)
1003: {
1004: /* Check type of command and execute */
1005: if ((FDCCommandRegister&0x80)==0) /* Type I - Restore,Seek,Step,Step-In,Step-Out */
1006: FDC_ExecuteTypeICommands();
1007: else if ((FDCCommandRegister&0x40)==0) /* Type II - Read Sector, Write Sector */
1008: FDC_ExecuteTypeIICommands();
1009: else if ((FDCCommandRegister&0xf0)!=0xd0) /* Type III - Read Address, Read Track, Write Track */
1010: FDC_ExecuteTypeIIICommands();
1.1.1.2 root 1011: else /* Type IV - Force Interrupt */
1.1 root 1012: FDC_ExecuteTypeIVCommands();
1013: }
1014:
1.1.1.2 root 1015:
1016: /*-----------------------------------------------------------------------*/
1.1 root 1017: /*
1018: Write to SectorCount register (WR 0xff8604)
1019: */
1020: void FDC_WriteSectorCountRegister(void)
1021: {
1022: FDCSectorCountRegister = DiscControllerWord_ff8604wr;
1023: }
1024:
1.1.1.2 root 1025:
1026: /*-----------------------------------------------------------------------*/
1.1 root 1027: /*
1028: Write to Command register (WR 0xff8604)
1029: */
1030: void FDC_WriteCommandRegister(void)
1031: {
1032: FDCCommandRegister = DiscControllerWord_ff8604wr;
1033: /* And execute */
1034: FDC_ExecuteCommand();
1035: }
1036:
1.1.1.2 root 1037:
1038: /*-----------------------------------------------------------------------*/
1.1 root 1039: /*
1040: Write to Track register (WR 0xff8604)
1041: */
1042: void FDC_WriteTrackRegister(void)
1043: {
1044: FDCTrackRegister = DiscControllerWord_ff8604wr; /* 0...79 */
1045: }
1046:
1.1.1.2 root 1047:
1048: /*-----------------------------------------------------------------------*/
1.1 root 1049: /*
1050: Write to Track register (WR 0xff8604)
1051: */
1052: void FDC_WriteSectorRegister(void)
1053: {
1054: FDCSectorRegister = DiscControllerWord_ff8604wr; /* 1,2,3..... */
1055: }
1056:
1.1.1.2 root 1057:
1058: /*-----------------------------------------------------------------------*/
1.1 root 1059: /*
1060: Write to Data register (WR 0xff8604)
1061: */
1062: void FDC_WriteDataRegister(void)
1063: {
1064: FDCDataRegister = DiscControllerWord_ff8604wr;
1065: }
1066:
1.1.1.2 root 1067:
1068: /*-----------------------------------------------------------------------*/
1.1 root 1069: /*
1070: Store byte in FDC registers, when write to 0xff8604
1071: */
1072: void FDC_WriteDiscControllerByte(void)
1073: {
1.1.1.3 ! root 1074: HDC_WriteCommandPacket(); /* Handle HDC functions */
! 1075:
1.1.1.2 root 1076: /* Are we trying to set the SectorCount? */
1.1 root 1077: if (DMAModeControl_ff8606wr&0x10) /* Bit 4 */
1078: FDC_WriteSectorCountRegister();
1.1.1.2 root 1079: else { /* Write to FDC registers */
1.1 root 1080: switch(DMAModeControl_ff8606wr&0x6) { /* Bits 1,2 (A1,A0) */
1081: case 0x0: /* 0 0 - Command register */
1082: FDC_WriteCommandRegister();
1083: break;
1084: case 0x2: /* 0 1 - Track register */
1085: FDC_WriteTrackRegister();
1086: break;
1087: case 0x4: /* 1 0 - Sector register */
1088: FDC_WriteSectorRegister();
1089: break;
1090: case 0x6: /* 1 1 - Data register */
1091: FDC_WriteDataRegister();
1092: break;
1093: }
1094: }
1095: }
1096:
1.1.1.2 root 1097:
1098: /*-----------------------------------------------------------------------*/
1.1 root 1099: /*
1100: Read Status/FDC registers, when read from 0xff8604
1101: Return 'DiscControllerByte'
1102: */
1103: void FDC_ReadDiscControllerStatusByte(void)
1104: {
1.1.1.3 ! root 1105: /* return the HDC status reg */
! 1106: if(DMAModeControl_ff8606wr == 0x08A) { /* HDC status reg selected */
! 1107: DiscControllerByte = HDCCommand.returnCode;
! 1108: return;
! 1109: }
! 1110:
! 1111: /* old FDC code */
1.1 root 1112: switch(DMAModeControl_ff8606wr&0x6) { /* Bits 1,2 (A1,A0) */
1113: case 0x0: /* 0 0 - Status register */
1114: DiscControllerByte = DiscControllerStatus_ff8604rd;
1115: if (bMotorOn)
1116: DiscControllerByte |= 0x80;
1117:
1118: /* Reset FDC GPIP */
1119: MFP_GPIP |= 0x20;
1120: break;
1121: case 0x2: /* 0 1 - Track register */
1122: DiscControllerByte = FDCTrackRegister;
1123: break;
1124: case 0x4: /* 1 0 - Sector register */
1125: DiscControllerByte = FDCSectorRegister;
1126: break;
1127: case 0x6: /* 1 1 - Data register */
1128: DiscControllerByte = FDCDataRegister;
1129: break;
1130: }
1131: }
1132:
1.1.1.2 root 1133:
1134: /*-----------------------------------------------------------------------*/
1.1 root 1135: /*
1136: Read DMA address from ST's RAM(always up-to-date)
1137: */
1138: unsigned long FDC_ReadDMAAddress(void)
1139: {
1140: unsigned long Address;
1141:
1142: /* Build up 24-bit address from hardware registers */
1143: Address = ((unsigned long)STMemory_ReadByte(0xff8609)<<16) | ((unsigned long)STMemory_ReadByte(0xff860b)<<8) | (unsigned long)STMemory_ReadByte(0xff860d);
1144:
1145: return(Address);
1146: }
1147:
1.1.1.2 root 1148:
1149: /*-----------------------------------------------------------------------*/
1.1 root 1150: /*
1151: Write DMA address to ST's RAM(always keep up-to-date)
1152: */
1153: void FDC_WriteDMAAddress(unsigned long Address)
1154: {
1155: /* Store as 24-bit address */
1156: STMemory_WriteByte(0xff8609,Address>>16);
1157: STMemory_WriteByte(0xff860b,Address>>8);
1158: STMemory_WriteByte(0xff860d,Address);
1159: }
1160:
1.1.1.2 root 1161:
1162: /*-----------------------------------------------------------------------*/
1.1 root 1163: /*
1164: Read sector from floppy drive into workspace
1165: We copy the bytes in chunks to simulate reading of the floppy using DMA
1166: */
1167: BOOL FDC_ReadSectorFromFloppy(void)
1168: {
1.1.1.2 root 1169: /* Copy in 1 sector to our workspace */
1.1 root 1170: if (Floppy_ReadSectors(nReadWriteDev,(char *)DMASectorWorkSpace,nReadWriteSector,nReadWriteTrack,nReadWriteSide,1,NULL)) {
1.1.1.2 root 1171: /* Update reading/writing parameters */
1.1 root 1172: nReadWriteSector++;
1.1.1.2 root 1173: if (nReadWriteSector>nReadWriteSectorsPerTrack) { /* Advance into next track? */
1.1 root 1174: nReadWriteSector = 1;
1175: nReadWriteTrack++;
1176: }
1177: return(TRUE);
1178: }
1179:
1.1.1.2 root 1180: /* Failed */
1.1 root 1181: return(FALSE);
1182: }
1183:
1.1.1.2 root 1184:
1185: /*-----------------------------------------------------------------------*/
1.1 root 1186: /*
1187: Write sector from workspace to floppy drive
1188: We copy the bytes in chunks to simulate writing of the floppy using DMA
1189: */
1190: BOOL FDC_WriteSectorFromFloppy(void)
1191: {
1192: unsigned long Address;
1193:
1.1.1.2 root 1194: /* Get DMA address */
1.1 root 1195: Address = FDC_ReadDMAAddress();
1196:
1.1.1.2 root 1197: /* Write out 1 sector from our workspace */
1.1 root 1198: if (Floppy_WriteSectors(nReadWriteDev,(char *)((unsigned long)STRam+Address),nReadWriteSector,nReadWriteTrack,nReadWriteSide,1,NULL)) {
1.1.1.2 root 1199: /* Update reading/writing parameters */
1.1 root 1200: nReadWriteSector++;
1.1.1.2 root 1201: if (nReadWriteSector>nReadWriteSectorsPerTrack) { /* Advance to next track? */
1.1 root 1202: nReadWriteSector = 1;
1203: nReadWriteTrack++;
1204: }
1205: return(TRUE);
1206: }
1207:
1.1.1.2 root 1208: /* Failed */
1.1 root 1209: return(FALSE);
1210: }
1211:
1212:
1.1.1.2 root 1213: /*-----------------------------------------------------------------------*/
1.1 root 1214: /*
1215: Copy data from DMA workspace into ST RAM
1216: */
1217: void FDC_DMADataFromFloppy(void)
1218: {
1.1.1.2 root 1219: /* Copy data to DMA address */
1.1 root 1220: memcpy( (char *)((unsigned long)STRam+FDC_ReadDMAAddress()), DMASectorWorkSpace, NUMBYTESPERSECTOR );
1221:
1.1.1.2 root 1222: /* Update DMA pointer */
1.1 root 1223: FDC_WriteDMAAddress(FDC_ReadDMAAddress()+NUMBYTESPERSECTOR);
1224: }
1225:
1226:
1.1.1.2 root 1227: /*-----------------------------------------------------------------------*/
1.1 root 1228: /*
1229: Write byte to 0xff8604
1230: */
1231: void FDC_WriteDiscController(unsigned short v)
1232: {
1233: DiscControllerWord_ff8604wr = v;
1234: FDC_WriteDiscControllerByte();
1235: }
1236:
1237:
1.1.1.2 root 1238: /*-----------------------------------------------------------------------*/
1.1 root 1239: /*
1240: Read word from 0xff8604
1241: */
1242: short FDC_ReadDiscControllerStatus(void)
1243: {
1244: FDC_ReadDiscControllerStatusByte(); /* Read Status/Track/Sector/Data according to 'DiscControllerWord_ff8604wr' */
1245: return DiscControllerByte;
1246: }
1247:
1248:
1.1.1.2 root 1249: /*-----------------------------------------------------------------------*/
1.1 root 1250: /*
1251: Write word to 0xff8606 (DMA Mode Control)
1252:
1253: Eg.
1254: $80 - Selects command/status register
1255: $82 - Selects track register
1256: $84 - Selects sector register
1257: $86 - Selects data regsiter
1258: NOTE - OR above values with $100 is transfer from memory to floppy
1259: Also if bit 4 is set, write to sector count register
1260: */
1261: void FDC_WriteDMAModeControl(unsigned short v)
1262: {
1263: DMAModeControl_ff8606wr_prev = DMAModeControl_ff8606wr; /* Store previous to check for _read/_write toggle(DMA reset) */
1264: DMAModeControl_ff8606wr = v; /* Store to DMA Mode control */
1265: FDC_CheckForDMAStatusReset();
1266: }
1267:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.