|
|
1.1 root 1: /* Floppy drive emulation */
2:
3:
4: #include "ioMem.h"
5: #include "ioMemTables.h"
6: #include "m68000.h"
7: #include "configuration.h"
8: #include "sysReg.h"
9: #include "dma.h"
10: #include "floppy.h"
11: #include "cycInt.h"
12: #include "file.h"
13: #include "statusbar.h"
14:
15:
16: #define LOG_FLP_REG_LEVEL LOG_DEBUG
17: #define LOG_FLP_CMD_LEVEL LOG_DEBUG
18:
19: #define IO_SEG_MASK 0x1FFFF
20:
21:
22: /* Controller */
23: struct {
24: Uint8 sra; /* Status Register A (ro) */
25: Uint8 srb; /* Status Register B (ro) */
26: Uint8 dor; /* Digital Output Register (rw) */
27: Uint8 msr; /* Main Status Register (ro) */
28: Uint8 dsr; /* Data Rate Select Register (wo) */
29: Uint8 fifo[16]; /* Data FIFO (rw) */
30: Uint8 din; /* Digital Input Register (wo) */
31: Uint8 ccr; /* Configuration Control Register (ro) */
32: Uint8 ctrl; /* External Control (rw) */
33:
34: Uint8 st[4]; /* Internal Status Registers */
35: Uint8 pcn; /* Cylinder Number */
36:
37: Uint8 sel;
38: Uint8 eis;
39: } flp;
40:
41: Uint8 floppy_select = 0;
42:
43: /* Drives */
44: struct {
45: Uint8 cyl;
46: Uint8 head;
47: Uint8 sector;
48: Uint8 blocksize;
49:
50: FILE* dsk;
51: Uint32 floppysize;
52:
53: bool spinning;
54:
55: bool protected;
56: bool inserted;
57: bool connected;
58: } flpdrv[FLP_MAX_DRIVES];
59:
60:
61: /* Register bits */
62:
63: #define SRA_INT 0x80
64: #define SRA_DRV1_N 0x40
65: #define SRA_STEP 0x20
66: #define SRA_TRK0_N 0x10
67: #define SRA_HDSEL 0x08
68: #define SRA_INDEX_N 0x04
69: #define SRA_WP_N 0x02
70: #define SRA_DIR 0x01
71:
72: #define SRB_ALL1 0xC0
73: #define SRB_DRVSEL0_N 0x20
74: #define SRB_W_TOGGLE 0x10
75: #define SRB_R_TOGGLE 0x08
76: #define SRB_W_ENABLE 0x04
77: #define SRB_MOTEN_MASK 0x03
78:
79: #define DOR_MOT3EN 0x80
80: #define DOR_MOT2EN 0x40
81: #define DOR_MOT1EN 0x20
82: #define DOR_MOT0EN 0x10
83: #define DOR_MOTEN_MASK 0xF0
84: #define DOR_DMA_N 0x08
85: #define DOR_RESET_N 0x04
86: #define DOR_SEL_MSK 0x03
87:
88: #define STAT_RQM 0x80
89: #define STAT_DIO 0x40 /* read = 1 */
90: #define STAT_NONDMA 0x20
91: #define STAT_CMDBSY 0x10
92: #define STAT_DRV3BSY 0x08
93: #define STAT_DRV2BSY 0x04
94: #define STAT_DRV1BSY 0x02
95: #define STAT_DRV0BSY 0x01
96: #define STAT_BSY_MASK 0x0F
97:
98: #define DSR_RESET 0x80
99: #define DSR_PDOWN 0x40
100: #define DSR_0 0x20
101: #define DSR_PRE_MASK 0x1C
102: #define DSR_RATE_MASK 0x03
103:
104: #define DIR_DSKCHG 0x80
105: #define DIR_HIDENS_N 0x01
106:
107: #define CCR_RATE_MASK 0x03
108:
109: #define CTRL_EJECT 0x80
110: #define CTRL_82077 0x40
111: #define CTRL_DRV_ID 0x04
112: #define CTRL_MEDIA_ID1 0x02
113: #define CTRL_MEDIA_ID0 0x01
114:
115:
116: /* Functions */
117: void floppy_reset(bool hard);
118: Uint8 floppy_fifo_read(void);
119: void floppy_fifo_write(Uint8 val);
120: Uint8 floppy_dor_read(void);
121: void floppy_dor_write(Uint8 val);
122: Uint8 floppy_sra_read(void);
123:
124:
125: void FLP_StatA_Read(void) { // 0x02014100
126: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = floppy_sra_read();
127: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Status A read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
128: }
129:
130: void FLP_StatB_Read(void) { // 0x02014101
131: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = flp.srb|SRB_ALL1;
132: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Status B read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
133: }
134:
135: void FLP_DataOut_Read(void) { // 0x02014102
136: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = floppy_dor_read();
137: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Data out read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
138: }
139:
140: void FLP_DataOut_Write(void) {
141: floppy_dor_write(IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
142: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Data out write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
143: }
144:
145: void FLP_Status_Read(void) { // 0x02014104
146: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = flp.msr;
147: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Main status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
148: }
149:
150: void FLP_DataRate_Write(void) {
151: flp.dsr = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
152: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Data rate write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
153:
154: if (flp.dsr&DSR_RESET) {
155: floppy_reset(false);
156: flp.dsr&=~DSR_RESET;
157: }
158: }
159:
160: void FLP_FIFO_Read(void) { // 0x02014105
161: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = floppy_fifo_read();
162: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] FIFO read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
163: }
164:
165: void FLP_FIFO_Write(void) {
166: Uint8 val = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
167: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] FIFO write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
168:
169: floppy_fifo_write(val);
170: }
171:
172: void FLP_DataIn_Read(void) { // 0x02014107
173: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = flp.din;
174: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Data in read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
175: }
176:
177: void FLP_Configuration_Write(void) {
178: flp.ccr = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
179: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Configuration write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
180: }
181:
182: void FLP_Control_Read(void) { // 0x02014108
183: Uint8 val;
184: if (ConfigureParams.System.nMachineType==NEXT_CUBE030)
185: val=flp.ctrl&~CTRL_DRV_ID;
186: else
187: val=flp.ctrl;
188:
189: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = val;
190: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
191: }
192:
193: void FLP_Select_Write(void) {
194: Uint8 val;
195: val = IoMem[IoAccessCurrentAddress & IO_SEG_MASK];
196: Log_Printf(LOG_DEBUG,"[Floppy] Select write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
197:
198: if (ConfigureParams.System.nMachineType!=NEXT_CUBE030) {
199: set_floppy_select(val&CTRL_82077,false);
200: }
201:
202: if (val&CTRL_EJECT) {
203: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Ejecting floppy disk");
204: Floppy_Eject(-1);
205: }
206: }
207:
208: void set_floppy_select(Uint8 sel, bool osp) {
209: if (sel) {
210: Log_Printf(LOG_WARN,"[%s] Selecting floppy controller",osp?"OSP":"Floppy");
211: floppy_select = 1;
212: } else {
213: Log_Printf(LOG_FLP_REG_LEVEL,"[%s] Selecting SCSI controller",osp?"OSP":"Floppy");
214: floppy_select = 0;
215: }
216: }
217:
218: enum {
219: FLP_STATE_WRITE,
220: FLP_STATE_READ,
221: FLP_STATE_FORMAT,
222: FLP_STATE_INTERRUPT,
223: FLP_STATE_DONE
224: } flp_io_state;
225:
226: int flp_sector_counter = 0;
227: int flp_io_drv = 0;
228:
229:
230: /* Internal registers */
231:
232: #define ST0_IC 0xC0 /* Interrupt Code (0 = normal termination) */
233: #define ST0_SE 0x20 /* Seek End */
234: #define ST0_EC 0x10 /* Equipment Check */
235: #define ST0_H 0x04 /* Head Address */
236: #define ST0_DS 0x03 /* Drive Select */
237:
238: #define ST1_EN 0x80 /* End of Cylinder */
239: #define ST1_DE 0x20 /* Data Error */
240: #define ST1_OR 0x10 /* Overrun/Underrun */
241: #define ST1_ND 0x04 /* No Data */
242: #define ST1_NW 0x02 /* Not writable */
243: #define ST1_MA 0x01 /* Missing Address Mark */
244:
245: #define ST2_CM 0x40 /* Control Mark */
246: #define ST2_DD 0x20 /* Data Error in Data Field */
247: #define ST2_WC 0x10 /* Wrong Cylinder */
248: #define ST2_BC 0x02 /* Bad Cylinder */
249: #define ST2_MD 0x01 /* Missing Data Address Mark */
250:
251: #define ST3_WP 0x40 /* Write Protected */
252: #define ST3_T0 0x10 /* Track 0 */
253: #define ST3_HD 0x04 /* Head Address */
254: #define ST3_DS 0x03 /* Drive Select */
255:
256:
257: #define IC_NORMAL 0x00
258: #define IC_ABNORMAL 0x40
259: #define IC_INV_CMD 0x80
260:
261:
262:
263: void floppy_reset(bool hard) {
264: Log_Printf(LOG_WARN,"[Floppy] Reset.");
265:
266: flp.sra &= ~(SRA_INT|SRA_STEP|SRA_HDSEL|SRA_DIR);
267: flp.srb &= ~(SRB_R_TOGGLE|SRB_W_TOGGLE);
268: flp.msr |= STAT_RQM;
269: flp.msr &= ~STAT_DIO;
270:
271: if (hard) {
272: flp_io_state = FLP_STATE_DONE;
273: flp.dor &= ~DOR_RESET_N;
274: flp.srb &= ~(SRB_MOTEN_MASK|SRB_DRVSEL0_N);
275: flp.din &= ~DIR_HIDENS_N;
276: flp.st[0]=flp.st[1]=flp.st[2]=flp.st[3]=0;
277: flp.pcn=0;
278: } else {
279: /* Single poll interrupt after reset (FIXME: delay should be 250 ms) */
280: flp_io_state = FLP_STATE_INTERRUPT;
281: CycInt_AddRelativeInterrupt(1000000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
282: }
283: }
284:
285: /* Floppy commands */
286:
287: #define CMD_MT_MSK 0x80
288: #define CMD_MFM_MSK 0x40
289: #define CMD_SK_MSK 0x20
290: #define CMD_OPCODE_MSK 0x1F
291:
292: #define CMD_READ 0x06
293: #define CMD_READ_DEL 0x0C
294: #define CMD_WRITE 0x05
295: #define CMD_WRITE_DEL 0x09
296: #define CMD_READ_TRK 0x02
297: #define CMD_VERIFY 0x16
298: #define CMD_VERSION 0x10
299: #define CMD_FORMAT 0x0D
300: #define CMD_SCAN_E 0x11
301: #define CMD_SCAN_LE 0x19
302: #define CMD_SCAN_HE 0x1D
303: #define CMD_RECAL 0x07
304: #define CMD_INTSTAT 0x08
305: #define CMD_SPECIFY 0x03
306: #define CMD_DRV_STATUS 0x04
307: #define CMD_SEEK 0x0F
308: #define CMD_CONFIGURE 0x13
309: #define CMD_DUMPREG 0x0E
310: #define CMD_READ_ID 0x0A
311: #define CMD_PERPEND 0x12
312: #define CMD_LOCK 0x14
313:
314: Uint8 cmd_data_size[] = {
315: 0,0,8,2,1,8,8,1,
316: 0,8,1,0,8,5,0,2,
317: 0,8,1,3,0,0,8,0,
318: 0,8,0,0,0,8,0,0
319: };
320:
321: bool cmd_phase = false;
322: int cmd_size = 0;
323: int cmd_limit = 0;
324: Uint8 command;
325: Uint8 cmd_data[8];
326:
327: int result_size = 0;
328:
329: void floppy_interrupt(void) {
330: Log_Printf(LOG_FLP_CMD_LEVEL,"[Floppy] Interrupt.");
331:
332: if (result_size>0) {
333: /* Go to result phase */
334: flp.msr |= (STAT_RQM|STAT_DIO);
335: } else {
336: flp.msr |= STAT_RQM;
337: }
338:
339: flp.msr &= ~(STAT_BSY_MASK);
340: flp.sra |= SRA_INT;
341: set_interrupt(INT_PHONE, SET_INT);
342: }
343:
344: /* -- Helpers -- */
345:
346: /* Geometry */
347: #define SIZE_720K 737280
348: #define SIZE_1440K 1474560
349: #define SIZE_2880K 2949120
350:
351: #define NUM_CYLINDERS 80
352: #define TRACKS_PER_CYL 2
353:
354: Uint32 physical_to_logical_sector(Uint8 c, Uint8 h, Uint8 s, int drive) {
355: Uint32 disksize = flpdrv[drive].floppysize;
356: Uint32 blocksize = 0x80<<flpdrv[drive].blocksize;
357: Uint32 spt = disksize/blocksize/TRACKS_PER_CYL/NUM_CYLINDERS;
358:
359: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Geometry: Cylinders: %i, Tracks per cylinder: %i, Sectors per track: %i, Blocksize: %i",
360: NUM_CYLINDERS,TRACKS_PER_CYL,spt,blocksize);
361:
362: if (s>spt) {
363: Log_Printf(LOG_WARN, "[Floppy] Geometry error: sector (%i) beyond limit (%i)!",s,spt);
364: flp.st[0] |= IC_ABNORMAL;
365: flp.st[1] |= ST1_EN;
366: }
367:
368: return (((c*TRACKS_PER_CYL)+h)*spt)+s-1;
369: }
370:
371: void check_blocksize(int drive, Uint8 blocksize) {
372: if (blocksize!=flpdrv[drive].blocksize) {
373: Log_Printf(LOG_WARN, "[Floppy] Geometry error: Blocksize not supported (%i)!",blocksize);
374: flp.st[0] |= IC_ABNORMAL;
375: flp.st[1] |= ST1_ND;
376: }
377: }
378:
379: void check_protection(int drive) {
380: if (flpdrv[drive].protected) {
381: Log_Printf(LOG_WARN, "[Floppy] Protection error: Disk is read-only!");
382: flp.st[0] |= IC_ABNORMAL;
383: flp.st[1] |= ST1_NW;
384: }
385: }
386:
387: void floppy_seek_track(Uint8 c, Uint8 h, int drive) {
388: if (c>(NUM_CYLINDERS-1)) /* CHECK: does this cause an error? */
389: c=(NUM_CYLINDERS-1);
390:
391: flp.st[0] |= ST0_SE;
392: flpdrv[drive].cyl = c;
393: flpdrv[drive].head = h;
394: }
395:
396: /* Media IDs for control register */
397: #define MEDIA_ID_NONE 0
398: #define MEDIA_ID_720K 3
399: #define MEDIA_ID_1440K 2
400: #define MEDIA_ID_2880K 1
401: #define MEDIA_ID_MSK 3
402:
403: Uint8 get_media_id(int drive) {
404: if (!flpdrv[drive].inserted) {
405: return MEDIA_ID_NONE;
406: } else {
407: switch (flpdrv[drive].floppysize) {
408: case SIZE_720K: return MEDIA_ID_720K;
409: case SIZE_1440K: return MEDIA_ID_1440K;
410: case SIZE_2880K: return MEDIA_ID_2880K;
411: default: return MEDIA_ID_NONE;
412: }
413: }
414: }
415:
416: /* Validate data rate */
417: #define CCR_RATE250 0x02
418: #define CCR_RATE500 0x00
419: #define CCR_RATE1000 0x03
420:
421: void check_data_rate(int drive) {
422: switch (flpdrv[drive].floppysize) {
423: case SIZE_720K:
424: if ((flp.ccr&CCR_RATE_MASK)==CCR_RATE250) {
425: return;
426: }
427: break;
428: case SIZE_1440K:
429: if ((flp.ccr&CCR_RATE_MASK)==CCR_RATE500) {
430: return;
431: }
432: break;
433: case SIZE_2880K:
434: if ((flp.ccr&CCR_RATE_MASK)==CCR_RATE1000) {
435: return;
436: }
437: break;
438:
439: default:
440: break;
441: }
442: Log_Printf(LOG_WARN, "[Floppy] Invalid data rate %02X",flp.ccr&CCR_RATE_MASK);
443: flp.st[0] |= IC_ABNORMAL;
444: flp.st[1] |= ST1_ND;
445: }
446:
447: void send_rw_status(int drive) {
448: flp.st[0] |= drive|(flpdrv[drive].head<<2);
449: flp.fifo[0] = flp.st[0];
450: flp.fifo[1] = flp.st[1];
451: flp.fifo[2] = flp.st[2];
452: flp.fifo[3] = flpdrv[drive].cyl;
453: flp.fifo[4] = flpdrv[drive].head;
454: flp.fifo[5] = flpdrv[drive].sector;
455: flp.fifo[6] = flpdrv[drive].blocksize;
456: result_size = 7;
457: }
458:
459: /* -- Floppy commands -- */
460:
461: void floppy_read(void) {
462: int drive = cmd_data[0]&0x03;
463: int head = (cmd_data[0]&0x04)>>2;
464: Uint8 c = cmd_data[1];
465: Uint8 h = cmd_data[2];
466: Uint8 s = cmd_data[3];
467: Uint8 bs = cmd_data[4];
468:
469: Uint32 sector_size, num_sectors, logical_sec;
470:
471: flp.st[0] = flp.st[1] = flp.st[2] = 0;
472:
473: /* If implied seek is enabled, seek track */
474: if (flp.eis) {
475: floppy_seek_track(c, h, drive);
476: }
477: /* Set start sector */
478: flpdrv[drive].sector = s;
479:
480: /* Match actual track with specified track */
481: if (flpdrv[drive].cyl!=c || flpdrv[drive].head!=h || flpdrv[drive].head!=head) {
482: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read: track mismatch!");
483: flp.st[0]|=IC_ABNORMAL;
484: flp.st[2]|=ST2_WC;
485: }
486: /* Validate blocksize */
487: check_blocksize(drive,bs);
488: sector_size = 0x80<<bs;
489:
490: /* Validate data rate */
491: check_data_rate(drive);
492:
493: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read: Cylinder=%i, Head=%i, Sector=%i, Blocksize=%i",
494: flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,sector_size);
495:
496: /* Get sector transfer count and logical sector offset */
497: num_sectors = cmd_data[5]-cmd_data[3]+1;
498: logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive);
499:
500: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read %i sectors at offset %i",num_sectors,logical_sec);
501:
502: if (flp.st[0]&IC_ABNORMAL) {
503: send_rw_status(drive);
504: flp_io_state = FLP_STATE_INTERRUPT;
505: } else {
506: flp_buffer.size = 0;
507: flp_buffer.limit = sector_size;
508: flp_sector_counter = num_sectors;
509: flp_io_drv = drive;
510: flp_io_state = FLP_STATE_READ;
511: }
512: CycInt_AddRelativeInterrupt(1000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
513: }
514:
515: void floppy_write(void) {
516: int drive = cmd_data[0]&0x03;
517: int head = (cmd_data[0]&0x04)>>2;
518: Uint8 c = cmd_data[1];
519: Uint8 h = cmd_data[2];
520: Uint8 s = cmd_data[3];
521: Uint8 bs = cmd_data[4];
522:
523: Uint32 sector_size, num_sectors, logical_sec;
524:
525: flp.st[0] = flp.st[1] = flp.st[2] = 0;
526:
527: /* If implied seek is enabled, seek track */
528: if (flp.eis) {
529: floppy_seek_track(c, h, drive);
530: }
531: /* Set start sector */
532: flpdrv[drive].sector = s;
533:
534: /* Match actual track with specified track */
535: if (flpdrv[drive].cyl!=c || flpdrv[drive].head!=h || flpdrv[drive].head!=head) {
536: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Write: track mismatch!");
537: flp.st[0]|=IC_ABNORMAL;
538: flp.st[2]|=ST2_WC;
539: }
540: /* Validate blocksize */
541: check_blocksize(drive,bs);
542: sector_size = 0x80<<bs;
543:
544: /* Validate data rate */
545: check_data_rate(drive);
546:
547: /* Check protection */
548: check_protection(drive);
549:
550: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Write: Cylinder=%i, Head=%i, Sector=%i, Blocksize=%i",
551: flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,sector_size);
552:
553: /* Get sector transfer count and logical sector offset */
554: num_sectors = cmd_data[5]-cmd_data[3]+1;
555: logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive);
556:
557: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Write %i sectors at offset %i",num_sectors,logical_sec);
558:
559: if (flp.st[0]&IC_ABNORMAL) {
560: send_rw_status(drive);
561: flp_io_state = FLP_STATE_INTERRUPT;
562: } else {
563: flp_buffer.size = 0;
564: flp_buffer.limit = sector_size;
565: flp_sector_counter = num_sectors;
566: flp_io_drv = drive;
567: flp_io_state = FLP_STATE_WRITE;
568: }
569: CycInt_AddRelativeInterrupt(1000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
570: }
571:
572: void floppy_format(void) {
573: int drive = cmd_data[0]&0x03;
574: int head = (cmd_data[0]&0x04)>>2;
575:
576: flp.st[0] = flp.st[1] = flp.st[2] = 0;
577:
578: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Format: Cylinder=%i, Head=%i",flpdrv[drive].cyl,head);
579:
580: /* Validate data rate */
581: check_data_rate(drive);
582:
583: /* Check protection */
584: check_protection(drive);
585:
586: if (flp.st[0]&IC_ABNORMAL) {
587: send_rw_status(drive);
588: flp_io_state = FLP_STATE_INTERRUPT;
589: } else {
590: flp_buffer.size = 0;
591: flp_buffer.limit = 4;
592: flp_io_drv = drive;
593: flp_io_state = FLP_STATE_FORMAT;
594: CycInt_AddRelativeInterrupt(100000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
595: }
596: }
597:
598: void floppy_read_id(void) {
599: int drive = cmd_data[0]&0x03;
600: int head = (cmd_data[0]&0x04)>>2;
601:
602: Uint32 sec_size = 0x80<<flpdrv[drive].blocksize;
603:
604: if (flpdrv[drive].head!=head)
605: abort();
606:
607: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read ID: Cylinder=%i, Head=%i, Sector=%i, Blocksize=%i",
608: flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,sec_size);
609:
610: flp.st[0] = flp.st[1] = flp.st[2] = 0;
611:
612: check_data_rate(drive); /* check data rate */
613: send_rw_status(drive);
614:
615: flp_io_state = FLP_STATE_INTERRUPT;
616: CycInt_AddRelativeInterrupt(1000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
617: }
618:
619: void floppy_recalibrate(void) {
620: int drive = cmd_data[0]&0x03;
621: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Drive = %i",drive);
622:
623: if (flpdrv[drive].connected) {
624: flp.msr |= (1<<drive); /* drive busy */
625: flp.dor &= 0xFC; /* CHECK: really needed? */
626: flp.dor |= drive;
627: flpdrv[drive].cyl = flp.pcn = 0;
628:
629: flp.st[0] = flp.st[1] = flp.st[2] = 0;
630:
631: /* Done */
632: flp.st[0] = IC_NORMAL|ST0_SE;
633: flp.sra &= ~SRA_TRK0_N;
634:
635: flp_io_state = FLP_STATE_INTERRUPT;
636: CycInt_AddRelativeInterrupt(1000000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
637: }
638: }
639:
640: void floppy_seek(Uint8 relative) {
641: int drive = cmd_data[0]&0x03;
642: int head = (cmd_data[0]&0x04)>>2;
643: flp.st[0] = flp.st[1] = flp.st[2] = 0;
644:
645: if (relative) {
646: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Relative seek: Head %i: %i cylinders",head,0);
647: abort();
648: } else {
649: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Seek: Head %i to cylinder %i",head,flpdrv[drive].cyl);
650: flp.st[0] = IC_NORMAL;
651:
652: floppy_seek_track(cmd_data[1], head, drive);
653: if (!(flp.st[0]&IC_ABNORMAL)) {
654: flp.pcn = flpdrv[drive].cyl;
655: }
656: }
657:
658: flp_io_state = FLP_STATE_INTERRUPT;
659: CycInt_AddRelativeInterrupt(1000000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
660: }
661:
662: void floppy_interrupt_status(void) {
663: /* Release interrupt */
664: set_interrupt(INT_PHONE, RELEASE_INT);
665: flp.sra &= ~SRA_INT;
666: /* Go to result phase */
667: flp.msr |= (STAT_RQM|STAT_DIO);
668: /* Return data */
669: flp.fifo[0] = flp.st[0];
670: flp.fifo[1] = flp.pcn;
671: result_size = 2;
672: }
673:
674: void floppy_specify(void) {
675: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Specify: %02X %02X",cmd_data[0],cmd_data[1]);
676:
677: if (cmd_data[1]&0x01) {
678: Log_Printf(LOG_WARN, "[Floppy] Specify: Non-DMA mode");
679: } else {
680: Log_Printf(LOG_WARN, "[Floppy] Specify: DMA mode");
681: }
682: flp.msr |= STAT_RQM;
683: }
684:
685: void floppy_configure(void) {
686: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Configure: %02X %02X %02X",cmd_data[0],cmd_data[1],cmd_data[2]);
687:
688: flp.eis = cmd_data[1]&0x40; /* Enable or disable implied seek */
689:
690: if (cmd_data[1]&0x10) {
691: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Configure: disable polling");
692: if (CycInt_InterruptActive(INTERRUPT_FLP_IO)) {
693: Log_Printf(LOG_WARN, "[Floppy] Disable pending reset poll interrupt");
694: CycInt_RemovePendingInterrupt(INTERRUPT_FLP_IO);
695: }
696: }
697: if (cmd_data[2]) {
698: abort();
699: }
700: flp.msr |= STAT_RQM;
701: }
702:
703: void floppy_perpendicular(void) {
704: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Perpendicular: %02X",cmd_data[0]);
705: flp.msr |= STAT_RQM;
706: }
707:
708: void floppy_unimplemented(void) {
709: flp.st[0] = IC_INV_CMD;
710:
711: flp.fifo[0] = flp.st[0];
712: result_size = 1;
713:
714: flp_io_state = FLP_STATE_INTERRUPT;
715: CycInt_AddRelativeInterrupt(10000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
716: }
717:
718: void floppy_execute_cmd(void) {
719: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Executing %02X",command);
720:
721: switch (command&CMD_OPCODE_MSK) {
722: case CMD_READ:
723: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Read");
724: floppy_read();
725: break;
726: case CMD_READ_DEL:
727: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Read and delete");
728: abort();
729: break;
730: case CMD_WRITE:
731: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Write");
732: floppy_write();
733: break;
734: case CMD_WRITE_DEL:
735: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Write and delete");
736: abort();
737: break;
738: case CMD_READ_TRK:
739: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Read track");
740: abort();
741: break;
742: case CMD_VERIFY:
743: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Verify");
744: abort();
745: break;
746: case CMD_VERSION:
747: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Version");
748: abort();
749: break;
750: case CMD_FORMAT:
751: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Format");
752: floppy_format();
753: break;
754: case CMD_SCAN_E:
755: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Scan equal");
756: abort();
757: break;
758: case CMD_SCAN_LE:
759: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Scan lower or equal");
760: abort();
761: break;
762: case CMD_SCAN_HE:
763: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Scan higher or equal");
764: abort();
765: break;
766: case CMD_RECAL:
767: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Recalibrate");
768: floppy_recalibrate();
769: break;
770: case CMD_INTSTAT:
771: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Interrupt status");
772: floppy_interrupt_status();
773: break;
774: case CMD_SPECIFY:
775: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Specify");
776: floppy_specify();
777: break;
778: case CMD_DRV_STATUS:
779: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Drive status");
780: abort();
781: break;
782: case CMD_SEEK:
783: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Seek");
784: floppy_seek(command&0x80);
785: break;
786: case CMD_CONFIGURE:
787: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Configure");
788: floppy_configure();
789: break;
790: case CMD_DUMPREG:
791: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Dump register");
792: abort();
793: break;
794: case CMD_READ_ID:
795: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Read ID");
796: floppy_read_id();
797: break;
798: case CMD_PERPEND:
799: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Perpendicular");
800: floppy_perpendicular();
801: break;
802: case CMD_LOCK:
803: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Lock");
804: abort();
805: break;
806:
807: default:
808: Log_Printf(LOG_WARN, "[Floppy] Command: Unknown");
809: floppy_unimplemented();
810: break;
811: }
812: Statusbar_BlinkLed(DEVICE_LED_FD);
813: }
814:
815: void floppy_fifo_write(Uint8 val) {
816:
817: flp.msr &= ~STAT_RQM;
818:
819: if (!cmd_phase) {
820: cmd_phase = true;
821: command = val;
822: cmd_limit = cmd_size = cmd_data_size[val&CMD_OPCODE_MSK];
823: flp.msr |= STAT_RQM;
824: } else if (cmd_size>0) {
825: cmd_data[cmd_limit-cmd_size]=val;
826: cmd_size--;
827: flp.msr |= STAT_RQM;
828: }
829:
830: if (cmd_size==0) {
831: cmd_phase = false;
832: floppy_execute_cmd();
833: }
834: }
835:
836: Uint8 floppy_fifo_read(void) {
837: int i;
838: Uint8 val;
839: if (result_size>0) {
840: val = flp.fifo[0];
841: for (i=0; i<(16-1); i++)
842: flp.fifo[i]=flp.fifo[i+1];
843: flp.fifo[16-1] = 0x00;
844: result_size--;
845: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] FIFO reading byte, val=%02x", val);
846: } else {
847: Log_Printf(LOG_WARN,"[Floppy] FIFO is emtpy!");
848: val = 0;
849: }
850:
851: if (result_size==0) {
852: flp.msr |= STAT_RQM;
853: flp.msr &= ~STAT_DIO;
854: /* FIXME: does this really belong here? */
855: set_interrupt(INT_PHONE, RELEASE_INT);
856: flp.sra &= ~SRA_INT;
857: }
858:
859: return val;
860: }
861:
862: void floppy_dor_write(Uint8 val) {
863: if ((val&DOR_SEL_MSK)!=flp.sel) {
864: Log_Printf(LOG_FLP_CMD_LEVEL,"[Floppy] Selecting drive %i.",val&DOR_SEL_MSK);
865: }
866: flp.sel = val&DOR_SEL_MSK;
867:
868: flp.dor &= ~DOR_SEL_MSK;
869: flp.dor |= flp.sel;
870:
871:
872: if (!(val&DOR_RESET_N)) {
873: flp.dor &= ~DOR_RESET_N;
874: floppy_reset(false);
875: } else {
876: flp.dor |= DOR_RESET_N;
877: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Clear reset state.");
878: }
879: if (flpdrv[flp.sel].connected) {
880: flp.ctrl &= ~CTRL_DRV_ID;
881:
882: if (val&(0x10<<flp.sel)) { /* motor enable */
883: Log_Printf(LOG_FLP_CMD_LEVEL,"[Floppy] Starting motor of drive %i.",flp.sel);
884: flp.ctrl &= ~MEDIA_ID_MSK;
885: flp.ctrl |= get_media_id(flp.sel);
886: flpdrv[flp.sel].spinning = true;
887: } else {
888: Log_Printf(LOG_FLP_CMD_LEVEL,"[Floppy] Stopping motor of drive %i.",flp.sel);
889: flp.ctrl &= ~MEDIA_ID_MSK; /* CHECK: really delete ID? */
890: flpdrv[flp.sel].spinning = false;
891: }
892: } else {
893: flp.ctrl |= CTRL_DRV_ID;
894: }
895: }
896:
897: Uint8 floppy_dor_read(void) {
898: int i;
899: Uint8 val = flp.dor&~DOR_MOTEN_MASK; /* clear motor bits */
900: for (i=0; i<FLP_MAX_DRIVES; i++) {
901: if (flpdrv[i].spinning) { /* set motor bit if motor is on */
902: val |= 0x10<<i;
903: }
904: }
905: return val;
906: }
907:
908: Uint8 floppy_sra_read(void) {
909: Uint8 val = flp.sra;
910: if (!flpdrv[flp.sel].protected) {
911: val|=SRA_WP_N;
912: }
913: return val;
914: }
915:
916:
917: /* -- Floppy I/O functions -- */
918:
919: void floppy_rw_nodata(void) {
920: Log_Printf(LOG_WARN, "[Floppy] Write: No more data from DMA. Stopping.");
921: /* Stop transfer */
922: flp_sector_counter=0;
923: flp.st[0] |= IC_ABNORMAL;
924: flp.st[1] |= ST1_OR;
925: send_rw_status(flp_io_drv);
926: }
927:
928: void floppy_format_done(void) {
929: int drive = flp_io_drv;
930:
931: Log_Printf(LOG_WARN, "[Floppy] Format: No more data from DMA. Done.");
932:
933: flp.st[0] = IC_NORMAL;
934: send_rw_status(drive);
935: }
936:
937: void floppy_read_sector(void) {
938: int drive = flp_io_drv;
939:
940: /* Read from image */
941: Uint32 sec_size = 0x80<<flpdrv[drive].blocksize;
942: Uint32 logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive);
943:
944: if (flp.st[0]&IC_ABNORMAL) {
945: Log_Printf(LOG_WARN, "[Floppy] Read error. Bad sector offset (%i).",logical_sec);
946: flp_sector_counter=0; /* stop the transfer */
947: flp_io_state = FLP_STATE_INTERRUPT;
948: send_rw_status(drive);
949: return;
950: } else {
951: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read sector at offset %i",logical_sec);
952:
953: flp_buffer.size = flp_buffer.limit = sec_size;
954: fseek(flpdrv[drive].dsk, logical_sec*sec_size, SEEK_SET);
955: fread(flp_buffer.data, flp_buffer.size, 1, flpdrv[drive].dsk);
956: flpdrv[drive].sector++;
957: flp_sector_counter--;
958: }
959:
960: if (flp_sector_counter==0) {
961: flp.st[0] = IC_ABNORMAL; /* Strange behavior of NeXT hardware */
962: flp.st[1] |= ST1_EN;
963: send_rw_status(drive);
964: }
965: }
966:
967: void floppy_write_sector(void) {
968: int drive = flp_io_drv;
969:
970: /* Write to image */
971: Uint32 sec_size = 0x80<<flpdrv[drive].blocksize;
972: Uint32 logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive);
973:
974: if (flp.st[0]&IC_ABNORMAL) {
975: Log_Printf(LOG_WARN, "[Floppy] Write error. Bad sector offset (%i).",logical_sec);
976: flp_sector_counter=0; /* stop the transfer */
977: flp_io_state = FLP_STATE_INTERRUPT;
978: send_rw_status(drive);
979: return;
980: } else {
981: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Write sector at offset %i",logical_sec);
982:
983: fseek(flpdrv[drive].dsk, logical_sec*sec_size, SEEK_SET);
984: fwrite(flp_buffer.data, flp_buffer.size, 1, flpdrv[drive].dsk);
985: flp_buffer.size = 0;
986: flp_buffer.limit = sec_size;
987: flpdrv[drive].sector++;
988: flp_sector_counter--;
989: }
990:
991: if (flp_sector_counter==0) {
992: flp.st[0] = IC_ABNORMAL; /* Strange behavior of NeXT hardware */
993: flp.st[1] |= ST1_EN;
994: send_rw_status(drive);
995: }
996: }
997:
998: void floppy_format_sector(void) {
999: int drive = flp_io_drv;
1000: Uint8 c = flp_buffer.data[0];
1001: Uint8 h = flp_buffer.data[1];
1002: Uint8 s = flp_buffer.data[2];
1003: Uint8 bs = flp_buffer.data[3];
1004:
1005: if (c!=flpdrv[drive].cyl || h!=flpdrv[drive].head || bs!=flpdrv[drive].blocksize) {
1006: Log_Printf(LOG_WARN, "[Floppy] Format error. Bad sector data. Stopping.");
1007: flp_io_state = FLP_STATE_INTERRUPT; /* This is a hack */
1008: floppy_format_done();
1009: flp_buffer.size = 0;
1010: return;
1011: }
1012: flpdrv[drive].sector = s;
1013:
1014: /* Erase data */
1015: Uint32 sec_size = 0x80<<bs;
1016: Uint32 logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive);
1017: flp_buffer.size = sec_size;
1018: memset(flp_buffer.data, 0, flp_buffer.size);
1019:
1020: if (flp.st[0]&IC_ABNORMAL) {
1021: Log_Printf(LOG_WARN, "[Floppy] Format error. Bad sector offset (%i).",logical_sec);
1022: flp_buffer.size = flp_buffer.limit = 0;
1023: send_rw_status(drive);
1024: } else {
1025: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Format sector at offset %i (%i/%i/%i), blocksize: %i",
1026: logical_sec,c,h,s,sec_size);
1027: fseek(flpdrv[drive].dsk, logical_sec*sec_size, SEEK_SET);
1028: fwrite(flp_buffer.data, flp_buffer.size, 1, flpdrv[drive].dsk);
1029: flp_buffer.size = 0;
1030: flp_buffer.limit = 4;
1031: }
1032: }
1033:
1034:
1035: Uint32 old_size;
1036:
1037: void FLP_IO_Handler(void) {
1038: CycInt_AcknowledgeInterrupt();
1039:
1040: switch (flp_io_state) {
1041: case FLP_STATE_WRITE:
1042: if (flp_buffer.size==flp_buffer.limit) {
1043: floppy_write_sector();
1044: if (flp_sector_counter==0) { /* done */
1045: flp_io_state = FLP_STATE_INTERRUPT;
1046: }
1047: } else if (flp_buffer.size<flp_buffer.limit) { /* loop in filling mode */
1048: old_size = flp_buffer.size;
1049: dma_esp_read_memory();
1050: if (flp_buffer.size==old_size) {
1051: floppy_rw_nodata();
1052: flp_io_state = FLP_STATE_INTERRUPT;
1053: break;
1054: }
1055: }
1056: break;
1057:
1058: case FLP_STATE_READ:
1059: if (flp_buffer.size==0 && flp_sector_counter>0) {
1060: floppy_read_sector();
1061: }
1062: if (flp_buffer.size>0) { /* loop in draining mode */
1063: old_size = flp_buffer.size;
1064: dma_esp_write_memory();
1065: if (flp_buffer.size==old_size) {
1066: floppy_rw_nodata();
1067: flp_io_state = FLP_STATE_INTERRUPT;
1068: break;
1069: }
1070: }
1071: if (flp_buffer.size==0 && flp_sector_counter==0) { /* done */
1072: flp_io_state = FLP_STATE_INTERRUPT;
1073: }
1074: break;
1075:
1076: case FLP_STATE_FORMAT:
1077: if (flp_buffer.size<flp_buffer.limit) {
1078: old_size = flp_buffer.size;
1079: dma_esp_read_memory();
1080: if (flp_buffer.size==old_size) {
1081: floppy_format_done();
1082: flp_io_state = FLP_STATE_INTERRUPT;
1083: break;
1084: }
1085: } else if (flp_buffer.size==flp_buffer.limit) {
1086: floppy_format_sector();
1087: }
1088: break;
1089:
1090: case FLP_STATE_INTERRUPT:
1091: floppy_interrupt();
1092: /* fall through */
1093:
1094: case FLP_STATE_DONE:
1095: return;
1096:
1097: default:
1098: return;
1099: }
1100:
1101: CycInt_AddRelativeInterrupt(2000, INT_CPU_CYCLE, INTERRUPT_FLP_IO);
1102: }
1103:
1104:
1105: /* Initialize/Uninitialize floppy disks */
1106:
1107: void Floppy_Init(void) {
1108: Log_Printf(LOG_WARN, "Loading floppy disks:");
1109: int i;
1110:
1111: for (i=0; i<FLP_MAX_DRIVES; i++) {
1112: flpdrv[i].spinning=false;
1113: /* Check if files exist. */
1114: if (ConfigureParams.Floppy.drive[i].bDriveConnected) {
1115: flpdrv[i].connected=true;
1116: if (ConfigureParams.Floppy.drive[i].bDiskInserted &&
1117: File_Exists(ConfigureParams.Floppy.drive[i].szImageName)) {
1118: Floppy_Insert(i);
1119: } else {
1120: flpdrv[i].dsk = NULL;
1121: flpdrv[i].inserted=false;
1122: }
1123: } else {
1124: flpdrv[i].connected=false;
1125: }
1126: }
1127:
1128: floppy_reset(true);
1129: }
1130:
1131: void Floppy_Uninit(void) {
1132: if (flpdrv[0].dsk)
1133: File_Close(flpdrv[0].dsk);
1134: if (flpdrv[1].dsk) {
1135: File_Close(flpdrv[1].dsk);
1136: }
1137: flpdrv[0].dsk = flpdrv[1].dsk = NULL;
1138: flpdrv[0].inserted = flpdrv[1].inserted = false;
1139: }
1140:
1141: Uint32 Floppy_CheckSize(int drive) {
1142: Uint32 size = File_Length(ConfigureParams.Floppy.drive[drive].szImageName);
1143:
1144: switch (size) {
1145: case SIZE_720K:
1146: case SIZE_1440K:
1147: case SIZE_2880K:
1148: return size;
1149:
1150: default:
1151: Log_Printf(LOG_WARN, "Floppy Disk%i: Invalid size (%i byte)\n",drive,size);
1152: return 0;
1153: }
1154: }
1155:
1156: int Floppy_Insert(int drive) {
1157: Uint32 size;
1158:
1159: /* Check floppy size. */
1160: size = Floppy_CheckSize(drive);
1161: if (size) {
1162: flpdrv[drive].floppysize = size;
1163: flpdrv[drive].blocksize = 2; /* 512 byte */
1164: } else {
1165: flpdrv[drive].dsk = NULL;
1166: flpdrv[drive].inserted=false;
1167: flpdrv[drive].floppysize = 0;
1168: return 1; /* bad size, do not insert */
1169: }
1170:
1171: if (ConfigureParams.Floppy.drive[drive].bWriteProtected) {
1172: flpdrv[drive].dsk = File_Open(ConfigureParams.Floppy.drive[drive].szImageName, "rb");
1173: flpdrv[drive].protected=true;
1174: } else {
1175: flpdrv[drive].dsk = File_Open(ConfigureParams.Floppy.drive[drive].szImageName, "rb+");
1176: flpdrv[drive].protected=false;
1177: }
1178:
1179: flpdrv[drive].inserted=true;
1180: flpdrv[drive].spinning=false;
1181:
1182: Log_Printf(LOG_WARN, "Floppy Disk%i: %s, %iK\n",drive,
1183: ConfigureParams.Floppy.drive[drive].szImageName,flpdrv[drive].floppysize/1024);
1184:
1185: Statusbar_AddMessage("Inserting floppy disk.", 0);
1186:
1187: return 0;
1188: }
1189:
1190: void Floppy_Eject(int drive) {
1191: if (drive<0) { /* Called from emulator, else called from GUI */
1192: drive=flp.sel;
1193:
1194: Statusbar_AddMessage("Ejecting floppy disk.", 0);
1195: }
1196:
1197: Log_Printf(LOG_WARN, "Unloading floppy disk %i",drive);
1198: Log_Printf(LOG_WARN, "Floppy disk %i: Eject",drive);
1199:
1200: File_Close(flpdrv[drive].dsk);
1201: flpdrv[drive].floppysize = 0;
1202: flpdrv[drive].blocksize = 0;
1203: flpdrv[drive].dsk=NULL;
1204: flpdrv[drive].inserted=false;
1205: flpdrv[drive].spinning=false;
1206:
1207: ConfigureParams.Floppy.drive[drive].bDiskInserted=false;
1208: ConfigureParams.Floppy.drive[drive].szImageName[0]='\0';
1209: }
1210:
1211: void Floppy_Reset(void) {
1212: Floppy_Uninit();
1213: Floppy_Init();
1214: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.