First Commit of my working state
[simh.git] / AltairZ80 / vfdhd.c
CommitLineData
196ba1fc
PH
1/*************************************************************************\r
2 * *\r
3 * $Id: vfdhd.c 1773 2008-01-11 05:46:19Z hharte $ *\r
4 * *\r
5 * Copyright (c) 2007-2008 Howard M. Harte. *\r
6 * http://www.hartetec.com *\r
7 * *\r
8 * Permission is hereby granted, free of charge, to any person obtaining *\r
9 * a copy of this software and associated documentation files (the *\r
10 * "Software"), to deal in the Software without restriction, including *\r
11 * without limitation the rights to use, copy, modify, merge, publish, *\r
12 * distribute, sublicense, and/or sell copies of the Software, and to *\r
13 * permit persons to whom the Software is furnished to do so, subject to *\r
14 * the following conditions: *\r
15 * *\r
16 * The above copyright notice and this permission notice shall be *\r
17 * included in all copies or substantial portions of the Software. *\r
18 * *\r
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *\r
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *\r
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *\r
22 * NONINFRINGEMENT. IN NO EVENT SHALL HOWARD M. HARTE BE LIABLE FOR ANY *\r
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *\r
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *\r
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *\r
26 * *\r
27 * Except as contained in this notice, the name of Howard M. Harte shall *\r
28 * not be used in advertising or otherwise to promote the sale, use or *\r
29 * other dealings in this Software without prior written authorization *\r
30 * Howard M. Harte. *\r
31 * *\r
32 * SIMH Interface based on altairz80_hdsk.c, by Peter Schorn. *\r
33 * *\r
34 * Module Description: *\r
35 * Micropolis FDC module for SIMH *\r
36 * *\r
37 * Environment: *\r
38 * User mode only *\r
39 * *\r
40 *************************************************************************/\r
41\r
42/*#define DBG_MSG */\r
43#define USE_VGI /* Use 275-byte VGI-format sectors (includes all metadata) */\r
44\r
45#include "altairz80_defs.h"\r
46\r
47#if defined (_WIN32)\r
48#include <windows.h>\r
49#endif\r
50\r
51#include "sim_imd.h"\r
52\r
53#ifdef DBG_MSG\r
54#define DBG_PRINT(args) printf args\r
55#else\r
56#define DBG_PRINT(args)\r
57#endif\r
58\r
59#define SEEK_MSG 0x01\r
60#define ORDERS_MSG 0x02\r
61#define CMD_MSG 0x04\r
62#define RD_DATA_MSG 0x08\r
63#define WR_DATA_MSG 0x10\r
64#define STATUS_MSG 0x20\r
65\r
66static void VFDHD_Command(void);\r
67\r
68#define VFDHD_MAX_DRIVES 4\r
69\r
70#define VFDHD_SECTOR_LEN 275\r
71\r
72typedef union {\r
73 struct {\r
74 uint8 preamble[40]; /* Hard disk uses 30 bytes of preamble, floppy uses 40. */\r
75 uint8 sync;\r
76 uint8 header[2];\r
77 uint8 unused[10];\r
78 uint8 data[256];\r
79 uint8 checksum;\r
80 uint8 ecc[4];\r
81 uint8 ecc_valid; /* 0xAA indicates ECC is being used. */\r
82 uint8 postamble[128];\r
83 } u;\r
84 uint8 raw[VFDHD_SECTOR_LEN];\r
85\r
86} SECTOR_FORMAT;\r
87\r
88typedef struct {\r
89 UNIT *uptr;\r
90 DISK_INFO *imd;\r
91 uint16 ntracks; /* number of tracks */\r
92 uint8 nheads; /* number of heads */\r
93 uint8 nspt; /* number of sectors per track */\r
94 uint8 npre_len; /* preamble length */\r
95 uint32 sectsize; /* sector size, not including pre/postamble */\r
96 uint16 track;\r
97 uint8 wp; /* Disk write protected */\r
98 uint8 ready; /* Drive is ready */\r
99 uint8 write_fault;\r
100 uint8 seek_complete;\r
101 uint8 sync_lost;\r
102 uint32 sector_wait_count;\r
103} VFDHD_DRIVE_INFO;\r
104\r
105typedef struct {\r
106 PNP_INFO pnp; /* Plug and Play */\r
107 uint8 xfr_flag; /* Indicates controller is ready to send/receive data */\r
108 uint8 sel_drive; /* Currently selected drive */\r
109 uint8 selected; /* 1 if drive is selected */\r
110 uint8 track0; /* Set it selected drive is on track 0 */\r
111 uint8 head; /* Currently selected head */\r
112 uint8 wr_latch; /* Write enable latch */\r
113 uint8 int_enable; /* Interrupt Enable */\r
114 uint32 datacount; /* Number of data bytes transferred from controller for current sector */\r
115 uint8 step;\r
116 uint8 direction;\r
117 uint8 rwc;\r
118 uint8 sector;\r
119 uint8 read;\r
120 uint8 ecc_enable;\r
121 uint8 precomp;\r
122\r
123 uint8 floppy_sel;\r
124 uint8 controller_busy;\r
125 uint8 motor_on;\r
126 uint8 hdsk_type;\r
127 VFDHD_DRIVE_INFO drive[VFDHD_MAX_DRIVES];\r
128} VFDHD_INFO;\r
129\r
130static VFDHD_INFO vfdhd_info_data = { { 0x0, 0, 0xC0, 4 } };\r
131static VFDHD_INFO *vfdhd_info = &vfdhd_info_data;\r
132\r
133static SECTOR_FORMAT sdata;\r
134extern uint32 PCX;\r
135extern t_stat set_iobase(UNIT *uptr, int32 val, char *cptr, void *desc);\r
136extern t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, void *desc);\r
137extern uint32 sim_map_resource(uint32 baseaddr, uint32 size, uint32 resource_type,\r
138 int32 (*routine)(const int32, const int32, const int32), uint8 unmap);\r
139\r
140#define UNIT_V_VFDHD_WLK (UNIT_V_UF + 0) /* write locked */\r
141#define UNIT_VFDHD_WLK (1 << UNIT_V_VFDHD_WLK)\r
142#define UNIT_V_VFDHD_VERBOSE (UNIT_V_UF + 1) /* verbose mode, i.e. show error messages */\r
143#define UNIT_VFDHD_VERBOSE (1 << UNIT_V_VFDHD_VERBOSE)\r
144#define VFDHD_CAPACITY (77*2*16*256) /* Default Micropolis Disk Capacity */\r
145#define IMAGE_TYPE_DSK 1 /* Flat binary "DSK" image file. */\r
146#define IMAGE_TYPE_IMD 2 /* ImageDisk "IMD" image file. */\r
147#define IMAGE_TYPE_CPT 3 /* CP/M Transfer "CPT" image file. */\r
148\r
149static t_stat vfdhd_reset(DEVICE *vfdhd_dev);\r
150static t_stat vfdhd_attach(UNIT *uptr, char *cptr);\r
151static t_stat vfdhd_detach(UNIT *uptr);\r
152\r
153static int32 vfdhddev(const int32 port, const int32 io, const int32 data);\r
154\r
155static uint8 VFDHD_Read(const uint32 Addr);\r
156static uint8 VFDHD_Write(const uint32 Addr, uint8 cData);\r
157\r
158static int32 trace_level = FALSE;\r
159static int32 hdSize = 5;\r
160\r
161static UNIT vfdhd_unit[] = {\r
162 { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) },\r
163 { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) },\r
164 { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) },\r
165 { UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, VFDHD_CAPACITY) }\r
166};\r
167\r
168static REG vfdhd_reg[] = {\r
169 { HRDATA (TRACELEVEL, trace_level, 16), },\r
170 { DRDATA (HDSIZE, hdSize, 10), },\r
171 { NULL }\r
172};\r
173\r
174static MTAB vfdhd_mod[] = {\r
175 { MTAB_XTD|MTAB_VDV, 0, "IOBASE", "IOBASE", &set_iobase, &show_iobase, NULL },\r
176 { UNIT_VFDHD_WLK, 0, "WRTENB", "WRTENB", NULL },\r
177 { UNIT_VFDHD_WLK, UNIT_VFDHD_WLK, "WRTLCK", "WRTLCK", NULL },\r
178 /* quiet, no warning messages */\r
179 { UNIT_VFDHD_VERBOSE, 0, "QUIET", "QUIET", NULL },\r
180 /* verbose, show warning messages */\r
181 { UNIT_VFDHD_VERBOSE, UNIT_VFDHD_VERBOSE, "VERBOSE", "VERBOSE", NULL },\r
182 { 0 }\r
183};\r
184\r
185DEVICE vfdhd_dev = {\r
186 "VFDHD", vfdhd_unit, vfdhd_reg, vfdhd_mod,\r
187 VFDHD_MAX_DRIVES, 10, 31, 1, VFDHD_MAX_DRIVES, VFDHD_MAX_DRIVES,\r
188 NULL, NULL, &vfdhd_reset,\r
189 NULL, &vfdhd_attach, &vfdhd_detach,\r
190 &vfdhd_info_data, (DEV_DISABLE | DEV_DIS), 0,\r
191 NULL, NULL, NULL\r
192};\r
193\r
194/* Reset routine */\r
195static t_stat vfdhd_reset(DEVICE *dptr)\r
196{\r
197 PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt;\r
198\r
199 if(dptr->flags & DEV_DIS) {\r
200 sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &vfdhddev, TRUE);\r
201 } else {\r
202 /* Connect MFDC at base address */\r
203 if(sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &vfdhddev, FALSE) != 0) {\r
204 printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->io_base);\r
205 return SCPE_ARG;\r
206 }\r
207 }\r
208 return SCPE_OK;\r
209}\r
210\r
211\r
212/* Attach routine */\r
213static t_stat vfdhd_attach(UNIT *uptr, char *cptr)\r
214{\r
215 char header[4];\r
216 t_stat r;\r
217 unsigned int i = 0;\r
218\r
219 r = attach_unit(uptr, cptr); /* attach unit */\r
220 if ( r != SCPE_OK) /* error? */\r
221 return r;\r
222\r
223 /* Determine length of this disk */\r
224 uptr->capac = sim_fsize(uptr->fileref);\r
225\r
226 for(i = 0; i < VFDHD_MAX_DRIVES; i++) {\r
227 vfdhd_info->drive[i].uptr = &vfdhd_dev.units[i];\r
228 }\r
229\r
230 for(i = 0; i < VFDHD_MAX_DRIVES; i++) {\r
231 if(vfdhd_dev.units[i].fileref == uptr->fileref) {\r
232 break;\r
233 }\r
234 }\r
235\r
236 if(uptr->capac > 0) {\r
237 fgets(header, 4, uptr->fileref);\r
238 if(!strcmp(header, "IMD")) {\r
239 uptr->u3 = IMAGE_TYPE_IMD;\r
240 } else if(!strcmp(header, "CPT")) {\r
241 printf("CPT images not yet supported\n");\r
242 uptr->u3 = IMAGE_TYPE_CPT;\r
243 vfdhd_detach(uptr);\r
244 return SCPE_OPENERR;\r
245 } else {\r
246 uptr->u3 = IMAGE_TYPE_DSK;\r
247 }\r
248 } else {\r
249 /* creating file, must be DSK format. */\r
250 uptr->u3 = IMAGE_TYPE_DSK;\r
251 }\r
252\r
253 if (uptr->flags & UNIT_VFDHD_VERBOSE)\r
254 printf("VFDHD%d: attached to '%s', type=%s, len=%d\n", i, cptr,\r
255 uptr->u3 == IMAGE_TYPE_IMD ? "IMD" : uptr->u3 == IMAGE_TYPE_CPT ? "CPT" : "DSK",\r
256 uptr->capac);\r
257\r
258 if(uptr->u3 == IMAGE_TYPE_IMD) {\r
259 if(uptr->capac < 318000) {\r
260 printf("Cannot create IMD files with SIMH.\nCopy an existing file and format it with CP/M.\n");\r
261 vfdhd_detach(uptr);\r
262 return SCPE_OPENERR;\r
263 }\r
264\r
265 if (uptr->flags & UNIT_VFDHD_VERBOSE)\r
266 printf("--------------------------------------------------------\n");\r
267 vfdhd_info->drive[i].imd = diskOpen((uptr->fileref), (uptr->flags & UNIT_VFDHD_VERBOSE));\r
268 printf("\n");\r
269 } else {\r
270 vfdhd_info->drive[i].imd = NULL;\r
271 }\r
272\r
273 if(i>0) { /* Floppy Disk, Unit 1-3 */\r
274 vfdhd_info->drive[i].ntracks = 77; /* number of tracks */\r
275 vfdhd_info->drive[i].nheads = 2; /* number of heads */\r
276 vfdhd_info->drive[i].nspt = 16; /* number of sectors per track */\r
277 vfdhd_info->drive[i].npre_len = 40; /* preamble length */\r
278 vfdhd_info->drive[i].sectsize = VFDHD_SECTOR_LEN; /* sector size, not including pre/postamble */\r
279 } else { /* Hard Disk, Unit 0 */\r
280 if(hdSize == 10) {\r
281 vfdhd_info->drive[i].ntracks = 153; /* number of tracks */\r
282 vfdhd_info->drive[i].nheads = 6; /* number of heads */\r
283 vfdhd_info->hdsk_type = 1;\r
284 printf("10MB\n");\r
285 } else if (hdSize == 5) {\r
286 vfdhd_info->drive[i].ntracks = 153; /* number of tracks */\r
287 vfdhd_info->drive[i].nheads = 4; /* number of heads */\r
288 vfdhd_info->hdsk_type = 0;\r
289 printf("5MB\n");\r
290 } else {\r
291 vfdhd_info->drive[i].ntracks = 512; /* number of tracks */\r
292 vfdhd_info->drive[i].nheads = 8; /* number of heads */\r
293 vfdhd_info->hdsk_type = 1;\r
294 printf("32MB\n");\r
295 }\r
296\r
297 vfdhd_info->drive[i].nheads = 4; /* number of heads */\r
298 vfdhd_info->drive[i].nspt = 32; /* number of sectors per track */\r
299 vfdhd_info->drive[i].npre_len = 30; /* preamble length */\r
300 vfdhd_info->drive[i].sectsize = VFDHD_SECTOR_LEN; /* sector size, not including pre/postamble */\r
301 vfdhd_info->drive[i].ready = 1;\r
302 vfdhd_info->drive[i].seek_complete = 1;\r
303 vfdhd_info->drive[i].sync_lost = 1; /* Active LOW */\r
304 }\r
305\r
306 vfdhd_info->motor_on = 1;\r
307 return SCPE_OK;\r
308}\r
309\r
310\r
311/* Detach routine */\r
312static t_stat vfdhd_detach(UNIT *uptr)\r
313{\r
314 t_stat r;\r
315 int8 i;\r
316\r
317 for(i = 0; i < VFDHD_MAX_DRIVES; i++) {\r
318 if(vfdhd_dev.units[i].fileref == uptr->fileref) {\r
319 break;\r
320 }\r
321 }\r
322\r
323 DBG_PRINT(("Detach VFDHD%d\n", i));\r
324 diskClose(vfdhd_info->drive[i].imd);\r
325\r
326 r = detach_unit(uptr); /* detach unit */\r
327 if ( r != SCPE_OK)\r
328 return r;\r
329\r
330 return SCPE_OK;\r
331}\r
332\r
333\r
334static uint8 cy;\r
335static uint8 adc(uint8 sum, uint8 a1)\r
336{\r
337 uint32 total;\r
338\r
339 total = sum + a1 + cy;\r
340\r
341 if(total > 0xFF) {\r
342 cy = 1;\r
343 } else {\r
344 cy = 0;\r
345 }\r
346\r
347 return(total & 0xFF);\r
348}\r
349\r
350static int32 vfdhddev(const int32 port, const int32 io, const int32 data)\r
351{\r
352 DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " IO %s, Port %02x" NLP, PCX, io ? "WR" : "RD", port));\r
353 if(io) {\r
354 VFDHD_Write(port, data);\r
355 return 0;\r
356 } else {\r
357 return(VFDHD_Read(port));\r
358 }\r
359}\r
360\r
361#define FDHD_CTRL_STATUS0 0 /* R=Status Port 0, W=Control Port 0 */\r
362#define FDHD_CTRL_STATUS1 1 /* R=Status Port 1, W=Control Port 0 */\r
363#define FDHD_DATA 2 /* R/W=Data Port */\r
364#define FDHD_RESET_START 3 /* R=RESET, W=START */\r
365\r
366static uint8 VFDHD_Read(const uint32 Addr)\r
367{\r
368 uint8 cData;\r
369 VFDHD_DRIVE_INFO *pDrive;\r
370\r
371 pDrive = &vfdhd_info->drive[vfdhd_info->sel_drive];\r
372\r
373 cData = 0x00;\r
374\r
375 switch(Addr & 0x3) {\r
376 case FDHD_CTRL_STATUS0:\r
377 cData = (pDrive->wp & 1); /* [0] Write Protect (FD) */\r
378 cData |= (pDrive->ready & 1) << 1; /* [1] Drive ready (HD) */\r
379 cData |= (pDrive->track == 0) ? 0x04 : 0; /* [2] TK0 (FD/HD) */\r
380 cData |= (pDrive->write_fault & 1) << 3; /* [3] Write Fault (HD) */\r
381 cData |= (pDrive->seek_complete & 1) << 4; /* [4] Seek Complete (HD) */\r
382 cData |= (pDrive->sync_lost & 1) << 5; /* [5] Loss of Sync (HD) */\r
383 cData |= 0xC0; /* [7:6] Reserved (pulled up) */\r
384 TRACE_PRINT(STATUS_MSG, ("VFDHD: " ADDRESS_FORMAT " RD S0 = 0x%02x" NLP, PCX, cData));\r
385 break;\r
386 case FDHD_CTRL_STATUS1:\r
387 vfdhd_info->floppy_sel = (vfdhd_info->sel_drive == 0) ? 0 : 1;\r
388 cData = (vfdhd_info->floppy_sel & 0x1); /* [0] Floppy Selected */\r
389 cData |= (vfdhd_info->controller_busy & 0x1) << 1; /* [1] Controller busy */\r
390 cData |= (vfdhd_info->motor_on & 0x1) << 2; /* [2] Motor On (FD) */\r
391 cData |= (vfdhd_info->hdsk_type & 0x1) << 3; /* [3] Hard Disk Type (0=5MB, 1=10MB) */\r
392 cData |= 0xF0; /* [7:4] Reserved (pulled up) */\r
393 if(vfdhd_info->sel_drive == 0) {\r
394/* cData &= 0xF0; */\r
395 }\r
396\r
397 vfdhd_info->controller_busy = 0;\r
398\r
399 TRACE_PRINT(STATUS_MSG, ("VFDHD: " ADDRESS_FORMAT " RD S1 = 0x%02x" NLP, PCX, cData));\r
400 break;\r
401 case FDHD_DATA:\r
402/* DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " RD Data" NLP, PCX)); */\r
403 cData = sdata.raw[vfdhd_info->datacount+40];\r
404\r
405 vfdhd_info->datacount++;\r
406\r
407/* DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " RD Data Sector %d[%03d]: 0x%02x" NLP, PCX, pDrive->sector, vfdhd_info->datacount, cData)); */\r
408 break;\r
409 case FDHD_RESET_START: /* Reset */\r
410 TRACE_PRINT(CMD_MSG, ("VFDHD: " ADDRESS_FORMAT " Reset" NLP, PCX));\r
411 vfdhd_info->datacount = 0;\r
412 cData = 0xFF; /* Return High-Z data */\r
413 break;\r
414 }\r
415\r
416 return (cData);\r
417}\r
418\r
419static uint8 VFDHD_Write(const uint32 Addr, uint8 cData)\r
420{\r
421 VFDHD_DRIVE_INFO *pDrive;\r
422\r
423 pDrive = &vfdhd_info->drive[vfdhd_info->sel_drive];\r
424\r
425 switch(Addr & 0x3) {\r
426 case FDHD_CTRL_STATUS0:\r
427 vfdhd_info->sel_drive = cData & 3;\r
428 vfdhd_info->head = (cData >> 2) & 0x7;\r
429 vfdhd_info->step = (cData >> 5) & 1;\r
430 vfdhd_info->direction = (cData >> 6) & 1;\r
431 vfdhd_info->rwc = (cData >> 7) & 1;\r
432\r
433 TRACE_PRINT(WR_DATA_MSG, ("VFDHD: " ADDRESS_FORMAT " WR C0=%02x: sel_drive=%d, head=%d, step=%d, dir=%d, rwc=%d" NLP,\r
434 PCX,\r
435 cData,\r
436 vfdhd_info->sel_drive,\r
437 vfdhd_info->head,\r
438 vfdhd_info->step,\r
439 vfdhd_info->direction,\r
440 vfdhd_info->rwc));\r
441\r
442 if(vfdhd_info->step == 1) {\r
443 if(vfdhd_info->direction == 1) { /* Step IN */\r
444 pDrive->track++;\r
445 } else { /* Step OUT */\r
446 if(pDrive->track != 0) {\r
447 pDrive->track--;\r
448 }\r
449 }\r
450 TRACE_PRINT(SEEK_MSG, ("VFDHD: " ADDRESS_FORMAT " Drive %d on track %d" NLP,\r
451 PCX, vfdhd_info->sel_drive, pDrive->track));\r
452 }\r
453\r
454 break;\r
455 case FDHD_CTRL_STATUS1:\r
456 vfdhd_info->sector = (cData & 0x1f);\r
457 vfdhd_info->read = (cData >> 5) & 1;\r
458 vfdhd_info->ecc_enable = (cData >> 6) & 1;\r
459 vfdhd_info->precomp = (cData >> 7) & 1;\r
460 if(cData == 0xFF) {\r
461 TRACE_PRINT(SEEK_MSG, ("VFDHD: " ADDRESS_FORMAT " Home Disk %d" NLP,\r
462 PCX, vfdhd_info->sel_drive));\r
463 pDrive->track = 0;\r
464 }\r
465 DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " WR C1=%02x: sector=%d, read=%d, ecc_en=%d, precomp=%d" NLP,\r
466 PCX,\r
467 cData,\r
468 vfdhd_info->sector,\r
469 vfdhd_info->read,\r
470 vfdhd_info->ecc_enable,\r
471 vfdhd_info->precomp));\r
472 break;\r
473 case FDHD_DATA: /* Data Port */\r
474 DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " WR Data" NLP, PCX));\r
475#ifdef USE_VGI\r
476 if(vfdhd_info->sel_drive > 0) { /* Floppy */\r
477 sdata.raw[vfdhd_info->datacount] = cData;\r
478 } else { /* Hard */\r
479 sdata.raw[vfdhd_info->datacount+10] = cData;\r
480 }\r
481#else\r
482 sdata.u.data[vfdhd_info->datacount-13] = cData;\r
483#endif /* USE_VGI */\r
484\r
485 vfdhd_info->datacount ++;\r
486\r
487 break;\r
488 case FDHD_RESET_START:\r
489 TRACE_PRINT(CMD_MSG, ("VFDHD: " ADDRESS_FORMAT " Start Command" NLP, PCX));\r
490 VFDHD_Command();\r
491 break;\r
492 }\r
493\r
494 cData = 0x00;\r
495\r
496 return (cData);\r
497}\r
498\r
499static void VFDHD_Command(void)\r
500{\r
501 VFDHD_DRIVE_INFO *pDrive;\r
502\r
503 uint32 bytesPerTrack;\r
504 uint32 bytesPerHead;\r
505\r
506 uint32 sec_offset;\r
507 uint32 flags;\r
508\r
509 pDrive = &(vfdhd_info->drive[vfdhd_info->sel_drive]);\r
510\r
511 bytesPerTrack = pDrive->sectsize * pDrive->nspt;\r
512 bytesPerHead = bytesPerTrack * pDrive->ntracks;\r
513\r
514 sec_offset = (pDrive->track * bytesPerTrack) + \\r
515 (vfdhd_info->head * bytesPerHead) + \\r
516 (vfdhd_info->sector * pDrive->sectsize);\r
517\r
518 vfdhd_info->controller_busy = 1;\r
519\r
520 if(vfdhd_info->read == 1) { /* Perform a Read operation */\r
521 unsigned int i, checksum;\r
522 unsigned int readlen;\r
523\r
524 TRACE_PRINT(RD_DATA_MSG, ("VFDHD: " ADDRESS_FORMAT " RD: Drive=%d, Track=%d, Head=%d, Sector=%d" NLP,\r
525 PCX,\r
526 vfdhd_info->sel_drive,\r
527 pDrive->track,\r
528 vfdhd_info->head,\r
529 vfdhd_info->sector));\r
530\r
531 /* Clear out unused portion of sector. */\r
532 memset(&sdata.u.unused[0], 0x00, 10);\r
533\r
534 sdata.u.sync = 0xFF;\r
535 sdata.u.header[0] = pDrive->track & 0xFF;\r
536 sdata.u.header[1] = vfdhd_info->sector;\r
537\r
538 switch((pDrive->uptr)->u3)\r
539 {\r
540 case IMAGE_TYPE_IMD:\r
541 if(pDrive->imd == NULL) {\r
542 printf(".imd is NULL!" NLP);\r
543 }\r
544 printf("%s: Read: imd=%p" NLP, __FUNCTION__, pDrive->imd);\r
545 sectRead(pDrive->imd,\r
546 pDrive->track,\r
547 vfdhd_info->head,\r
548 vfdhd_info->sector,\r
549 sdata.u.data,\r
550 256,\r
551 &flags,\r
552 &readlen);\r
553\r
554 adc(0,0); /* clear Carry bit */\r
555 checksum = 0;\r
556\r
557 /* Checksum everything except the sync byte */\r
558 for(i=1;i<269;i++) {\r
559 checksum = adc(checksum, sdata.raw[i]);\r
560 }\r
561\r
562 sdata.u.checksum = checksum & 0xFF;\r
563 sdata.u.ecc_valid = 0xAA;\r
564 break;\r
565 case IMAGE_TYPE_DSK:\r
566 if(pDrive->uptr->fileref == NULL) {\r
567 printf(".fileref is NULL!" NLP);\r
568 } else {\r
569 fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);\r
570 fread(&sdata.u.sync, 274, /*VFDHD_SECTOR_LEN,*/ 1, (pDrive->uptr)->fileref);\r
571\r
572 memset(&sdata.u.preamble, 0, 40);\r
573 memset(&sdata.u.ecc, 0, 5); /* Clear out the ECC and ECC Valid bytes */\r
574 sdata.u.ecc_valid = 0xAA;\r
575 for(vfdhd_info->datacount = 0; sdata.raw[vfdhd_info->datacount] == 0x00; vfdhd_info->datacount++) {\r
576 }\r
577\r
578 DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " READ: Sync found at offset %d" NLP, PCX, vfdhd_info->datacount));\r
579\r
580 }\r
581 break;\r
582 case IMAGE_TYPE_CPT:\r
583 printf("%s: CPT Format not supported" NLP, __FUNCTION__);\r
584 break;\r
585 default:\r
586 printf("%s: Unknown image Format" NLP, __FUNCTION__);\r
587 break;\r
588 }\r
589\r
590 } else { /* Perform a Write operation */\r
591 unsigned int writelen;\r
592\r
593 TRACE_PRINT(WR_DATA_MSG, ("VFDHD: " ADDRESS_FORMAT " WR: Drive=%d, Track=%d, Head=%d, Sector=%d" NLP,\r
594 PCX,\r
595 vfdhd_info->sel_drive,\r
596 pDrive->track,\r
597 vfdhd_info->head,\r
598 vfdhd_info->sector));\r
599\r
600#ifdef USE_VGI\r
601#else\r
602 int data_index = vfdhd_info->datacount - 13;\r
603\r
604 sec_offset = (pDrive->track * 4096) + \\r
605 (vfdhd_info->head * 315392) + \\r
606 (vfdhd_info->sector * 256);\r
607#endif /* USE_VGI */\r
608\r
609 switch((pDrive->uptr)->u3)\r
610 {\r
611 case IMAGE_TYPE_IMD:\r
612 if(pDrive->imd == NULL) {\r
613 printf(".imd is NULL!" NLP);\r
614 }\r
615 sectWrite(pDrive->imd,\r
616 pDrive->track,\r
617 vfdhd_info->head,\r
618 vfdhd_info->sector,\r
619 sdata.u.data,\r
620 256,\r
621 &flags,\r
622 &writelen);\r
623 break;\r
624 case IMAGE_TYPE_DSK:\r
625 if(pDrive->uptr->fileref == NULL) {\r
626 printf(".fileref is NULL!" NLP);\r
627 } else {\r
628 DBG_PRINT(("VFDHD: " ADDRESS_FORMAT " WR drive=%d, track=%d, head=%d, sector=%d" NLP,\r
629 PCX,\r
630 vfdhd_info->sel_drive,\r
631 pDrive->track,\r
632 vfdhd_info->head,\r
633 vfdhd_info->sector));\r
634 fseek((pDrive->uptr)->fileref, sec_offset, SEEK_SET);\r
635#ifdef USE_VGI\r
636 fwrite(&sdata.u.sync, VFDHD_SECTOR_LEN, 1, (pDrive->uptr)->fileref);\r
637#else\r
638 fwrite(sdata.u.data, 256, 1, (pDrive->uptr)->fileref);\r
639#endif /* USE_VGI */\r
640 }\r
641 break;\r
642 case IMAGE_TYPE_CPT:\r
643 printf("%s: CPT Format not supported" NLP, __FUNCTION__);\r
644 break;\r
645 default:\r
646 printf("%s: Unknown image Format" NLP, __FUNCTION__);\r
647 break;\r
648 }\r
649 }\r
650}\r