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