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