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