1 /*************************************************************************
3 * $Id: mfdc.c 1773 2008-01-11 05:46:19Z hharte $ *
5 * Copyright (c) 2007-2008 Howard M. Harte. *
6 * http://www.hartetec.com *
8 * Permission is hereby granted, free of charge, to any person obtaining *
9 * a copy of this software and associated documentation files (the *
10 * "Software"), to deal in the Software without restriction, including *
11 * without limitation the rights to use, copy, modify, merge, publish, *
12 * distribute, sublicense, and/or sell copies of the Software, and to *
13 * permit persons to whom the Software is furnished to do so, subject to *
14 * the following conditions: *
16 * The above copyright notice and this permission notice shall be *
17 * included in all copies or substantial portions of the Software. *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
22 * NONINFRINGEMENT. IN NO EVENT SHALL HOWARD M. HARTE BE LIABLE FOR ANY *
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
27 * Except as contained in this notice, the name of Howard M. Harte shall *
28 * not be used in advertising or otherwise to promote the sale, use or *
29 * other dealings in this Software without prior written authorization *
32 * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. *
34 * Module Description: *
35 * Micropolis FD Control module for SIMH. *
36 * See the "Vector Using MDOS Revision 8.4" manual at: *
37 * www.hartetechnologies.com/manuals in the Vector Graphic section *
38 * for details of the on-disk sector format and programming information. *
43 *************************************************************************/
46 #define USE_VGI /* Use 275-byte VGI-format sectors (includes all metadata) */
48 #include "altairz80_defs.h"
56 #define DBG_PRINT(args) printf args
58 #define DBG_PRINT(args)
62 #define ORDERS_MSG 0x02
64 #define RD_DATA_MSG 0x08
65 #define WR_DATA_MSG 0x10
66 #define STATUS_MSG 0x20
69 extern t_stat
set_membase(UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
70 extern t_stat
show_membase(FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
71 extern uint32
sim_map_resource(uint32 baseaddr
, uint32 size
, uint32 resource_type
,
72 int32 (*routine
)(const int32
, const int32
, const int32
), uint8 unmap
);
73 extern int32
find_unit_index(UNIT
*uptr
);
75 static void MFDC_Command(uint8 cData
);
77 #define MFDC_MAX_DRIVES 4
78 #define JUMPER_W9 1 /* Not Installed (0) = 2MHz, Installed (1) = 4MHz. */
81 #define MFDC_SECTOR_LEN 275
91 uint8 ecc_valid
; /* Not used for Micropolis FDC, but is used by FDHD. */
93 uint8 raw
[MFDC_SECTOR_LEN
];
101 uint8 wp
; /* Disk write protected */
102 uint8 ready
; /* Drive is ready */
103 uint8 sector
; /* Current Sector number */
104 uint32 sector_wait_count
;
108 PNP_INFO pnp
; /* Plug and Play */
109 uint8 xfr_flag
; /* Indicates controller is ready to send/receive data */
110 uint8 sel_drive
; /* Currently selected drive */
111 uint8 selected
; /* 1 if drive is selected */
112 uint8 track0
; /* Set it selected drive is on track 0 */
113 uint8 head
; /* Currently selected head */
114 uint8 wr_latch
; /* Write enable latch */
115 uint8 int_enable
; /* Interrupt Enable */
116 uint32 datacount
; /* Number of data bytes transferred from controller for current sector */
117 uint8 read_in_progress
; /* TRUE if a read is in progress */
118 MFDC_DRIVE_INFO drive
[MFDC_MAX_DRIVES
];
121 static MFDC_INFO mfdc_info_data
= { { 0xF800, 1024, 0, 0 } };
122 static MFDC_INFO
*mfdc_info
= &mfdc_info_data
;
124 static SECTOR_FORMAT sdata
;
126 #define UNIT_V_MFDC_WLK (UNIT_V_UF + 0) /* write locked */
127 #define UNIT_MFDC_WLK (1 << UNIT_V_MFDC_WLK)
128 #define UNIT_V_MFDC_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */
129 #define UNIT_MFDC_VERBOSE (1 << UNIT_V_MFDC_VERBOSE)
130 #define MFDC_CAPACITY (77*16*MFDC_SECTOR_LEN) /* Default Micropolis Disk Capacity */
131 #define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */
132 #define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */
133 #define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */
135 static t_stat
mfdc_reset(DEVICE
*mfdc_dev
);
136 static t_stat
mfdc_attach(UNIT
*uptr
, char *cptr
);
137 static t_stat
mfdc_detach(UNIT
*uptr
);
138 static uint8
MFDC_Read(const uint32 Addr
);
139 static uint8
MFDC_Write(const uint32 Addr
, uint8 cData
);
141 static int32
mdskdev(const int32 Addr
, const int32 rw
, const int32 data
);
143 static int32 trace_level
= 0;
145 static UNIT mfdc_unit
[] = {
146 { UDATA (NULL
, UNIT_FIX
+ UNIT_ATTABLE
+ UNIT_DISABLE
+ UNIT_ROABLE
, MFDC_CAPACITY
) },
147 { UDATA (NULL
, UNIT_FIX
+ UNIT_ATTABLE
+ UNIT_DISABLE
+ UNIT_ROABLE
, MFDC_CAPACITY
) },
148 { UDATA (NULL
, UNIT_FIX
+ UNIT_ATTABLE
+ UNIT_DISABLE
+ UNIT_ROABLE
, MFDC_CAPACITY
) },
149 { UDATA (NULL
, UNIT_FIX
+ UNIT_ATTABLE
+ UNIT_DISABLE
+ UNIT_ROABLE
, MFDC_CAPACITY
) }
152 static REG mfdc_reg
[] = {
153 { HRDATA (TRACELEVEL
, trace_level
, 16), },
157 static MTAB mfdc_mod
[] = {
158 { MTAB_XTD
|MTAB_VDV
, 0, "MEMBASE", "MEMBASE", &set_membase
, &show_membase
, NULL
},
159 { UNIT_MFDC_WLK
, 0, "WRTENB", "WRTENB", NULL
},
160 { UNIT_MFDC_WLK
, UNIT_MFDC_WLK
, "WRTLCK", "WRTLCK", NULL
},
161 /* quiet, no warning messages */
162 { UNIT_MFDC_VERBOSE
, 0, "QUIET", "QUIET", NULL
},
163 /* verbose, show warning messages */
164 { UNIT_MFDC_VERBOSE
, UNIT_MFDC_VERBOSE
, "VERBOSE", "VERBOSE", NULL
},
169 "MDSK", mfdc_unit
, mfdc_reg
, mfdc_mod
,
170 MFDC_MAX_DRIVES
, 10, 31, 1, MFDC_MAX_DRIVES
, MFDC_MAX_DRIVES
,
171 NULL
, NULL
, &mfdc_reset
,
172 NULL
, &mfdc_attach
, &mfdc_detach
,
173 &mfdc_info_data
, (DEV_DISABLE
| DEV_DIS
), 0,
177 /* Micropolis FD Control Boot ROM
178 * This ROM code is runtime-relocatable. See Appendix F of the "Vector Using MDOS Revision 8.4"
179 * manual at www.hartetechnologies.com/manuals in the Vector Graphic section.
181 static uint8 mfdc_rom
[256] = {
182 0xF3, 0x21, 0xA2, 0x00, 0xF9, 0x36, 0xC9, 0xCD, 0xA2, 0x00, 0xEB, 0x2A, 0xA0, 0x00, 0x2E, 0x00, /* 0x00 */
183 0xE5, 0x01, 0x1D, 0x00, 0x09, 0xE5, 0xE1, 0x0E, 0x1A, 0x09, 0x06, 0xBD, 0xEB, 0x3B, 0x3B, 0x1A, /* 0x10 */
184 0x77, 0xBE, 0xC0, 0x23, 0x13, 0x05, 0xC0, 0xE1, 0x2A, 0xA0, 0x00, 0x11, 0x00, 0x02, 0x19, 0x22, /* 0x20 */
185 0xA2, 0x00, 0x36, 0xA0, 0xC3, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xA2, 0x00, 0x7E, 0xE6, /* 0x30 */
186 0x80, 0xCA, 0xA9, 0x00, 0x7E, 0xE6, 0x0F, 0xA8, 0xC2, 0xA9, 0x00, 0x23, 0xB6, 0xF2, 0xB7, 0x00, /* 0x40 */
187 0x23, 0x7E, 0xAF, 0xEB, 0x06, 0x00, 0x00, 0x00, 0x1A, 0x77, 0x23, 0x88, 0x47, 0x1A, 0x77, 0x23, /* 0x50 */
188 0x88, 0x47, 0x0D, 0xC2, 0xC3, 0x00, 0x1A, 0xB8, 0xC9, 0x2A, 0xA2, 0x00, 0x36, 0x20, 0x23, 0x7E, /* 0x60 */
189 0x2B, 0xE6, 0x24, 0xEE, 0x20, 0xC2, 0xD4, 0x00, 0x0E, 0x5E, 0xCD, 0x49, 0x01, 0x23, 0x7E, 0x2B, /* 0x70 */
190 0xE6, 0x24, 0xEE, 0x20, 0xC2, 0xD4, 0x00, 0x23, 0x7E, 0xE6, 0x08, 0x2B, 0xCA, 0x07, 0x01, 0x06, /* 0x80 */
191 0x08, 0x36, 0x61, 0x0E, 0x0F, 0xCD, 0x49, 0x01, 0x05, 0xC2, 0xFC, 0x00, 0x23, 0x7E, 0xE6, 0x08, /* 0x90 */
192 0x2B, 0xC2, 0x19, 0x01, 0x36, 0x60, 0x0E, 0x0F, 0xCD, 0x49, 0x01, 0xC3, 0x07, 0x01, 0x21, 0x5F, /* 0xA0 */
193 0x01, 0xCD, 0x37, 0x01, 0xC2, 0xD4, 0x00, 0x2A, 0x69, 0x02, 0x22, 0xA4, 0x00, 0xCD, 0x37, 0x01, /* 0xB0 */
194 0xC2, 0xD4, 0x00, 0x2A, 0xA4, 0x00, 0x11, 0x0C, 0x00, 0x19, 0xD1, 0xE9, 0xE5, 0xEB, 0x01, 0x86, /* 0xC0 */
195 0x00, 0xCD, 0xA6, 0x00, 0xE1, 0xC2, 0x37, 0x01, 0xE5, 0x7E, 0x23, 0xB6, 0xE1, 0xC9, 0x7E, 0xE6, /* 0xD0 */
196 0x20, 0x79, 0xC2, 0x51, 0x01, 0x07, 0x4F, 0x3E, 0xFF, 0xD6, 0x01, 0xB7, 0xC2, 0x54, 0x01, 0x0D, /* 0xE0 */
197 0xC2, 0x52, 0x01, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xA6, 0x00 /* 0xF0 */
201 t_stat
mfdc_reset(DEVICE
*dptr
)
204 PNP_INFO
*pnp
= (PNP_INFO
*)dptr
->ctxt
;
206 if(dptr
->flags
& DEV_DIS
) {
207 sim_map_resource(pnp
->mem_base
, pnp
->mem_size
, RESOURCE_TYPE_MEMORY
, &mdskdev
, TRUE
);
209 /* Connect MFDC at base address */
210 for(i
= 0; i
< MFDC_MAX_DRIVES
; i
++) {
211 mfdc_info
->drive
[i
].uptr
= &mfdc_dev
.units
[i
];
213 if(sim_map_resource(pnp
->mem_base
, pnp
->mem_size
, RESOURCE_TYPE_MEMORY
, &mdskdev
, FALSE
) != 0) {
214 printf("%s: error mapping resource at 0x%04x\n", __FUNCTION__
, pnp
->mem_base
);
215 dptr
->flags
|= DEV_DIS
;
223 t_stat
mfdc_attach(UNIT
*uptr
, char *cptr
)
229 r
= attach_unit(uptr
, cptr
); /* attach unit */
230 if ( r
!= SCPE_OK
) /* error? */
233 /* Determine length of this disk */
234 if(sim_fsize(uptr
->fileref
) != 0) {
235 uptr
->capac
= sim_fsize(uptr
->fileref
);
237 uptr
->capac
= MFDC_CAPACITY
;
240 i
= find_unit_index(uptr
);
242 /* Default for new file is DSK */
243 uptr
->u3
= IMAGE_TYPE_DSK
;
245 if(uptr
->capac
> 0) {
246 fgets(header
, 4, uptr
->fileref
);
247 if(!strcmp(header
, "IMD")) {
248 uptr
->u3
= IMAGE_TYPE_IMD
;
249 } else if(!strcmp(header
, "CPT")) {
250 printf("CPT images not yet supported\n");
251 uptr
->u3
= IMAGE_TYPE_CPT
;
255 uptr
->u3
= IMAGE_TYPE_DSK
;
259 if (uptr
->flags
& UNIT_MFDC_VERBOSE
)
260 printf("MDSK%d, attached to '%s', type=%s, len=%d\n", i
, cptr
,
261 uptr
->u3
== IMAGE_TYPE_IMD
? "IMD" : uptr
->u3
== IMAGE_TYPE_CPT
? "CPT" : "DSK",
264 if(uptr
->u3
== IMAGE_TYPE_IMD
) {
265 if(uptr
->capac
< 318000) {
266 printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n");
271 if (uptr
->flags
& UNIT_MFDC_VERBOSE
)
272 printf("--------------------------------------------------------\n");
273 mfdc_info
->drive
[i
].imd
= diskOpen((uptr
->fileref
), (uptr
->flags
& UNIT_MFDC_VERBOSE
));
274 if (uptr
->flags
& UNIT_MFDC_VERBOSE
)
277 mfdc_info
->drive
[i
].imd
= NULL
;
285 t_stat
mfdc_detach(UNIT
*uptr
)
290 for(i
= 0; i
< MFDC_MAX_DRIVES
; i
++) {
291 if(mfdc_dev
.units
[i
].fileref
== uptr
->fileref
) {
296 if (i
>= MFDC_MAX_DRIVES
) return SCPE_ARG
;
298 DBG_PRINT(("Detach MFDC%d\n", i
));
299 diskClose(mfdc_info
->drive
[i
].imd
);
301 r
= detach_unit(uptr
); /* detach unit */
311 static uint8
adc(uint8 sum
, uint8 a1
)
315 total
= sum
+ a1
+ cy
;
323 return(total
& 0xFF);
326 /* Main Entry Point for Memory-Mapped I/O to the Micropolis FD Control Board
328 * The controller is typically located at 0xF800 in the Memory Map, and occupies
329 * 1K of address space. Accesses are broken down as follows:
331 * 0xF800-0xF8FF: Bootstrap ROM
332 * 0xF900-0xF9FF: Nothing (reads 0xFF)
333 * 0xFA00-0xFBFF: Controller registers: there are four registers, which are shadowed
334 * throughout this 512-byte range.
336 * The controller can be relocated on any 1K boundary in the memory map, and since the
337 * boot ROM code is runtime relocatable, it moves with the controller registers.
339 static int32
mdskdev(const int32 Addr
, const int32 rw
, const int32 data
)
341 switch(Addr
& 0x300) {
342 case 0x000: /* Boot ROM */
343 if(rw
== 0) { /* Read boot ROM */
344 return(mfdc_rom
[Addr
& 0xFF]);
346 printf("MFDC: Attempt to write to boot ROM." NLP
);
350 case 0x100: /* Nothing */
354 case 0x300: /* Controller Registers */
355 if(rw
== 0) { /* Read Register */
356 return(MFDC_Read(Addr
));
357 } else { /* Write Register */
358 return(MFDC_Write(Addr
, data
));
367 static uint8
MFDC_Read(const uint32 Addr
)
370 MFDC_DRIVE_INFO
*pDrive
;
374 pDrive
= &mfdc_info
->drive
[mfdc_info
->sel_drive
];
378 if(mfdc_info
->read_in_progress
== FALSE
) {
379 pDrive
->sector_wait_count
++;
380 if(pDrive
->sector_wait_count
> 10) {
382 pDrive
->sector
&= 0x0F; /* Max of 16 sectors */
383 mfdc_info
->wr_latch
= 0; /* on new sector, disable the write latch */
384 DBG_PRINT(("Head over sector %d" NLP
, pDrive
->sector
));
385 pDrive
->sector_wait_count
= 0;
389 cData
= (pDrive
->sector
) & 0xF; /* [3:0] current sector */
390 cData
|= (JUMPER_W10
<< 4);
391 cData
|= ((~JUMPER_W9
) & 1) << 5;
392 cData
|= (0 << 6); /* Sector Interrupt Flag, reset by RESET command or Interrupt Disable */
393 cData
|= (1 << 7); /* Sector Flag */
394 mfdc_info
->xfr_flag
= 1; /* Drive has data */
395 mfdc_info
->datacount
= 0;
396 TRACE_PRINT(STATUS_MSG
, ("MFDC: " ADDRESS_FORMAT
" RD Sector Register = 0x%02x" NLP
, PCX
, cData
));
399 cData
= (mfdc_info
->sel_drive
& 0x3); /* [1:0] selected drive */
400 cData
|= (!mfdc_info
->selected
<< 2); /* [2] drive is selected */
401 cData
|= (pDrive
->track
== 0) ? 0x08 : 0; /* [3] TK0 */
402 pDrive
->wp
= ((pDrive
->uptr
)->flags
& UNIT_MFDC_WLK
) ? 1 : 0;
403 cData
|= (pDrive
->wp
<< 4); /* [4] Write Protect */
404 cData
|= (pDrive
->ready
<< 5); /* [5] Drive Ready */
405 cData
|= (0 << 6); /* [6] PINTE from S-100 Bus */
406 cData
|= (mfdc_info
->xfr_flag
<< 7); /* [7] Transfer Flag */
408 TRACE_PRINT(STATUS_MSG
, ("MFDC: " ADDRESS_FORMAT
" RD Status = 0x%02x" NLP
, PCX
, cData
));
412 if(mfdc_info
->datacount
== 0) {
413 unsigned int i
, checksum
;
414 unsigned long sec_offset
;
416 unsigned int readlen
;
418 /* Clear out unused portion of sector. */
419 memset(&sdata
.u
.unused
[0], 0x00, 10);
422 sdata
.u
.header
[0] = pDrive
->track
;
423 sdata
.u
.header
[1] = pDrive
->sector
;
425 TRACE_PRINT(RD_DATA_MSG
, ("MFDC: " ADDRESS_FORMAT
" RD Data T:%d S:[%d]" NLP
,
431 sec_offset
= (pDrive
->track
* MFDC_SECTOR_LEN
* 16) + \
432 (pDrive
->sector
* MFDC_SECTOR_LEN
);
434 sec_offset
= (pDrive
->track
* 4096) + \
435 (pDrive
->sector
* 256);
438 if (!(pDrive
->uptr
->flags
& UNIT_ATT
)) {
439 if (pDrive
->uptr
->flags
& UNIT_MFDC_VERBOSE
)
440 printf("MFDC: " ADDRESS_FORMAT
" MDSK%i not attached." NLP
, PCX
,
441 mfdc_info
->sel_drive
);
445 switch((pDrive
->uptr
)->u3
)
448 if(pDrive
->imd
== NULL
) {
449 printf(".imd is NULL!" NLP
);
451 /* printf("%s: Read: imd=%p" NLP, __FUNCTION__, pDrive->imd); */
452 sectRead(pDrive
->imd
,
462 if(pDrive
->uptr
->fileref
== NULL
) {
463 printf(".fileref is NULL!" NLP
);
465 fseek((pDrive
->uptr
)->fileref
, sec_offset
, SEEK_SET
);
467 fread(sdata
.raw
, MFDC_SECTOR_LEN
, 1, (pDrive
->uptr
)->fileref
);
469 fread(sdata
.u
.data
, 256, 1, (pDrive
->uptr
)->fileref
);
474 printf("%s: CPT Format not supported" NLP
, __FUNCTION__
);
477 printf("%s: Unknown image Format" NLP
, __FUNCTION__
);
481 /* printf("%d/%d @%04x Len=%04x" NLP, sdata.u.header[0], sdata.u.header[1], sdata.u.header[9]<<8|sdata.u.header[8], sdata.u.header[11]<<8|sdata.u.header[10]); */
483 adc(0,0); /* clear Carry bit */
486 /* Checksum everything except the sync byte */
488 checksum
= adc(checksum
, sdata
.raw
[i
]);
491 sdata
.u
.checksum
= checksum
& 0xFF;
492 /* DBG_PRINT(("Checksum=%x" NLP, sdata.u.checksum)); */
493 mfdc_info
->read_in_progress
= TRUE
;
496 cData
= sdata
.raw
[mfdc_info
->datacount
];
498 mfdc_info
->datacount
++;
499 if(mfdc_info
->datacount
== 270) {
500 TRACE_PRINT(RD_DATA_MSG
, ("MFDC: " ADDRESS_FORMAT
" Read sector [%d] complete" NLP
,
501 PCX
, pDrive
->sector
));
502 mfdc_info
->read_in_progress
= FALSE
;
505 /* DBG_PRINT(("MFDC: " ADDRESS_FORMAT " RD Data Sector %d[%03d]: 0x%02x" NLP, PCX, pDrive->sector, mfdc_info->datacount, cData)); */
512 static uint8
MFDC_Write(const uint32 Addr
, uint8 cData
)
514 unsigned int sec_offset
;
515 unsigned int flags
= 0;
516 unsigned int writelen
;
517 MFDC_DRIVE_INFO
*pDrive
;
519 pDrive
= &mfdc_info
->drive
[mfdc_info
->sel_drive
];
528 /* DBG_PRINT(("MFDC: " ADDRESS_FORMAT " WR Data" NLP, PCX)); */
529 if(mfdc_info
->wr_latch
== 0) {
530 printf("MFDC: " ADDRESS_FORMAT
" Error, attempt to write data when write latch is not set." NLP
, PCX
);
533 sec_offset
= (pDrive
->track
* MFDC_SECTOR_LEN
* 16) + \
534 (pDrive
->sector
* MFDC_SECTOR_LEN
);
536 sdata
.raw
[mfdc_info
->datacount
] = cData
;
538 int data_index
= mfdc_info
->datacount
- 13;
540 sec_offset
= (pDrive
->track
* 4096) + \
541 (pDrive
->sector
* 256);
543 if((data_index
>= 0) && (data_index
< 256)) {
544 DBG_PRINT(("writing data [%03d]=%02x" NLP
, data_index
, cData
));
546 sdata
.u
.data
[data_index
] = cData
;
552 mfdc_info
->datacount
++;
554 if(mfdc_info
->datacount
== 270) {
555 TRACE_PRINT(WR_DATA_MSG
, ("MFDC: " ADDRESS_FORMAT
" WR Data T:%d S:[%d]" NLP
,
560 if (!(pDrive
->uptr
->flags
& UNIT_ATT
)) {
561 if (pDrive
->uptr
->flags
& UNIT_MFDC_VERBOSE
)
562 printf("MFDC: " ADDRESS_FORMAT
" MDSK%i not attached." NLP
, PCX
,
563 mfdc_info
->sel_drive
);
567 switch((pDrive
->uptr
)->u3
)
570 if(pDrive
->imd
== NULL
) {
571 printf(".imd is NULL!" NLP
);
573 sectWrite(pDrive
->imd
,
583 if(pDrive
->uptr
->fileref
== NULL
) {
584 printf(".fileref is NULL!" NLP
);
586 fseek((pDrive
->uptr
)->fileref
, sec_offset
, SEEK_SET
);
588 fwrite(sdata
.raw
, MFDC_SECTOR_LEN
, 1, (pDrive
->uptr
)->fileref
);
590 fwrite(sdata
.u
.data
, 256, 1, (pDrive
->uptr
)->fileref
);
595 printf("%s: CPT Format not supported" NLP
, __FUNCTION__
);
598 printf("%s: Unknown image Format" NLP
, __FUNCTION__
);
611 #define MFDC_CMD_NOP 0
612 #define MFDC_CMD_SELECT 1
613 #define MFDC_CMD_INTR 2
614 #define MFDC_CMD_STEP 3
615 #define MFDC_CMD_SET_WRITE 4
616 #define MFDC_CMD_RESET 5
618 static void MFDC_Command(uint8 cData
)
622 MFDC_DRIVE_INFO
*pDrive
;
624 pDrive
= &mfdc_info
->drive
[mfdc_info
->sel_drive
];
627 cCommand
= cData
>> 5;
628 cModifier
= cData
& 0x1F;
632 TRACE_PRINT(CMD_MSG
, ("MFDC: " ADDRESS_FORMAT
" No Op." NLP
, PCX
));
634 case MFDC_CMD_SELECT
:
635 mfdc_info
->sel_drive
= cModifier
& 3;
636 mfdc_info
->head
= (cModifier
& 0x10) >> 4;
637 mfdc_info
->selected
= TRUE
;
639 if(pDrive
->uptr
->fileref
!= NULL
) {
645 TRACE_PRINT(CMD_MSG
, ("MFDC: " ADDRESS_FORMAT
" Select Drive: %d, Head: %s" NLP
,
646 PCX
, mfdc_info
->sel_drive
, (mfdc_info
->head
) ? "Upper" : "Lower"));
649 mfdc_info
->int_enable
= cModifier
& 1; /* 0=int disable, 1=enable */
650 TRACE_PRINT(CMD_MSG
, ("MFDC: " ADDRESS_FORMAT
" Interrupts %s." NLP
,
651 PCX
, mfdc_info
->int_enable
? "Enabled" : "Disabled"));
654 if(cModifier
& 1) { /* Step IN */
657 else { /* Step OUT */
658 if(pDrive
->track
!= 0) {
663 TRACE_PRINT(SEEK_MSG
, ("MFDC: " ADDRESS_FORMAT
" Step %s, Track=%d." NLP
,
664 PCX
, (cModifier
& 1) ? "IN" : "OUT", pDrive
->track
));
667 case MFDC_CMD_SET_WRITE
:
668 TRACE_PRINT(CMD_MSG
, ("MFDC: " ADDRESS_FORMAT
" Set WRITE." NLP
, PCX
));
669 mfdc_info
->wr_latch
= 1; /* Allow writes for the current sector */
670 mfdc_info
->datacount
= 0; /* reset the byte counter */
673 TRACE_PRINT(CMD_MSG
, ("MFDC: " ADDRESS_FORMAT
" Reset Controller." NLP
, PCX
));
674 mfdc_info
->selected
= 0; /* de-select the drive */
675 mfdc_info
->wr_latch
= 0; /* Disable the write latch */
676 mfdc_info
->datacount
= 0; /* reset the byte counter */
679 TRACE_PRINT(CMD_MSG
, ("MFDC: " ADDRESS_FORMAT
" Unsupported command." NLP
, PCX
));