f0033b8629b29528ab89944dde9556ca8e188e64
[qemu] / hw / fdc.c
1 /*
2  * QEMU Floppy disk emulator (Intel 82078)
3  *
4  * Copyright (c) 2003, 2007 Jocelyn Mayer
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 /*
25  * The controller is used in Sun4m systems in a slightly different
26  * way. There are changes in DOR register and DMA is not available.
27  */
28 #include "vl.h"
29
30 /********************************************************/
31 /* debug Floppy devices */
32 //#define DEBUG_FLOPPY
33
34 #ifdef DEBUG_FLOPPY
35 #define FLOPPY_DPRINTF(fmt, args...) \
36 do { printf("FLOPPY: " fmt , ##args); } while (0)
37 #else
38 #define FLOPPY_DPRINTF(fmt, args...)
39 #endif
40
41 #define FLOPPY_ERROR(fmt, args...) \
42 do { printf("FLOPPY ERROR: %s: " fmt, __func__ , ##args); } while (0)
43
44 /********************************************************/
45 /* Floppy drive emulation                               */
46
47 /* Will always be a fixed parameter for us */
48 #define FD_SECTOR_LEN 512
49 #define FD_SECTOR_SC  2   /* Sector size code */
50
51 /* Floppy disk drive emulation */
52 typedef enum fdisk_type_t {
53     FDRIVE_DISK_288   = 0x01, /* 2.88 MB disk           */
54     FDRIVE_DISK_144   = 0x02, /* 1.44 MB disk           */
55     FDRIVE_DISK_720   = 0x03, /* 720 kB disk            */
56     FDRIVE_DISK_USER  = 0x04, /* User defined geometry  */
57     FDRIVE_DISK_NONE  = 0x05, /* No disk                */
58 } fdisk_type_t;
59
60 typedef enum fdrive_type_t {
61     FDRIVE_DRV_144  = 0x00,   /* 1.44 MB 3"5 drive      */
62     FDRIVE_DRV_288  = 0x01,   /* 2.88 MB 3"5 drive      */
63     FDRIVE_DRV_120  = 0x02,   /* 1.2  MB 5"25 drive     */
64     FDRIVE_DRV_NONE = 0x03,   /* No drive connected     */
65 } fdrive_type_t;
66
67 typedef enum fdrive_flags_t {
68     FDRIVE_MOTOR_ON   = 0x01, /* motor on/off           */
69 } fdrive_flags_t;
70
71 typedef enum fdisk_flags_t {
72     FDISK_DBL_SIDES  = 0x01,
73 } fdisk_flags_t;
74
75 typedef struct fdrive_t {
76     BlockDriverState *bs;
77     /* Drive status */
78     fdrive_type_t drive;
79     fdrive_flags_t drflags;
80     uint8_t perpendicular;    /* 2.88 MB access mode    */
81     /* Position */
82     uint8_t head;
83     uint8_t track;
84     uint8_t sect;
85     /* Last operation status */
86     uint8_t dir;              /* Direction              */
87     uint8_t rw;               /* Read/write             */
88     /* Media */
89     fdisk_flags_t flags;
90     uint8_t last_sect;        /* Nb sector per track    */
91     uint8_t max_track;        /* Nb of tracks           */
92     uint16_t bps;             /* Bytes per sector       */
93     uint8_t ro;               /* Is read-only           */
94 } fdrive_t;
95
96 static void fd_init (fdrive_t *drv, BlockDriverState *bs)
97 {
98     /* Drive */
99     drv->bs = bs;
100     drv->drive = FDRIVE_DRV_NONE;
101     drv->drflags = 0;
102     drv->perpendicular = 0;
103     /* Disk */
104     drv->last_sect = 0;
105     drv->max_track = 0;
106 }
107
108 static int _fd_sector (uint8_t head, uint8_t track,
109                        uint8_t sect, uint8_t last_sect)
110 {
111     return (((track * 2) + head) * last_sect) + sect - 1;
112 }
113
114 /* Returns current position, in sectors, for given drive */
115 static int fd_sector (fdrive_t *drv)
116 {
117     return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect);
118 }
119
120 static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
121                     int enable_seek)
122 {
123     uint32_t sector;
124     int ret;
125
126     if (track > drv->max_track ||
127         (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
128         FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
129                        head, track, sect, 1,
130                        (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
131                        drv->max_track, drv->last_sect);
132         return 2;
133     }
134     if (sect > drv->last_sect) {
135         FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
136                        head, track, sect, 1,
137                        (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
138                        drv->max_track, drv->last_sect);
139         return 3;
140     }
141     sector = _fd_sector(head, track, sect, drv->last_sect);
142     ret = 0;
143     if (sector != fd_sector(drv)) {
144 #if 0
145         if (!enable_seek) {
146             FLOPPY_ERROR("no implicit seek %d %02x %02x (max=%d %02x %02x)\n",
147                          head, track, sect, 1, drv->max_track, drv->last_sect);
148             return 4;
149         }
150 #endif
151         drv->head = head;
152         if (drv->track != track)
153             ret = 1;
154         drv->track = track;
155         drv->sect = sect;
156     }
157
158     return ret;
159 }
160
161 /* Set drive back to track 0 */
162 static void fd_recalibrate (fdrive_t *drv)
163 {
164     FLOPPY_DPRINTF("recalibrate\n");
165     drv->head = 0;
166     drv->track = 0;
167     drv->sect = 1;
168     drv->dir = 1;
169     drv->rw = 0;
170 }
171
172 /* Recognize floppy formats */
173 typedef struct fd_format_t {
174     fdrive_type_t drive;
175     fdisk_type_t  disk;
176     uint8_t last_sect;
177     uint8_t max_track;
178     uint8_t max_head;
179     const unsigned char *str;
180 } fd_format_t;
181
182 static const fd_format_t fd_formats[] = {
183     /* First entry is default format */
184     /* 1.44 MB 3"1/2 floppy disks */
185     { FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", },
186     { FDRIVE_DRV_144, FDRIVE_DISK_144, 20, 80, 1,  "1.6 MB 3\"1/2", },
187     { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 80, 1, "1.68 MB 3\"1/2", },
188     { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 82, 1, "1.72 MB 3\"1/2", },
189     { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 83, 1, "1.74 MB 3\"1/2", },
190     { FDRIVE_DRV_144, FDRIVE_DISK_144, 22, 80, 1, "1.76 MB 3\"1/2", },
191     { FDRIVE_DRV_144, FDRIVE_DISK_144, 23, 80, 1, "1.84 MB 3\"1/2", },
192     { FDRIVE_DRV_144, FDRIVE_DISK_144, 24, 80, 1, "1.92 MB 3\"1/2", },
193     /* 2.88 MB 3"1/2 floppy disks */
194     { FDRIVE_DRV_288, FDRIVE_DISK_288, 36, 80, 1, "2.88 MB 3\"1/2", },
195     { FDRIVE_DRV_288, FDRIVE_DISK_288, 39, 80, 1, "3.12 MB 3\"1/2", },
196     { FDRIVE_DRV_288, FDRIVE_DISK_288, 40, 80, 1,  "3.2 MB 3\"1/2", },
197     { FDRIVE_DRV_288, FDRIVE_DISK_288, 44, 80, 1, "3.52 MB 3\"1/2", },
198     { FDRIVE_DRV_288, FDRIVE_DISK_288, 48, 80, 1, "3.84 MB 3\"1/2", },
199     /* 720 kB 3"1/2 floppy disks */
200     { FDRIVE_DRV_144, FDRIVE_DISK_720,  9, 80, 1,  "720 kB 3\"1/2", },
201     { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 80, 1,  "800 kB 3\"1/2", },
202     { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 82, 1,  "820 kB 3\"1/2", },
203     { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 83, 1,  "830 kB 3\"1/2", },
204     { FDRIVE_DRV_144, FDRIVE_DISK_720, 13, 80, 1, "1.04 MB 3\"1/2", },
205     { FDRIVE_DRV_144, FDRIVE_DISK_720, 14, 80, 1, "1.12 MB 3\"1/2", },
206     /* 1.2 MB 5"1/4 floppy disks */
207     { FDRIVE_DRV_120, FDRIVE_DISK_288, 15, 80, 1,  "1.2 kB 5\"1/4", },
208     { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 80, 1, "1.44 MB 5\"1/4", },
209     { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 82, 1, "1.48 MB 5\"1/4", },
210     { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 83, 1, "1.49 MB 5\"1/4", },
211     { FDRIVE_DRV_120, FDRIVE_DISK_288, 20, 80, 1,  "1.6 MB 5\"1/4", },
212     /* 720 kB 5"1/4 floppy disks */
213     { FDRIVE_DRV_120, FDRIVE_DISK_288,  9, 80, 1,  "720 kB 5\"1/4", },
214     { FDRIVE_DRV_120, FDRIVE_DISK_288, 11, 80, 1,  "880 kB 5\"1/4", },
215     /* 360 kB 5"1/4 floppy disks */
216     { FDRIVE_DRV_120, FDRIVE_DISK_288,  9, 40, 1,  "360 kB 5\"1/4", },
217     { FDRIVE_DRV_120, FDRIVE_DISK_288,  9, 40, 0,  "180 kB 5\"1/4", },
218     { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 41, 1,  "410 kB 5\"1/4", },
219     { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 42, 1,  "420 kB 5\"1/4", },
220     /* 320 kB 5"1/4 floppy disks */
221     { FDRIVE_DRV_120, FDRIVE_DISK_288,  8, 40, 1,  "320 kB 5\"1/4", },
222     { FDRIVE_DRV_120, FDRIVE_DISK_288,  8, 40, 0,  "160 kB 5\"1/4", },
223     /* 360 kB must match 5"1/4 better than 3"1/2... */
224     { FDRIVE_DRV_144, FDRIVE_DISK_720,  9, 80, 0,  "360 kB 3\"1/2", },
225     /* end */
226     { FDRIVE_DRV_NONE, FDRIVE_DISK_NONE, -1, -1, 0, NULL, },
227 };
228
229 /* Revalidate a disk drive after a disk change */
230 static void fd_revalidate (fdrive_t *drv)
231 {
232     const fd_format_t *parse;
233     int64_t nb_sectors, size;
234     int i, first_match, match;
235     int nb_heads, max_track, last_sect, ro;
236
237     FLOPPY_DPRINTF("revalidate\n");
238     if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
239         ro = bdrv_is_read_only(drv->bs);
240         bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
241         if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
242             FLOPPY_DPRINTF("User defined disk (%d %d %d)",
243                            nb_heads - 1, max_track, last_sect);
244         } else {
245             bdrv_get_geometry(drv->bs, &nb_sectors);
246             match = -1;
247             first_match = -1;
248             for (i = 0;; i++) {
249                 parse = &fd_formats[i];
250                 if (parse->drive == FDRIVE_DRV_NONE)
251                     break;
252                 if (drv->drive == parse->drive ||
253                     drv->drive == FDRIVE_DRV_NONE) {
254                     size = (parse->max_head + 1) * parse->max_track *
255                         parse->last_sect;
256                     if (nb_sectors == size) {
257                         match = i;
258                         break;
259                     }
260                     if (first_match == -1)
261                         first_match = i;
262                 }
263             }
264             if (match == -1) {
265                 if (first_match == -1)
266                     match = 1;
267                 else
268                     match = first_match;
269                 parse = &fd_formats[match];
270             }
271             nb_heads = parse->max_head + 1;
272             max_track = parse->max_track;
273             last_sect = parse->last_sect;
274             drv->drive = parse->drive;
275             FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
276                            nb_heads, max_track, last_sect, ro ? "ro" : "rw");
277         }
278         if (nb_heads == 1) {
279             drv->flags &= ~FDISK_DBL_SIDES;
280         } else {
281             drv->flags |= FDISK_DBL_SIDES;
282         }
283         drv->max_track = max_track;
284         drv->last_sect = last_sect;
285         drv->ro = ro;
286     } else {
287         FLOPPY_DPRINTF("No disk in drive\n");
288         drv->last_sect = 0;
289         drv->max_track = 0;
290         drv->flags &= ~FDISK_DBL_SIDES;
291     }
292 }
293
294 /* Motor control */
295 static void fd_start (fdrive_t *drv)
296 {
297     drv->drflags |= FDRIVE_MOTOR_ON;
298 }
299
300 static void fd_stop (fdrive_t *drv)
301 {
302     drv->drflags &= ~FDRIVE_MOTOR_ON;
303 }
304
305 /* Re-initialise a drives (motor off, repositioned) */
306 static void fd_reset (fdrive_t *drv)
307 {
308     fd_stop(drv);
309     fd_recalibrate(drv);
310 }
311
312 /********************************************************/
313 /* Intel 82078 floppy disk controller emulation          */
314
315 static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq);
316 static void fdctrl_reset_fifo (fdctrl_t *fdctrl);
317 static int fdctrl_transfer_handler (void *opaque, int nchan,
318                                     int dma_pos, int dma_len);
319 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status);
320 static void fdctrl_result_timer(void *opaque);
321
322 static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl);
323 static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl);
324 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value);
325 static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl);
326 static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value);
327 static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl);
328 static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value);
329 static uint32_t fdctrl_read_data (fdctrl_t *fdctrl);
330 static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value);
331 static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
332
333 enum {
334     FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */
335     FD_CTRL_RESET  = 0x02,
336     FD_CTRL_SLEEP  = 0x04, /* XXX: suppress that */
337     FD_CTRL_BUSY   = 0x08, /* dma transfer in progress */
338     FD_CTRL_INTR   = 0x10,
339 };
340
341 enum {
342     FD_DIR_WRITE   = 0,
343     FD_DIR_READ    = 1,
344     FD_DIR_SCANE   = 2,
345     FD_DIR_SCANL   = 3,
346     FD_DIR_SCANH   = 4,
347 };
348
349 enum {
350     FD_STATE_CMD    = 0x00,
351     FD_STATE_STATUS = 0x01,
352     FD_STATE_DATA   = 0x02,
353     FD_STATE_STATE  = 0x03,
354     FD_STATE_MULTI  = 0x10,
355     FD_STATE_SEEK   = 0x20,
356     FD_STATE_FORMAT = 0x40,
357 };
358
359 #define FD_STATE(state) ((state) & FD_STATE_STATE)
360 #define FD_SET_STATE(state, new_state) \
361 do { (state) = ((state) & ~FD_STATE_STATE) | (new_state); } while (0)
362 #define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
363 #define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
364 #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
365
366 struct fdctrl_t {
367     fdctrl_t *fdctrl;
368     /* Controller's identification */
369     uint8_t version;
370     /* HW */
371     qemu_irq irq;
372     int dma_chann;
373     target_phys_addr_t io_base;
374     /* Controller state */
375     QEMUTimer *result_timer;
376     uint8_t state;
377     uint8_t dma_en;
378     uint8_t cur_drv;
379     uint8_t bootsel;
380     /* Command FIFO */
381     uint8_t fifo[FD_SECTOR_LEN];
382     uint32_t data_pos;
383     uint32_t data_len;
384     uint8_t data_state;
385     uint8_t data_dir;
386     uint8_t int_status;
387     uint8_t eot; /* last wanted sector */
388     /* States kept only to be returned back */
389     /* Timers state */
390     uint8_t timer0;
391     uint8_t timer1;
392     /* precompensation */
393     uint8_t precomp_trk;
394     uint8_t config;
395     uint8_t lock;
396     /* Power down config (also with status regB access mode */
397     uint8_t pwrd;
398     /* Sun4m quirks? */
399     int sun4m;
400     /* Floppy drives */
401     fdrive_t drives[2];
402 };
403
404 static uint32_t fdctrl_read (void *opaque, uint32_t reg)
405 {
406     fdctrl_t *fdctrl = opaque;
407     uint32_t retval;
408
409     switch (reg & 0x07) {
410     case 0x00:
411         if (fdctrl->sun4m) {
412             // Identify to Linux as S82078B
413             retval = fdctrl_read_statusB(fdctrl);
414         } else {
415             retval = (uint32_t)(-1);
416         }
417         break;
418     case 0x01:
419         retval = fdctrl_read_statusB(fdctrl);
420         break;
421     case 0x02:
422         retval = fdctrl_read_dor(fdctrl);
423         break;
424     case 0x03:
425         retval = fdctrl_read_tape(fdctrl);
426         break;
427     case 0x04:
428         retval = fdctrl_read_main_status(fdctrl);
429         break;
430     case 0x05:
431         retval = fdctrl_read_data(fdctrl);
432         break;
433     case 0x07:
434         retval = fdctrl_read_dir(fdctrl);
435         break;
436     default:
437         retval = (uint32_t)(-1);
438         break;
439     }
440     FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
441
442     return retval;
443 }
444
445 static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
446 {
447     fdctrl_t *fdctrl = opaque;
448
449     FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
450
451     switch (reg & 0x07) {
452     case 0x02:
453         fdctrl_write_dor(fdctrl, value);
454         break;
455     case 0x03:
456         fdctrl_write_tape(fdctrl, value);
457         break;
458     case 0x04:
459         fdctrl_write_rate(fdctrl, value);
460         break;
461     case 0x05:
462         fdctrl_write_data(fdctrl, value);
463         break;
464     default:
465         break;
466     }
467 }
468
469 static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg)
470 {
471     return fdctrl_read(opaque, (uint32_t)reg);
472 }
473
474 static void fdctrl_write_mem (void *opaque,
475                               target_phys_addr_t reg, uint32_t value)
476 {
477     fdctrl_write(opaque, (uint32_t)reg, value);
478 }
479
480 static CPUReadMemoryFunc *fdctrl_mem_read[3] = {
481     fdctrl_read_mem,
482     fdctrl_read_mem,
483     fdctrl_read_mem,
484 };
485
486 static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
487     fdctrl_write_mem,
488     fdctrl_write_mem,
489     fdctrl_write_mem,
490 };
491
492 static void fd_save (QEMUFile *f, fdrive_t *fd)
493 {
494     uint8_t tmp;
495
496     tmp = fd->drflags;
497     qemu_put_8s(f, &tmp);
498     qemu_put_8s(f, &fd->head);
499     qemu_put_8s(f, &fd->track);
500     qemu_put_8s(f, &fd->sect);
501     qemu_put_8s(f, &fd->dir);
502     qemu_put_8s(f, &fd->rw);
503 }
504
505 static void fdc_save (QEMUFile *f, void *opaque)
506 {
507     fdctrl_t *s = opaque;
508
509     qemu_put_8s(f, &s->state);
510     qemu_put_8s(f, &s->dma_en);
511     qemu_put_8s(f, &s->cur_drv);
512     qemu_put_8s(f, &s->bootsel);
513     qemu_put_buffer(f, s->fifo, FD_SECTOR_LEN);
514     qemu_put_be32s(f, &s->data_pos);
515     qemu_put_be32s(f, &s->data_len);
516     qemu_put_8s(f, &s->data_state);
517     qemu_put_8s(f, &s->data_dir);
518     qemu_put_8s(f, &s->int_status);
519     qemu_put_8s(f, &s->eot);
520     qemu_put_8s(f, &s->timer0);
521     qemu_put_8s(f, &s->timer1);
522     qemu_put_8s(f, &s->precomp_trk);
523     qemu_put_8s(f, &s->config);
524     qemu_put_8s(f, &s->lock);
525     qemu_put_8s(f, &s->pwrd);
526     fd_save(f, &s->drives[0]);
527     fd_save(f, &s->drives[1]);
528 }
529
530 static int fd_load (QEMUFile *f, fdrive_t *fd)
531 {
532     uint8_t tmp;
533
534     qemu_get_8s(f, &tmp);
535     fd->drflags = tmp;
536     qemu_get_8s(f, &fd->head);
537     qemu_get_8s(f, &fd->track);
538     qemu_get_8s(f, &fd->sect);
539     qemu_get_8s(f, &fd->dir);
540     qemu_get_8s(f, &fd->rw);
541
542     return 0;
543 }
544
545 static int fdc_load (QEMUFile *f, void *opaque, int version_id)
546 {
547     fdctrl_t *s = opaque;
548     int ret;
549
550     if (version_id != 1)
551         return -EINVAL;
552
553     qemu_get_8s(f, &s->state);
554     qemu_get_8s(f, &s->dma_en);
555     qemu_get_8s(f, &s->cur_drv);
556     qemu_get_8s(f, &s->bootsel);
557     qemu_get_buffer(f, s->fifo, FD_SECTOR_LEN);
558     qemu_get_be32s(f, &s->data_pos);
559     qemu_get_be32s(f, &s->data_len);
560     qemu_get_8s(f, &s->data_state);
561     qemu_get_8s(f, &s->data_dir);
562     qemu_get_8s(f, &s->int_status);
563     qemu_get_8s(f, &s->eot);
564     qemu_get_8s(f, &s->timer0);
565     qemu_get_8s(f, &s->timer1);
566     qemu_get_8s(f, &s->precomp_trk);
567     qemu_get_8s(f, &s->config);
568     qemu_get_8s(f, &s->lock);
569     qemu_get_8s(f, &s->pwrd);
570
571     ret = fd_load(f, &s->drives[0]);
572     if (ret == 0)
573         ret = fd_load(f, &s->drives[1]);
574
575     return ret;
576 }
577
578 static void fdctrl_external_reset(void *opaque)
579 {
580     fdctrl_t *s = opaque;
581
582     fdctrl_reset(s, 0);
583 }
584
585 fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped,
586                        target_phys_addr_t io_base,
587                        BlockDriverState **fds)
588 {
589     fdctrl_t *fdctrl;
590     int io_mem;
591     int i;
592
593     FLOPPY_DPRINTF("init controller\n");
594     fdctrl = qemu_mallocz(sizeof(fdctrl_t));
595     if (!fdctrl)
596         return NULL;
597     fdctrl->result_timer = qemu_new_timer(vm_clock,
598                                           fdctrl_result_timer, fdctrl);
599
600     fdctrl->version = 0x90; /* Intel 82078 controller */
601     fdctrl->irq = irq;
602     fdctrl->dma_chann = dma_chann;
603     fdctrl->io_base = io_base;
604     fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
605     fdctrl->sun4m = 0;
606     if (fdctrl->dma_chann != -1) {
607         fdctrl->dma_en = 1;
608         DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
609     } else {
610         fdctrl->dma_en = 0;
611     }
612     for (i = 0; i < 2; i++) {
613         fd_init(&fdctrl->drives[i], fds[i]);
614     }
615     fdctrl_reset(fdctrl, 0);
616     fdctrl->state = FD_CTRL_ACTIVE;
617     if (mem_mapped) {
618         io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write,
619                                         fdctrl);
620         cpu_register_physical_memory(io_base, 0x08, io_mem);
621     } else {
622         register_ioport_read((uint32_t)io_base + 0x01, 5, 1, &fdctrl_read,
623                              fdctrl);
624         register_ioport_read((uint32_t)io_base + 0x07, 1, 1, &fdctrl_read,
625                              fdctrl);
626         register_ioport_write((uint32_t)io_base + 0x01, 5, 1, &fdctrl_write,
627                               fdctrl);
628         register_ioport_write((uint32_t)io_base + 0x07, 1, 1, &fdctrl_write,
629                               fdctrl);
630     }
631     register_savevm("fdc", io_base, 1, fdc_save, fdc_load, fdctrl);
632     qemu_register_reset(fdctrl_external_reset, fdctrl);
633     for (i = 0; i < 2; i++) {
634         fd_revalidate(&fdctrl->drives[i]);
635     }
636
637     return fdctrl;
638 }
639
640 fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
641                              BlockDriverState **fds)
642 {
643     fdctrl_t *fdctrl;
644
645     fdctrl = fdctrl_init(irq, 0, 1, io_base, fds);
646     fdctrl->sun4m = 1;
647
648     return fdctrl;
649 }
650
651 /* XXX: may change if moved to bdrv */
652 int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
653 {
654     return fdctrl->drives[drive_num].drive;
655 }
656
657 /* Change IRQ state */
658 static void fdctrl_reset_irq (fdctrl_t *fdctrl)
659 {
660     FLOPPY_DPRINTF("Reset interrupt\n");
661     qemu_set_irq(fdctrl->irq, 0);
662     fdctrl->state &= ~FD_CTRL_INTR;
663 }
664
665 static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
666 {
667     // Sparc mutation
668     if (fdctrl->sun4m && !fdctrl->dma_en) {
669         fdctrl->state &= ~FD_CTRL_BUSY;
670         fdctrl->int_status = status;
671         return;
672     }
673     if (~(fdctrl->state & FD_CTRL_INTR)) {
674         qemu_set_irq(fdctrl->irq, 1);
675         fdctrl->state |= FD_CTRL_INTR;
676     }
677     FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);
678     fdctrl->int_status = status;
679 }
680
681 /* Reset controller */
682 static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
683 {
684     int i;
685
686     FLOPPY_DPRINTF("reset controller\n");
687     fdctrl_reset_irq(fdctrl);
688     /* Initialise controller */
689     fdctrl->cur_drv = 0;
690     /* FIFO state */
691     fdctrl->data_pos = 0;
692     fdctrl->data_len = 0;
693     fdctrl->data_state = FD_STATE_CMD;
694     fdctrl->data_dir = FD_DIR_WRITE;
695     for (i = 0; i < MAX_FD; i++)
696         fd_reset(&fdctrl->drives[i]);
697     fdctrl_reset_fifo(fdctrl);
698     if (do_irq)
699         fdctrl_raise_irq(fdctrl, 0xc0);
700 }
701
702 static inline fdrive_t *drv0 (fdctrl_t *fdctrl)
703 {
704     return &fdctrl->drives[fdctrl->bootsel];
705 }
706
707 static inline fdrive_t *drv1 (fdctrl_t *fdctrl)
708 {
709     return &fdctrl->drives[1 - fdctrl->bootsel];
710 }
711
712 static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
713 {
714     return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl);
715 }
716
717 /* Status B register : 0x01 (read-only) */
718 static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
719 {
720     FLOPPY_DPRINTF("status register: 0x00\n");
721     return 0;
722 }
723
724 /* Digital output register : 0x02 */
725 static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
726 {
727     uint32_t retval = 0;
728
729     /* Drive motors state indicators */
730     if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)
731         retval |= 1 << 5;
732     if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
733         retval |= 1 << 4;
734     /* DMA enable */
735     retval |= fdctrl->dma_en << 3;
736     /* Reset indicator */
737     retval |= (fdctrl->state & FD_CTRL_RESET) == 0 ? 0x04 : 0;
738     /* Selected drive */
739     retval |= fdctrl->cur_drv;
740     FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);
741
742     return retval;
743 }
744
745 static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
746 {
747     /* Reset mode */
748     if (fdctrl->state & FD_CTRL_RESET) {
749         if (!(value & 0x04)) {
750             FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
751             return;
752         }
753     }
754     FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
755     /* Drive motors state indicators */
756     if (value & 0x20)
757         fd_start(drv1(fdctrl));
758     else
759         fd_stop(drv1(fdctrl));
760     if (value & 0x10)
761         fd_start(drv0(fdctrl));
762     else
763         fd_stop(drv0(fdctrl));
764     /* DMA enable */
765 #if 0
766     if (fdctrl->dma_chann != -1)
767         fdctrl->dma_en = 1 - ((value >> 3) & 1);
768 #endif
769     /* Reset */
770     if (!(value & 0x04)) {
771         if (!(fdctrl->state & FD_CTRL_RESET)) {
772             FLOPPY_DPRINTF("controller enter RESET state\n");
773             fdctrl->state |= FD_CTRL_RESET;
774         }
775     } else {
776         if (fdctrl->state & FD_CTRL_RESET) {
777             FLOPPY_DPRINTF("controller out of RESET state\n");
778             fdctrl_reset(fdctrl, 1);
779             fdctrl->state &= ~(FD_CTRL_RESET | FD_CTRL_SLEEP);
780         }
781     }
782     /* Selected drive */
783     fdctrl->cur_drv = value & 1;
784 }
785
786 /* Tape drive register : 0x03 */
787 static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
788 {
789     uint32_t retval = 0;
790
791     /* Disk boot selection indicator */
792     retval |= fdctrl->bootsel << 2;
793     /* Tape indicators: never allowed */
794     FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval);
795
796     return retval;
797 }
798
799 static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
800 {
801     /* Reset mode */
802     if (fdctrl->state & FD_CTRL_RESET) {
803         FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
804         return;
805     }
806     FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
807     /* Disk boot selection indicator */
808     fdctrl->bootsel = (value >> 2) & 1;
809     /* Tape indicators: never allow */
810 }
811
812 /* Main status register : 0x04 (read) */
813 static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
814 {
815     uint32_t retval = 0;
816
817     fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET);
818     if (!(fdctrl->state & FD_CTRL_BUSY)) {
819         /* Data transfer allowed */
820         retval |= 0x80;
821         /* Data transfer direction indicator */
822         if (fdctrl->data_dir == FD_DIR_READ)
823             retval |= 0x40;
824     }
825     /* Should handle 0x20 for SPECIFY command */
826     /* Command busy indicator */
827     if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA ||
828         FD_STATE(fdctrl->data_state) == FD_STATE_STATUS)
829         retval |= 0x10;
830     FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
831
832     return retval;
833 }
834
835 /* Data select rate register : 0x04 (write) */
836 static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
837 {
838     /* Reset mode */
839     if (fdctrl->state & FD_CTRL_RESET) {
840         FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
841         return;
842     }
843     FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
844     /* Reset: autoclear */
845     if (value & 0x80) {
846         fdctrl->state |= FD_CTRL_RESET;
847         fdctrl_reset(fdctrl, 1);
848         fdctrl->state &= ~FD_CTRL_RESET;
849     }
850     if (value & 0x40) {
851         fdctrl->state |= FD_CTRL_SLEEP;
852         fdctrl_reset(fdctrl, 1);
853     }
854 //        fdctrl.precomp = (value >> 2) & 0x07;
855 }
856
857 static int fdctrl_media_changed(fdrive_t *drv)
858 {
859     int ret;
860
861     if (!drv->bs)
862         return 0;
863     ret = bdrv_media_changed(drv->bs);
864     if (ret) {
865         fd_revalidate(drv);
866     }
867     return ret;
868 }
869
870 /* Digital input register : 0x07 (read-only) */
871 static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
872 {
873     uint32_t retval = 0;
874
875     if (fdctrl_media_changed(drv0(fdctrl)) ||
876         fdctrl_media_changed(drv1(fdctrl)))
877         retval |= 0x80;
878     if (retval != 0)
879         FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
880
881     return retval;
882 }
883
884 /* FIFO state control */
885 static void fdctrl_reset_fifo (fdctrl_t *fdctrl)
886 {
887     fdctrl->data_dir = FD_DIR_WRITE;
888     fdctrl->data_pos = 0;
889     FD_SET_STATE(fdctrl->data_state, FD_STATE_CMD);
890 }
891
892 /* Set FIFO status for the host to read */
893 static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq)
894 {
895     fdctrl->data_dir = FD_DIR_READ;
896     fdctrl->data_len = fifo_len;
897     fdctrl->data_pos = 0;
898     FD_SET_STATE(fdctrl->data_state, FD_STATE_STATUS);
899     if (do_irq)
900         fdctrl_raise_irq(fdctrl, 0x00);
901 }
902
903 /* Set an error: unimplemented/unknown command */
904 static void fdctrl_unimplemented (fdctrl_t *fdctrl)
905 {
906 #if 0
907     fdrive_t *cur_drv;
908
909     cur_drv = get_cur_drv(fdctrl);
910     fdctrl->fifo[0] = 0x60 | (cur_drv->head << 2) | fdctrl->cur_drv;
911     fdctrl->fifo[1] = 0x00;
912     fdctrl->fifo[2] = 0x00;
913     fdctrl_set_fifo(fdctrl, 3, 1);
914 #else
915     //    fdctrl_reset_fifo(fdctrl);
916     fdctrl->fifo[0] = 0x80;
917     fdctrl_set_fifo(fdctrl, 1, 0);
918 #endif
919 }
920
921 /* Callback for transfer end (stop or abort) */
922 static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
923                                   uint8_t status1, uint8_t status2)
924 {
925     fdrive_t *cur_drv;
926
927     cur_drv = get_cur_drv(fdctrl);
928     FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
929                    status0, status1, status2,
930                    status0 | (cur_drv->head << 2) | fdctrl->cur_drv);
931     fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | fdctrl->cur_drv;
932     fdctrl->fifo[1] = status1;
933     fdctrl->fifo[2] = status2;
934     fdctrl->fifo[3] = cur_drv->track;
935     fdctrl->fifo[4] = cur_drv->head;
936     fdctrl->fifo[5] = cur_drv->sect;
937     fdctrl->fifo[6] = FD_SECTOR_SC;
938     fdctrl->data_dir = FD_DIR_READ;
939     if (fdctrl->state & FD_CTRL_BUSY) {
940         DMA_release_DREQ(fdctrl->dma_chann);
941         fdctrl->state &= ~FD_CTRL_BUSY;
942     }
943     fdctrl_set_fifo(fdctrl, 7, 1);
944 }
945
946 /* Prepare a data transfer (either DMA or FIFO) */
947 static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
948 {
949     fdrive_t *cur_drv;
950     uint8_t kh, kt, ks;
951     int did_seek;
952
953     fdctrl->cur_drv = fdctrl->fifo[1] & 1;
954     cur_drv = get_cur_drv(fdctrl);
955     kt = fdctrl->fifo[2];
956     kh = fdctrl->fifo[3];
957     ks = fdctrl->fifo[4];
958     FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
959                    fdctrl->cur_drv, kh, kt, ks,
960                    _fd_sector(kh, kt, ks, cur_drv->last_sect));
961     did_seek = 0;
962     switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {
963     case 2:
964         /* sect too big */
965         fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
966         fdctrl->fifo[3] = kt;
967         fdctrl->fifo[4] = kh;
968         fdctrl->fifo[5] = ks;
969         return;
970     case 3:
971         /* track too big */
972         fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);
973         fdctrl->fifo[3] = kt;
974         fdctrl->fifo[4] = kh;
975         fdctrl->fifo[5] = ks;
976         return;
977     case 4:
978         /* No seek enabled */
979         fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
980         fdctrl->fifo[3] = kt;
981         fdctrl->fifo[4] = kh;
982         fdctrl->fifo[5] = ks;
983         return;
984     case 1:
985         did_seek = 1;
986         break;
987     default:
988         break;
989     }
990     /* Set the FIFO state */
991     fdctrl->data_dir = direction;
992     fdctrl->data_pos = 0;
993     FD_SET_STATE(fdctrl->data_state, FD_STATE_DATA); /* FIFO ready for data */
994     if (fdctrl->fifo[0] & 0x80)
995         fdctrl->data_state |= FD_STATE_MULTI;
996     else
997         fdctrl->data_state &= ~FD_STATE_MULTI;
998     if (did_seek)
999         fdctrl->data_state |= FD_STATE_SEEK;
1000     else
1001         fdctrl->data_state &= ~FD_STATE_SEEK;
1002     if (fdctrl->fifo[5] == 00) {
1003         fdctrl->data_len = fdctrl->fifo[8];
1004     } else {
1005         int tmp;
1006         fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
1007         tmp = (cur_drv->last_sect - ks + 1);
1008         if (fdctrl->fifo[0] & 0x80)
1009             tmp += cur_drv->last_sect;
1010         fdctrl->data_len *= tmp;
1011     }
1012     fdctrl->eot = fdctrl->fifo[6];
1013     if (fdctrl->dma_en) {
1014         int dma_mode;
1015         /* DMA transfer are enabled. Check if DMA channel is well programmed */
1016         dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
1017         dma_mode = (dma_mode >> 2) & 3;
1018         FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
1019                        dma_mode, direction,
1020                        (128 << fdctrl->fifo[5]) *
1021                        (cur_drv->last_sect - ks + 1), fdctrl->data_len);
1022         if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
1023               direction == FD_DIR_SCANH) && dma_mode == 0) ||
1024             (direction == FD_DIR_WRITE && dma_mode == 2) ||
1025             (direction == FD_DIR_READ && dma_mode == 1)) {
1026             /* No access is allowed until DMA transfer has completed */
1027             fdctrl->state |= FD_CTRL_BUSY;
1028             /* Now, we just have to wait for the DMA controller to
1029              * recall us...
1030              */
1031             DMA_hold_DREQ(fdctrl->dma_chann);
1032             DMA_schedule(fdctrl->dma_chann);
1033             return;
1034         } else {
1035             FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
1036         }
1037     }
1038     FLOPPY_DPRINTF("start non-DMA transfer\n");
1039     /* IO based transfer: calculate len */
1040     fdctrl_raise_irq(fdctrl, 0x00);
1041
1042     return;
1043 }
1044
1045 /* Prepare a transfer of deleted data */
1046 static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction)
1047 {
1048     /* We don't handle deleted data,
1049      * so we don't return *ANYTHING*
1050      */
1051     fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
1052 }
1053
1054 /* handlers for DMA transfers */
1055 static int fdctrl_transfer_handler (void *opaque, int nchan,
1056                                     int dma_pos, int dma_len)
1057 {
1058     fdctrl_t *fdctrl;
1059     fdrive_t *cur_drv;
1060     int len, start_pos, rel_pos;
1061     uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
1062
1063     fdctrl = opaque;
1064     if (!(fdctrl->state & FD_CTRL_BUSY)) {
1065         FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
1066         return 0;
1067     }
1068     cur_drv = get_cur_drv(fdctrl);
1069     if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
1070         fdctrl->data_dir == FD_DIR_SCANH)
1071         status2 = 0x04;
1072     if (dma_len > fdctrl->data_len)
1073         dma_len = fdctrl->data_len;
1074     if (cur_drv->bs == NULL) {
1075         if (fdctrl->data_dir == FD_DIR_WRITE)
1076             fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
1077         else
1078             fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
1079         len = 0;
1080         goto transfer_error;
1081     }
1082     rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
1083     for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
1084         len = dma_len - fdctrl->data_pos;
1085         if (len + rel_pos > FD_SECTOR_LEN)
1086             len = FD_SECTOR_LEN - rel_pos;
1087         FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x "
1088                        "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos,
1089                        fdctrl->data_len, fdctrl->cur_drv, cur_drv->head,
1090                        cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
1091                        fd_sector(cur_drv) * 512);
1092         if (fdctrl->data_dir != FD_DIR_WRITE ||
1093             len < FD_SECTOR_LEN || rel_pos != 0) {
1094             /* READ & SCAN commands and realign to a sector for WRITE */
1095             if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
1096                           fdctrl->fifo, 1) < 0) {
1097                 FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
1098                                fd_sector(cur_drv));
1099                 /* Sure, image size is too small... */
1100                 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1101             }
1102         }
1103         switch (fdctrl->data_dir) {
1104         case FD_DIR_READ:
1105             /* READ commands */
1106             DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
1107                               fdctrl->data_pos, len);
1108             break;
1109         case FD_DIR_WRITE:
1110             /* WRITE commands */
1111             DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
1112                              fdctrl->data_pos, len);
1113             if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
1114                            fdctrl->fifo, 1) < 0) {
1115                 FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
1116                 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
1117                 goto transfer_error;
1118             }
1119             break;
1120         default:
1121             /* SCAN commands */
1122             {
1123                 uint8_t tmpbuf[FD_SECTOR_LEN];
1124                 int ret;
1125                 DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
1126                 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
1127                 if (ret == 0) {
1128                     status2 = 0x08;
1129                     goto end_transfer;
1130                 }
1131                 if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||
1132                     (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {
1133                     status2 = 0x00;
1134                     goto end_transfer;
1135                 }
1136             }
1137             break;
1138         }
1139         fdctrl->data_pos += len;
1140         rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
1141         if (rel_pos == 0) {
1142             /* Seek to next sector */
1143             FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
1144                            cur_drv->head, cur_drv->track, cur_drv->sect,
1145                            fd_sector(cur_drv),
1146                            fdctrl->data_pos - len);
1147             /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
1148                error in fact */
1149             if (cur_drv->sect >= cur_drv->last_sect ||
1150                 cur_drv->sect == fdctrl->eot) {
1151                 cur_drv->sect = 1;
1152                 if (FD_MULTI_TRACK(fdctrl->data_state)) {
1153                     if (cur_drv->head == 0 &&
1154                         (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
1155                         cur_drv->head = 1;
1156                     } else {
1157                         cur_drv->head = 0;
1158                         cur_drv->track++;
1159                         if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
1160                             break;
1161                     }
1162                 } else {
1163                     cur_drv->track++;
1164                     break;
1165                 }
1166                 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
1167                                cur_drv->head, cur_drv->track,
1168                                cur_drv->sect, fd_sector(cur_drv));
1169             } else {
1170                 cur_drv->sect++;
1171             }
1172         }
1173     }
1174  end_transfer:
1175     len = fdctrl->data_pos - start_pos;
1176     FLOPPY_DPRINTF("end transfer %d %d %d\n",
1177                    fdctrl->data_pos, len, fdctrl->data_len);
1178     if (fdctrl->data_dir == FD_DIR_SCANE ||
1179         fdctrl->data_dir == FD_DIR_SCANL ||
1180         fdctrl->data_dir == FD_DIR_SCANH)
1181         status2 = 0x08;
1182     if (FD_DID_SEEK(fdctrl->data_state))
1183         status0 |= 0x20;
1184     fdctrl->data_len -= len;
1185     //    if (fdctrl->data_len == 0)
1186     fdctrl_stop_transfer(fdctrl, status0, status1, status2);
1187  transfer_error:
1188
1189     return len;
1190 }
1191
1192 /* Data register : 0x05 */
1193 static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
1194 {
1195     fdrive_t *cur_drv;
1196     uint32_t retval = 0;
1197     int pos, len;
1198
1199     cur_drv = get_cur_drv(fdctrl);
1200     fdctrl->state &= ~FD_CTRL_SLEEP;
1201     if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) {
1202         FLOPPY_ERROR("can't read data in CMD state\n");
1203         return 0;
1204     }
1205     pos = fdctrl->data_pos;
1206     if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
1207         pos %= FD_SECTOR_LEN;
1208         if (pos == 0) {
1209             len = fdctrl->data_len - fdctrl->data_pos;
1210             if (len > FD_SECTOR_LEN)
1211                 len = FD_SECTOR_LEN;
1212             bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1);
1213         }
1214     }
1215     retval = fdctrl->fifo[pos];
1216     if (++fdctrl->data_pos == fdctrl->data_len) {
1217         fdctrl->data_pos = 0;
1218         /* Switch from transfer mode to status mode
1219          * then from status mode to command mode
1220          */
1221         if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
1222             fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
1223         } else {
1224             fdctrl_reset_fifo(fdctrl);
1225             fdctrl_reset_irq(fdctrl);
1226         }
1227     }
1228     FLOPPY_DPRINTF("data register: 0x%02x\n", retval);
1229
1230     return retval;
1231 }
1232
1233 static void fdctrl_format_sector (fdctrl_t *fdctrl)
1234 {
1235     fdrive_t *cur_drv;
1236     uint8_t kh, kt, ks;
1237     int did_seek;
1238
1239     fdctrl->cur_drv = fdctrl->fifo[1] & 1;
1240     cur_drv = get_cur_drv(fdctrl);
1241     kt = fdctrl->fifo[6];
1242     kh = fdctrl->fifo[7];
1243     ks = fdctrl->fifo[8];
1244     FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
1245                    fdctrl->cur_drv, kh, kt, ks,
1246                    _fd_sector(kh, kt, ks, cur_drv->last_sect));
1247     did_seek = 0;
1248     switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {
1249     case 2:
1250         /* sect too big */
1251         fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
1252         fdctrl->fifo[3] = kt;
1253         fdctrl->fifo[4] = kh;
1254         fdctrl->fifo[5] = ks;
1255         return;
1256     case 3:
1257         /* track too big */
1258         fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);
1259         fdctrl->fifo[3] = kt;
1260         fdctrl->fifo[4] = kh;
1261         fdctrl->fifo[5] = ks;
1262         return;
1263     case 4:
1264         /* No seek enabled */
1265         fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
1266         fdctrl->fifo[3] = kt;
1267         fdctrl->fifo[4] = kh;
1268         fdctrl->fifo[5] = ks;
1269         return;
1270     case 1:
1271         did_seek = 1;
1272         fdctrl->data_state |= FD_STATE_SEEK;
1273         break;
1274     default:
1275         break;
1276     }
1277     memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1278     if (cur_drv->bs == NULL ||
1279         bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
1280         FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv));
1281         fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
1282     } else {
1283         if (cur_drv->sect == cur_drv->last_sect) {
1284             fdctrl->data_state &= ~FD_STATE_FORMAT;
1285             /* Last sector done */
1286             if (FD_DID_SEEK(fdctrl->data_state))
1287                 fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
1288             else
1289                 fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1290         } else {
1291             /* More to do */
1292             fdctrl->data_pos = 0;
1293             fdctrl->data_len = 4;
1294         }
1295     }
1296 }
1297
1298 static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
1299 {
1300     fdrive_t *cur_drv;
1301
1302     cur_drv = get_cur_drv(fdctrl);
1303     /* Reset mode */
1304     if (fdctrl->state & FD_CTRL_RESET) {
1305         FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
1306         return;
1307     }
1308     fdctrl->state &= ~FD_CTRL_SLEEP;
1309     if (FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) {
1310         FLOPPY_ERROR("can't write data in status mode\n");
1311         return;
1312     }
1313     /* Is it write command time ? */
1314     if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
1315         /* FIFO data write */
1316         fdctrl->fifo[fdctrl->data_pos++] = value;
1317         if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) ||
1318             fdctrl->data_pos == fdctrl->data_len) {
1319             bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1);
1320         }
1321         /* Switch from transfer mode to status mode
1322          * then from status mode to command mode
1323          */
1324         if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA)
1325             fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
1326         return;
1327     }
1328     if (fdctrl->data_pos == 0) {
1329         /* Command */
1330         switch (value & 0x5F) {
1331         case 0x46:
1332             /* READ variants */
1333             FLOPPY_DPRINTF("READ command\n");
1334             /* 8 parameters cmd */
1335             fdctrl->data_len = 9;
1336             goto enqueue;
1337         case 0x4C:
1338             /* READ_DELETED variants */
1339             FLOPPY_DPRINTF("READ_DELETED command\n");
1340             /* 8 parameters cmd */
1341             fdctrl->data_len = 9;
1342             goto enqueue;
1343         case 0x50:
1344             /* SCAN_EQUAL variants */
1345             FLOPPY_DPRINTF("SCAN_EQUAL command\n");
1346             /* 8 parameters cmd */
1347             fdctrl->data_len = 9;
1348             goto enqueue;
1349         case 0x56:
1350             /* VERIFY variants */
1351             FLOPPY_DPRINTF("VERIFY command\n");
1352             /* 8 parameters cmd */
1353             fdctrl->data_len = 9;
1354             goto enqueue;
1355         case 0x59:
1356             /* SCAN_LOW_OR_EQUAL variants */
1357             FLOPPY_DPRINTF("SCAN_LOW_OR_EQUAL command\n");
1358             /* 8 parameters cmd */
1359             fdctrl->data_len = 9;
1360             goto enqueue;
1361         case 0x5D:
1362             /* SCAN_HIGH_OR_EQUAL variants */
1363             FLOPPY_DPRINTF("SCAN_HIGH_OR_EQUAL command\n");
1364             /* 8 parameters cmd */
1365             fdctrl->data_len = 9;
1366             goto enqueue;
1367         default:
1368             break;
1369         }
1370         switch (value & 0x7F) {
1371         case 0x45:
1372             /* WRITE variants */
1373             FLOPPY_DPRINTF("WRITE command\n");
1374             /* 8 parameters cmd */
1375             fdctrl->data_len = 9;
1376             goto enqueue;
1377         case 0x49:
1378             /* WRITE_DELETED variants */
1379             FLOPPY_DPRINTF("WRITE_DELETED command\n");
1380             /* 8 parameters cmd */
1381             fdctrl->data_len = 9;
1382             goto enqueue;
1383         default:
1384             break;
1385         }
1386         switch (value) {
1387         case 0x03:
1388             /* SPECIFY */
1389             FLOPPY_DPRINTF("SPECIFY command\n");
1390             /* 1 parameter cmd */
1391             fdctrl->data_len = 3;
1392             goto enqueue;
1393         case 0x04:
1394             /* SENSE_DRIVE_STATUS */
1395             FLOPPY_DPRINTF("SENSE_DRIVE_STATUS command\n");
1396             /* 1 parameter cmd */
1397             fdctrl->data_len = 2;
1398             goto enqueue;
1399         case 0x07:
1400             /* RECALIBRATE */
1401             FLOPPY_DPRINTF("RECALIBRATE command\n");
1402             /* 1 parameter cmd */
1403             fdctrl->data_len = 2;
1404             goto enqueue;
1405         case 0x08:
1406             /* SENSE_INTERRUPT_STATUS */
1407             FLOPPY_DPRINTF("SENSE_INTERRUPT_STATUS command (%02x)\n",
1408                            fdctrl->int_status);
1409             /* No parameters cmd: returns status if no interrupt */
1410 #if 0
1411             fdctrl->fifo[0] =
1412                 fdctrl->int_status | (cur_drv->head << 2) | fdctrl->cur_drv;
1413 #else
1414             /* XXX: int_status handling is broken for read/write
1415                commands, so we do this hack. It should be suppressed
1416                ASAP */
1417             fdctrl->fifo[0] =
1418                 0x20 | (cur_drv->head << 2) | fdctrl->cur_drv;
1419 #endif
1420             fdctrl->fifo[1] = cur_drv->track;
1421             fdctrl_set_fifo(fdctrl, 2, 0);
1422             fdctrl_reset_irq(fdctrl);
1423             fdctrl->int_status = 0xC0;
1424             return;
1425         case 0x0E:
1426             /* DUMPREG */
1427             FLOPPY_DPRINTF("DUMPREG command\n");
1428             /* Drives position */
1429             fdctrl->fifo[0] = drv0(fdctrl)->track;
1430             fdctrl->fifo[1] = drv1(fdctrl)->track;
1431             fdctrl->fifo[2] = 0;
1432             fdctrl->fifo[3] = 0;
1433             /* timers */
1434             fdctrl->fifo[4] = fdctrl->timer0;
1435             fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en;
1436             fdctrl->fifo[6] = cur_drv->last_sect;
1437             fdctrl->fifo[7] = (fdctrl->lock << 7) |
1438                 (cur_drv->perpendicular << 2);
1439             fdctrl->fifo[8] = fdctrl->config;
1440             fdctrl->fifo[9] = fdctrl->precomp_trk;
1441             fdctrl_set_fifo(fdctrl, 10, 0);
1442             return;
1443         case 0x0F:
1444             /* SEEK */
1445             FLOPPY_DPRINTF("SEEK command\n");
1446             /* 2 parameters cmd */
1447             fdctrl->data_len = 3;
1448             goto enqueue;
1449         case 0x10:
1450             /* VERSION */
1451             FLOPPY_DPRINTF("VERSION command\n");
1452             /* No parameters cmd */
1453             /* Controller's version */
1454             fdctrl->fifo[0] = fdctrl->version;
1455             fdctrl_set_fifo(fdctrl, 1, 1);
1456             return;
1457         case 0x12:
1458             /* PERPENDICULAR_MODE */
1459             FLOPPY_DPRINTF("PERPENDICULAR_MODE command\n");
1460             /* 1 parameter cmd */
1461             fdctrl->data_len = 2;
1462             goto enqueue;
1463         case 0x13:
1464             /* CONFIGURE */
1465             FLOPPY_DPRINTF("CONFIGURE command\n");
1466             /* 3 parameters cmd */
1467             fdctrl->data_len = 4;
1468             goto enqueue;
1469         case 0x14:
1470             /* UNLOCK */
1471             FLOPPY_DPRINTF("UNLOCK command\n");
1472             /* No parameters cmd */
1473             fdctrl->lock = 0;
1474             fdctrl->fifo[0] = 0;
1475             fdctrl_set_fifo(fdctrl, 1, 0);
1476             return;
1477         case 0x17:
1478             /* POWERDOWN_MODE */
1479             FLOPPY_DPRINTF("POWERDOWN_MODE command\n");
1480             /* 2 parameters cmd */
1481             fdctrl->data_len = 3;
1482             goto enqueue;
1483         case 0x18:
1484             /* PART_ID */
1485             FLOPPY_DPRINTF("PART_ID command\n");
1486             /* No parameters cmd */
1487             fdctrl->fifo[0] = 0x41; /* Stepping 1 */
1488             fdctrl_set_fifo(fdctrl, 1, 0);
1489             return;
1490         case 0x2C:
1491             /* SAVE */
1492             FLOPPY_DPRINTF("SAVE command\n");
1493             /* No parameters cmd */
1494             fdctrl->fifo[0] = 0;
1495             fdctrl->fifo[1] = 0;
1496             /* Drives position */
1497             fdctrl->fifo[2] = drv0(fdctrl)->track;
1498             fdctrl->fifo[3] = drv1(fdctrl)->track;
1499             fdctrl->fifo[4] = 0;
1500             fdctrl->fifo[5] = 0;
1501             /* timers */
1502             fdctrl->fifo[6] = fdctrl->timer0;
1503             fdctrl->fifo[7] = fdctrl->timer1;
1504             fdctrl->fifo[8] = cur_drv->last_sect;
1505             fdctrl->fifo[9] = (fdctrl->lock << 7) |
1506                 (cur_drv->perpendicular << 2);
1507             fdctrl->fifo[10] = fdctrl->config;
1508             fdctrl->fifo[11] = fdctrl->precomp_trk;
1509             fdctrl->fifo[12] = fdctrl->pwrd;
1510             fdctrl->fifo[13] = 0;
1511             fdctrl->fifo[14] = 0;
1512             fdctrl_set_fifo(fdctrl, 15, 1);
1513             return;
1514         case 0x33:
1515             /* OPTION */
1516             FLOPPY_DPRINTF("OPTION command\n");
1517             /* 1 parameter cmd */
1518             fdctrl->data_len = 2;
1519             goto enqueue;
1520         case 0x42:
1521             /* READ_TRACK */
1522             FLOPPY_DPRINTF("READ_TRACK command\n");
1523             /* 8 parameters cmd */
1524             fdctrl->data_len = 9;
1525             goto enqueue;
1526         case 0x4A:
1527             /* READ_ID */
1528             FLOPPY_DPRINTF("READ_ID command\n");
1529             /* 1 parameter cmd */
1530             fdctrl->data_len = 2;
1531             goto enqueue;
1532         case 0x4C:
1533             /* RESTORE */
1534             FLOPPY_DPRINTF("RESTORE command\n");
1535             /* 17 parameters cmd */
1536             fdctrl->data_len = 18;
1537             goto enqueue;
1538         case 0x4D:
1539             /* FORMAT_TRACK */
1540             FLOPPY_DPRINTF("FORMAT_TRACK command\n");
1541             /* 5 parameters cmd */
1542             fdctrl->data_len = 6;
1543             goto enqueue;
1544         case 0x8E:
1545             /* DRIVE_SPECIFICATION_COMMAND */
1546             FLOPPY_DPRINTF("DRIVE_SPECIFICATION_COMMAND command\n");
1547             /* 5 parameters cmd */
1548             fdctrl->data_len = 6;
1549             goto enqueue;
1550         case 0x8F:
1551             /* RELATIVE_SEEK_OUT */
1552             FLOPPY_DPRINTF("RELATIVE_SEEK_OUT command\n");
1553             /* 2 parameters cmd */
1554             fdctrl->data_len = 3;
1555             goto enqueue;
1556         case 0x94:
1557             /* LOCK */
1558             FLOPPY_DPRINTF("LOCK command\n");
1559             /* No parameters cmd */
1560             fdctrl->lock = 1;
1561             fdctrl->fifo[0] = 0x10;
1562             fdctrl_set_fifo(fdctrl, 1, 1);
1563             return;
1564         case 0xCD:
1565             /* FORMAT_AND_WRITE */
1566             FLOPPY_DPRINTF("FORMAT_AND_WRITE command\n");
1567             /* 10 parameters cmd */
1568             fdctrl->data_len = 11;
1569             goto enqueue;
1570         case 0xCF:
1571             /* RELATIVE_SEEK_IN */
1572             FLOPPY_DPRINTF("RELATIVE_SEEK_IN command\n");
1573             /* 2 parameters cmd */
1574             fdctrl->data_len = 3;
1575             goto enqueue;
1576         default:
1577             /* Unknown command */
1578             FLOPPY_ERROR("unknown command: 0x%02x\n", value);
1579             fdctrl_unimplemented(fdctrl);
1580             return;
1581         }
1582     }
1583  enqueue:
1584     FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
1585     fdctrl->fifo[fdctrl->data_pos] = value;
1586     if (++fdctrl->data_pos == fdctrl->data_len) {
1587         /* We now have all parameters
1588          * and will be able to treat the command
1589          */
1590         if (fdctrl->data_state & FD_STATE_FORMAT) {
1591             fdctrl_format_sector(fdctrl);
1592             return;
1593         }
1594         switch (fdctrl->fifo[0] & 0x1F) {
1595         case 0x06:
1596             {
1597                 /* READ variants */
1598                 FLOPPY_DPRINTF("treat READ command\n");
1599                 fdctrl_start_transfer(fdctrl, FD_DIR_READ);
1600                 return;
1601             }
1602         case 0x0C:
1603             /* READ_DELETED variants */
1604 //            FLOPPY_DPRINTF("treat READ_DELETED command\n");
1605             FLOPPY_ERROR("treat READ_DELETED command\n");
1606             fdctrl_start_transfer_del(fdctrl, FD_DIR_READ);
1607             return;
1608         case 0x16:
1609             /* VERIFY variants */
1610 //            FLOPPY_DPRINTF("treat VERIFY command\n");
1611             FLOPPY_ERROR("treat VERIFY command\n");
1612             fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
1613             return;
1614         case 0x10:
1615             /* SCAN_EQUAL variants */
1616 //            FLOPPY_DPRINTF("treat SCAN_EQUAL command\n");
1617             FLOPPY_ERROR("treat SCAN_EQUAL command\n");
1618             fdctrl_start_transfer(fdctrl, FD_DIR_SCANE);
1619             return;
1620         case 0x19:
1621             /* SCAN_LOW_OR_EQUAL variants */
1622 //            FLOPPY_DPRINTF("treat SCAN_LOW_OR_EQUAL command\n");
1623             FLOPPY_ERROR("treat SCAN_LOW_OR_EQUAL command\n");
1624             fdctrl_start_transfer(fdctrl, FD_DIR_SCANL);
1625             return;
1626         case 0x1D:
1627             /* SCAN_HIGH_OR_EQUAL variants */
1628 //            FLOPPY_DPRINTF("treat SCAN_HIGH_OR_EQUAL command\n");
1629             FLOPPY_ERROR("treat SCAN_HIGH_OR_EQUAL command\n");
1630             fdctrl_start_transfer(fdctrl, FD_DIR_SCANH);
1631             return;
1632         default:
1633             break;
1634         }
1635         switch (fdctrl->fifo[0] & 0x3F) {
1636         case 0x05:
1637             /* WRITE variants */
1638             FLOPPY_DPRINTF("treat WRITE command (%02x)\n", fdctrl->fifo[0]);
1639             fdctrl_start_transfer(fdctrl, FD_DIR_WRITE);
1640             return;
1641         case 0x09:
1642             /* WRITE_DELETED variants */
1643 //            FLOPPY_DPRINTF("treat WRITE_DELETED command\n");
1644             FLOPPY_ERROR("treat WRITE_DELETED command\n");
1645             fdctrl_start_transfer_del(fdctrl, FD_DIR_WRITE);
1646             return;
1647         default:
1648             break;
1649         }
1650         switch (fdctrl->fifo[0]) {
1651         case 0x03:
1652             /* SPECIFY */
1653             FLOPPY_DPRINTF("treat SPECIFY command\n");
1654             fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
1655             fdctrl->timer1 = fdctrl->fifo[2] >> 1;
1656             fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ;
1657             /* No result back */
1658             fdctrl_reset_fifo(fdctrl);
1659             break;
1660         case 0x04:
1661             /* SENSE_DRIVE_STATUS */
1662             FLOPPY_DPRINTF("treat SENSE_DRIVE_STATUS command\n");
1663             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
1664             cur_drv = get_cur_drv(fdctrl);
1665             cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
1666             /* 1 Byte status back */
1667             fdctrl->fifo[0] = (cur_drv->ro << 6) |
1668                 (cur_drv->track == 0 ? 0x10 : 0x00) |
1669                 (cur_drv->head << 2) |
1670                 fdctrl->cur_drv |
1671                 0x28;
1672             fdctrl_set_fifo(fdctrl, 1, 0);
1673             break;
1674         case 0x07:
1675             /* RECALIBRATE */
1676             FLOPPY_DPRINTF("treat RECALIBRATE command\n");
1677             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
1678             cur_drv = get_cur_drv(fdctrl);
1679             fd_recalibrate(cur_drv);
1680             fdctrl_reset_fifo(fdctrl);
1681             /* Raise Interrupt */
1682             fdctrl_raise_irq(fdctrl, 0x20);
1683             break;
1684         case 0x0F:
1685             /* SEEK */
1686             FLOPPY_DPRINTF("treat SEEK command\n");
1687             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
1688             cur_drv = get_cur_drv(fdctrl);
1689             fd_start(cur_drv);
1690             if (fdctrl->fifo[2] <= cur_drv->track)
1691                 cur_drv->dir = 1;
1692             else
1693                 cur_drv->dir = 0;
1694             fdctrl_reset_fifo(fdctrl);
1695             if (fdctrl->fifo[2] > cur_drv->max_track) {
1696                 fdctrl_raise_irq(fdctrl, 0x60);
1697             } else {
1698                 cur_drv->track = fdctrl->fifo[2];
1699                 /* Raise Interrupt */
1700                 fdctrl_raise_irq(fdctrl, 0x20);
1701             }
1702             break;
1703         case 0x12:
1704             /* PERPENDICULAR_MODE */
1705             FLOPPY_DPRINTF("treat PERPENDICULAR_MODE command\n");
1706             if (fdctrl->fifo[1] & 0x80)
1707                 cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
1708             /* No result back */
1709             fdctrl_reset_fifo(fdctrl);
1710             break;
1711         case 0x13:
1712             /* CONFIGURE */
1713             FLOPPY_DPRINTF("treat CONFIGURE command\n");
1714             fdctrl->config = fdctrl->fifo[2];
1715             fdctrl->precomp_trk =  fdctrl->fifo[3];
1716             /* No result back */
1717             fdctrl_reset_fifo(fdctrl);
1718             break;
1719         case 0x17:
1720             /* POWERDOWN_MODE */
1721             FLOPPY_DPRINTF("treat POWERDOWN_MODE command\n");
1722             fdctrl->pwrd = fdctrl->fifo[1];
1723             fdctrl->fifo[0] = fdctrl->fifo[1];
1724             fdctrl_set_fifo(fdctrl, 1, 1);
1725             break;
1726         case 0x33:
1727             /* OPTION */
1728             FLOPPY_DPRINTF("treat OPTION command\n");
1729             /* No result back */
1730             fdctrl_reset_fifo(fdctrl);
1731             break;
1732         case 0x42:
1733             /* READ_TRACK */
1734 //            FLOPPY_DPRINTF("treat READ_TRACK command\n");
1735             FLOPPY_ERROR("treat READ_TRACK command\n");
1736             fdctrl_start_transfer(fdctrl, FD_DIR_READ);
1737             break;
1738         case 0x4A:
1739             /* READ_ID */
1740             FLOPPY_DPRINTF("treat READ_ID command\n");
1741             /* XXX: should set main status register to busy */
1742             cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
1743             qemu_mod_timer(fdctrl->result_timer,
1744                            qemu_get_clock(vm_clock) + (ticks_per_sec / 50));
1745             break;
1746         case 0x4C:
1747             /* RESTORE */
1748             FLOPPY_DPRINTF("treat RESTORE command\n");
1749             /* Drives position */
1750             drv0(fdctrl)->track = fdctrl->fifo[3];
1751             drv1(fdctrl)->track = fdctrl->fifo[4];
1752             /* timers */
1753             fdctrl->timer0 = fdctrl->fifo[7];
1754             fdctrl->timer1 = fdctrl->fifo[8];
1755             cur_drv->last_sect = fdctrl->fifo[9];
1756             fdctrl->lock = fdctrl->fifo[10] >> 7;
1757             cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
1758             fdctrl->config = fdctrl->fifo[11];
1759             fdctrl->precomp_trk = fdctrl->fifo[12];
1760             fdctrl->pwrd = fdctrl->fifo[13];
1761             fdctrl_reset_fifo(fdctrl);
1762             break;
1763         case 0x4D:
1764             /* FORMAT_TRACK */
1765             FLOPPY_DPRINTF("treat FORMAT_TRACK command\n");
1766             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
1767             cur_drv = get_cur_drv(fdctrl);
1768             fdctrl->data_state |= FD_STATE_FORMAT;
1769             if (fdctrl->fifo[0] & 0x80)
1770                 fdctrl->data_state |= FD_STATE_MULTI;
1771             else
1772                 fdctrl->data_state &= ~FD_STATE_MULTI;
1773             fdctrl->data_state &= ~FD_STATE_SEEK;
1774             cur_drv->bps =
1775                 fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
1776 #if 0
1777             cur_drv->last_sect =
1778                 cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
1779                 fdctrl->fifo[3] / 2;
1780 #else
1781             cur_drv->last_sect = fdctrl->fifo[3];
1782 #endif
1783             /* TODO: implement format using DMA expected by the Bochs BIOS
1784              * and Linux fdformat (read 3 bytes per sector via DMA and fill
1785              * the sector with the specified fill byte
1786              */
1787             fdctrl->data_state &= ~FD_STATE_FORMAT;
1788             fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1789             break;
1790         case 0x8E:
1791             /* DRIVE_SPECIFICATION_COMMAND */
1792             FLOPPY_DPRINTF("treat DRIVE_SPECIFICATION_COMMAND command\n");
1793             if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
1794                 /* Command parameters done */
1795                 if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
1796                     fdctrl->fifo[0] = fdctrl->fifo[1];
1797                     fdctrl->fifo[2] = 0;
1798                     fdctrl->fifo[3] = 0;
1799                     fdctrl_set_fifo(fdctrl, 4, 1);
1800                 } else {
1801                     fdctrl_reset_fifo(fdctrl);
1802                 }
1803             } else if (fdctrl->data_len > 7) {
1804                 /* ERROR */
1805                 fdctrl->fifo[0] = 0x80 |
1806                     (cur_drv->head << 2) | fdctrl->cur_drv;
1807                 fdctrl_set_fifo(fdctrl, 1, 1);
1808             }
1809             break;
1810         case 0x8F:
1811             /* RELATIVE_SEEK_OUT */
1812             FLOPPY_DPRINTF("treat RELATIVE_SEEK_OUT command\n");
1813             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
1814             cur_drv = get_cur_drv(fdctrl);
1815             fd_start(cur_drv);
1816             cur_drv->dir = 0;
1817             if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
1818                 cur_drv->track = cur_drv->max_track - 1;
1819             } else {
1820                 cur_drv->track += fdctrl->fifo[2];
1821             }
1822             fdctrl_reset_fifo(fdctrl);
1823             fdctrl_raise_irq(fdctrl, 0x20);
1824             break;
1825         case 0xCD:
1826             /* FORMAT_AND_WRITE */
1827 //                FLOPPY_DPRINTF("treat FORMAT_AND_WRITE command\n");
1828             FLOPPY_ERROR("treat FORMAT_AND_WRITE command\n");
1829             fdctrl_unimplemented(fdctrl);
1830             break;
1831         case 0xCF:
1832             /* RELATIVE_SEEK_IN */
1833             FLOPPY_DPRINTF("treat RELATIVE_SEEK_IN command\n");
1834             fdctrl->cur_drv = fdctrl->fifo[1] & 1;
1835             cur_drv = get_cur_drv(fdctrl);
1836             fd_start(cur_drv);
1837             cur_drv->dir = 1;
1838             if (fdctrl->fifo[2] > cur_drv->track) {
1839                 cur_drv->track = 0;
1840             } else {
1841                 cur_drv->track -= fdctrl->fifo[2];
1842             }
1843             fdctrl_reset_fifo(fdctrl);
1844             /* Raise Interrupt */
1845             fdctrl_raise_irq(fdctrl, 0x20);
1846             break;
1847         }
1848     }
1849 }
1850
1851 static void fdctrl_result_timer(void *opaque)
1852 {
1853     fdctrl_t *fdctrl = opaque;
1854     fdrive_t *cur_drv = get_cur_drv(fdctrl);
1855
1856     /* Pretend we are spinning.
1857      * This is needed for Coherent, which uses READ ID to check for
1858      * sector interleaving.
1859      */
1860     if (cur_drv->last_sect != 0) {
1861         cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1;
1862     }
1863     fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1864 }