Statistics
| Branch: | Revision:

root / hw / fdc.c @ 11257187

History | View | Annotate | Download (60.4 kB)

1
/*
2
 * QEMU Floppy disk emulator (Intel 82078)
3
 *
4
 * Copyright (c) 2003, 2007 Jocelyn Mayer
5
 * Copyright (c) 2008 Herv? Poussineau
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
/*
26
 * The controller is used in Sun4m systems in a slightly different
27
 * way. There are changes in DOR register and DMA is not available.
28
 */
29

    
30
#include "hw.h"
31
#include "fdc.h"
32
#include "qemu-error.h"
33
#include "qemu-timer.h"
34
#include "isa.h"
35
#include "sysbus.h"
36
#include "qdev-addr.h"
37
#include "blockdev.h"
38
#include "sysemu.h"
39
#include "block_int.h"
40

    
41
/********************************************************/
42
/* debug Floppy devices */
43
//#define DEBUG_FLOPPY
44

    
45
#ifdef DEBUG_FLOPPY
46
#define FLOPPY_DPRINTF(fmt, ...)                                \
47
    do { printf("FLOPPY: " fmt , ## __VA_ARGS__); } while (0)
48
#else
49
#define FLOPPY_DPRINTF(fmt, ...)
50
#endif
51

    
52
#define FLOPPY_ERROR(fmt, ...)                                          \
53
    do { printf("FLOPPY ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
54

    
55
/********************************************************/
56
/* Floppy drive emulation                               */
57

    
58
#define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
59
#define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
60

    
61
/* Will always be a fixed parameter for us */
62
#define FD_SECTOR_LEN          512
63
#define FD_SECTOR_SC           2   /* Sector size code */
64
#define FD_RESET_SENSEI_COUNT  4   /* Number of sense interrupts on RESET */
65

    
66
/* Floppy disk drive emulation */
67
typedef enum FDiskFlags {
68
    FDISK_DBL_SIDES  = 0x01,
69
} FDiskFlags;
70

    
71
typedef struct FDrive {
72
    BlockDriverState *bs;
73
    /* Drive status */
74
    FDriveType drive;
75
    uint8_t perpendicular;    /* 2.88 MB access mode    */
76
    /* Position */
77
    uint8_t head;
78
    uint8_t track;
79
    uint8_t sect;
80
    /* Media */
81
    FDiskFlags flags;
82
    uint8_t last_sect;        /* Nb sector per track    */
83
    uint8_t max_track;        /* Nb of tracks           */
84
    uint16_t bps;             /* Bytes per sector       */
85
    uint8_t ro;               /* Is read-only           */
86
    uint8_t media_changed;    /* Is media changed       */
87
} FDrive;
88

    
89
static void fd_init(FDrive *drv)
90
{
91
    /* Drive */
92
    drv->drive = FDRIVE_DRV_NONE;
93
    drv->perpendicular = 0;
94
    /* Disk */
95
    drv->last_sect = 0;
96
    drv->max_track = 0;
97
}
98

    
99
static int fd_sector_calc(uint8_t head, uint8_t track, uint8_t sect,
100
                          uint8_t last_sect)
101
{
102
    return (((track * 2) + head) * last_sect) + sect - 1;
103
}
104

    
105
/* Returns current position, in sectors, for given drive */
106
static int fd_sector(FDrive *drv)
107
{
108
    return fd_sector_calc(drv->head, drv->track, drv->sect, drv->last_sect);
109
}
110

    
111
/* Seek to a new position:
112
 * returns 0 if already on right track
113
 * returns 1 if track changed
114
 * returns 2 if track is invalid
115
 * returns 3 if sector is invalid
116
 * returns 4 if seek is disabled
117
 */
118
static int fd_seek(FDrive *drv, uint8_t head, uint8_t track, uint8_t sect,
119
                   int enable_seek)
120
{
121
    uint32_t sector;
122
    int ret;
123

    
124
    if (track > drv->max_track ||
125
        (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
126
        FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
127
                       head, track, sect, 1,
128
                       (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
129
                       drv->max_track, drv->last_sect);
130
        return 2;
131
    }
132
    if (sect > drv->last_sect) {
133
        FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
134
                       head, track, sect, 1,
135
                       (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
136
                       drv->max_track, drv->last_sect);
137
        return 3;
138
    }
139
    sector = fd_sector_calc(head, track, sect, drv->last_sect);
140
    ret = 0;
141
    if (sector != fd_sector(drv)) {
142
#if 0
143
        if (!enable_seek) {
144
            FLOPPY_ERROR("no implicit seek %d %02x %02x (max=%d %02x %02x)\n",
145
                         head, track, sect, 1, drv->max_track, drv->last_sect);
146
            return 4;
147
        }
148
#endif
149
        drv->head = head;
150
        if (drv->track != track)
151
            ret = 1;
152
        drv->track = track;
153
        drv->sect = sect;
154
    }
155

    
156
    return ret;
157
}
158

    
159
/* Set drive back to track 0 */
160
static void fd_recalibrate(FDrive *drv)
161
{
162
    FLOPPY_DPRINTF("recalibrate\n");
163
    drv->head = 0;
164
    drv->track = 0;
165
    drv->sect = 1;
166
}
167

    
168
/* Revalidate a disk drive after a disk change */
169
static void fd_revalidate(FDrive *drv)
170
{
171
    int nb_heads, max_track, last_sect, ro;
172
    FDriveType drive;
173

    
174
    FLOPPY_DPRINTF("revalidate\n");
175
    if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
176
        ro = bdrv_is_read_only(drv->bs);
177
        bdrv_get_floppy_geometry_hint(drv->bs, &nb_heads, &max_track,
178
                                      &last_sect, drv->drive, &drive);
179
        if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
180
            FLOPPY_DPRINTF("User defined disk (%d %d %d)",
181
                           nb_heads - 1, max_track, last_sect);
182
        } else {
183
            FLOPPY_DPRINTF("Floppy disk (%d h %d t %d s) %s\n", nb_heads,
184
                           max_track, last_sect, ro ? "ro" : "rw");
185
        }
186
        if (nb_heads == 1) {
187
            drv->flags &= ~FDISK_DBL_SIDES;
188
        } else {
189
            drv->flags |= FDISK_DBL_SIDES;
190
        }
191
        drv->max_track = max_track;
192
        drv->last_sect = last_sect;
193
        drv->ro = ro;
194
        drv->drive = drive;
195
    } else {
196
        FLOPPY_DPRINTF("No disk in drive\n");
197
        drv->last_sect = 0;
198
        drv->max_track = 0;
199
        drv->flags &= ~FDISK_DBL_SIDES;
200
    }
201
}
202

    
203
/********************************************************/
204
/* Intel 82078 floppy disk controller emulation          */
205

    
206
typedef struct FDCtrl FDCtrl;
207

    
208
static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
209
static void fdctrl_reset_fifo(FDCtrl *fdctrl);
210
static int fdctrl_transfer_handler (void *opaque, int nchan,
211
                                    int dma_pos, int dma_len);
212
static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0);
213

    
214
static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl);
215
static uint32_t fdctrl_read_statusB(FDCtrl *fdctrl);
216
static uint32_t fdctrl_read_dor(FDCtrl *fdctrl);
217
static void fdctrl_write_dor(FDCtrl *fdctrl, uint32_t value);
218
static uint32_t fdctrl_read_tape(FDCtrl *fdctrl);
219
static void fdctrl_write_tape(FDCtrl *fdctrl, uint32_t value);
220
static uint32_t fdctrl_read_main_status(FDCtrl *fdctrl);
221
static void fdctrl_write_rate(FDCtrl *fdctrl, uint32_t value);
222
static uint32_t fdctrl_read_data(FDCtrl *fdctrl);
223
static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value);
224
static uint32_t fdctrl_read_dir(FDCtrl *fdctrl);
225

    
226
enum {
227
    FD_DIR_WRITE   = 0,
228
    FD_DIR_READ    = 1,
229
    FD_DIR_SCANE   = 2,
230
    FD_DIR_SCANL   = 3,
231
    FD_DIR_SCANH   = 4,
232
};
233

    
234
enum {
235
    FD_STATE_MULTI  = 0x01,        /* multi track flag */
236
    FD_STATE_FORMAT = 0x02,        /* format flag */
237
    FD_STATE_SEEK   = 0x04,        /* seek flag */
238
};
239

    
240
enum {
241
    FD_REG_SRA = 0x00,
242
    FD_REG_SRB = 0x01,
243
    FD_REG_DOR = 0x02,
244
    FD_REG_TDR = 0x03,
245
    FD_REG_MSR = 0x04,
246
    FD_REG_DSR = 0x04,
247
    FD_REG_FIFO = 0x05,
248
    FD_REG_DIR = 0x07,
249
};
250

    
251
enum {
252
    FD_CMD_READ_TRACK = 0x02,
253
    FD_CMD_SPECIFY = 0x03,
254
    FD_CMD_SENSE_DRIVE_STATUS = 0x04,
255
    FD_CMD_WRITE = 0x05,
256
    FD_CMD_READ = 0x06,
257
    FD_CMD_RECALIBRATE = 0x07,
258
    FD_CMD_SENSE_INTERRUPT_STATUS = 0x08,
259
    FD_CMD_WRITE_DELETED = 0x09,
260
    FD_CMD_READ_ID = 0x0a,
261
    FD_CMD_READ_DELETED = 0x0c,
262
    FD_CMD_FORMAT_TRACK = 0x0d,
263
    FD_CMD_DUMPREG = 0x0e,
264
    FD_CMD_SEEK = 0x0f,
265
    FD_CMD_VERSION = 0x10,
266
    FD_CMD_SCAN_EQUAL = 0x11,
267
    FD_CMD_PERPENDICULAR_MODE = 0x12,
268
    FD_CMD_CONFIGURE = 0x13,
269
    FD_CMD_LOCK = 0x14,
270
    FD_CMD_VERIFY = 0x16,
271
    FD_CMD_POWERDOWN_MODE = 0x17,
272
    FD_CMD_PART_ID = 0x18,
273
    FD_CMD_SCAN_LOW_OR_EQUAL = 0x19,
274
    FD_CMD_SCAN_HIGH_OR_EQUAL = 0x1d,
275
    FD_CMD_SAVE = 0x2e,
276
    FD_CMD_OPTION = 0x33,
277
    FD_CMD_RESTORE = 0x4e,
278
    FD_CMD_DRIVE_SPECIFICATION_COMMAND = 0x8e,
279
    FD_CMD_RELATIVE_SEEK_OUT = 0x8f,
280
    FD_CMD_FORMAT_AND_WRITE = 0xcd,
281
    FD_CMD_RELATIVE_SEEK_IN = 0xcf,
282
};
283

    
284
enum {
285
    FD_CONFIG_PRETRK = 0xff, /* Pre-compensation set to track 0 */
286
    FD_CONFIG_FIFOTHR = 0x0f, /* FIFO threshold set to 1 byte */
287
    FD_CONFIG_POLL  = 0x10, /* Poll enabled */
288
    FD_CONFIG_EFIFO = 0x20, /* FIFO disabled */
289
    FD_CONFIG_EIS   = 0x40, /* No implied seeks */
290
};
291

    
292
enum {
293
    FD_SR0_EQPMT    = 0x10,
294
    FD_SR0_SEEK     = 0x20,
295
    FD_SR0_ABNTERM  = 0x40,
296
    FD_SR0_INVCMD   = 0x80,
297
    FD_SR0_RDYCHG   = 0xc0,
298
};
299

    
300
enum {
301
    FD_SR1_EC       = 0x80, /* End of cylinder */
302
};
303

    
304
enum {
305
    FD_SR2_SNS      = 0x04, /* Scan not satisfied */
306
    FD_SR2_SEH      = 0x08, /* Scan equal hit */
307
};
308

    
309
enum {
310
    FD_SRA_DIR      = 0x01,
311
    FD_SRA_nWP      = 0x02,
312
    FD_SRA_nINDX    = 0x04,
313
    FD_SRA_HDSEL    = 0x08,
314
    FD_SRA_nTRK0    = 0x10,
315
    FD_SRA_STEP     = 0x20,
316
    FD_SRA_nDRV2    = 0x40,
317
    FD_SRA_INTPEND  = 0x80,
318
};
319

    
320
enum {
321
    FD_SRB_MTR0     = 0x01,
322
    FD_SRB_MTR1     = 0x02,
323
    FD_SRB_WGATE    = 0x04,
324
    FD_SRB_RDATA    = 0x08,
325
    FD_SRB_WDATA    = 0x10,
326
    FD_SRB_DR0      = 0x20,
327
};
328

    
329
enum {
330
#if MAX_FD == 4
331
    FD_DOR_SELMASK  = 0x03,
332
#else
333
    FD_DOR_SELMASK  = 0x01,
334
#endif
335
    FD_DOR_nRESET   = 0x04,
336
    FD_DOR_DMAEN    = 0x08,
337
    FD_DOR_MOTEN0   = 0x10,
338
    FD_DOR_MOTEN1   = 0x20,
339
    FD_DOR_MOTEN2   = 0x40,
340
    FD_DOR_MOTEN3   = 0x80,
341
};
342

    
343
enum {
344
#if MAX_FD == 4
345
    FD_TDR_BOOTSEL  = 0x0c,
346
#else
347
    FD_TDR_BOOTSEL  = 0x04,
348
#endif
349
};
350

    
351
enum {
352
    FD_DSR_DRATEMASK= 0x03,
353
    FD_DSR_PWRDOWN  = 0x40,
354
    FD_DSR_SWRESET  = 0x80,
355
};
356

    
357
enum {
358
    FD_MSR_DRV0BUSY = 0x01,
359
    FD_MSR_DRV1BUSY = 0x02,
360
    FD_MSR_DRV2BUSY = 0x04,
361
    FD_MSR_DRV3BUSY = 0x08,
362
    FD_MSR_CMDBUSY  = 0x10,
363
    FD_MSR_NONDMA   = 0x20,
364
    FD_MSR_DIO      = 0x40,
365
    FD_MSR_RQM      = 0x80,
366
};
367

    
368
enum {
369
    FD_DIR_DSKCHG   = 0x80,
370
};
371

    
372
#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
373
#define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
374
#define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
375

    
376
struct FDCtrl {
377
    /* Controller's identification */
378
    uint8_t version;
379
    /* HW */
380
    qemu_irq irq;
381
    int dma_chann;
382
    /* Controller state */
383
    QEMUTimer *result_timer;
384
    uint8_t sra;
385
    uint8_t srb;
386
    uint8_t dor;
387
    uint8_t dor_vmstate; /* only used as temp during vmstate */
388
    uint8_t tdr;
389
    uint8_t dsr;
390
    uint8_t msr;
391
    uint8_t cur_drv;
392
    uint8_t status0;
393
    uint8_t status1;
394
    uint8_t status2;
395
    /* Command FIFO */
396
    uint8_t *fifo;
397
    int32_t fifo_size;
398
    uint32_t data_pos;
399
    uint32_t data_len;
400
    uint8_t data_state;
401
    uint8_t data_dir;
402
    uint8_t eot; /* last wanted sector */
403
    /* States kept only to be returned back */
404
    /* Timers state */
405
    uint8_t timer0;
406
    uint8_t timer1;
407
    /* precompensation */
408
    uint8_t precomp_trk;
409
    uint8_t config;
410
    uint8_t lock;
411
    /* Power down config (also with status regB access mode */
412
    uint8_t pwrd;
413
    /* Sun4m quirks? */
414
    int sun4m;
415
    /* Floppy drives */
416
    uint8_t num_floppies;
417
    FDrive drives[MAX_FD];
418
    int reset_sensei;
419
};
420

    
421
typedef struct FDCtrlSysBus {
422
    SysBusDevice busdev;
423
    struct FDCtrl state;
424
} FDCtrlSysBus;
425

    
426
typedef struct FDCtrlISABus {
427
    ISADevice busdev;
428
    struct FDCtrl state;
429
    int32_t bootindexA;
430
    int32_t bootindexB;
431
} FDCtrlISABus;
432

    
433
static uint32_t fdctrl_read (void *opaque, uint32_t reg)
434
{
435
    FDCtrl *fdctrl = opaque;
436
    uint32_t retval;
437

    
438
    switch (reg) {
439
    case FD_REG_SRA:
440
        retval = fdctrl_read_statusA(fdctrl);
441
        break;
442
    case FD_REG_SRB:
443
        retval = fdctrl_read_statusB(fdctrl);
444
        break;
445
    case FD_REG_DOR:
446
        retval = fdctrl_read_dor(fdctrl);
447
        break;
448
    case FD_REG_TDR:
449
        retval = fdctrl_read_tape(fdctrl);
450
        break;
451
    case FD_REG_MSR:
452
        retval = fdctrl_read_main_status(fdctrl);
453
        break;
454
    case FD_REG_FIFO:
455
        retval = fdctrl_read_data(fdctrl);
456
        break;
457
    case FD_REG_DIR:
458
        retval = fdctrl_read_dir(fdctrl);
459
        break;
460
    default:
461
        retval = (uint32_t)(-1);
462
        break;
463
    }
464
    FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
465

    
466
    return retval;
467
}
468

    
469
static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
470
{
471
    FDCtrl *fdctrl = opaque;
472

    
473
    FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
474

    
475
    switch (reg) {
476
    case FD_REG_DOR:
477
        fdctrl_write_dor(fdctrl, value);
478
        break;
479
    case FD_REG_TDR:
480
        fdctrl_write_tape(fdctrl, value);
481
        break;
482
    case FD_REG_DSR:
483
        fdctrl_write_rate(fdctrl, value);
484
        break;
485
    case FD_REG_FIFO:
486
        fdctrl_write_data(fdctrl, value);
487
        break;
488
    default:
489
        break;
490
    }
491
}
492

    
493
static uint32_t fdctrl_read_port (void *opaque, uint32_t reg)
494
{
495
    return fdctrl_read(opaque, reg & 7);
496
}
497

    
498
static void fdctrl_write_port (void *opaque, uint32_t reg, uint32_t value)
499
{
500
    fdctrl_write(opaque, reg & 7, value);
501
}
502

    
503
static uint32_t fdctrl_read_mem (void *opaque, target_phys_addr_t reg)
504
{
505
    return fdctrl_read(opaque, (uint32_t)reg);
506
}
507

    
508
static void fdctrl_write_mem (void *opaque,
509
                              target_phys_addr_t reg, uint32_t value)
510
{
511
    fdctrl_write(opaque, (uint32_t)reg, value);
512
}
513

    
514
static CPUReadMemoryFunc * const fdctrl_mem_read[3] = {
515
    fdctrl_read_mem,
516
    fdctrl_read_mem,
517
    fdctrl_read_mem,
518
};
519

    
520
static CPUWriteMemoryFunc * const fdctrl_mem_write[3] = {
521
    fdctrl_write_mem,
522
    fdctrl_write_mem,
523
    fdctrl_write_mem,
524
};
525

    
526
static CPUReadMemoryFunc * const fdctrl_mem_read_strict[3] = {
527
    fdctrl_read_mem,
528
    NULL,
529
    NULL,
530
};
531

    
532
static CPUWriteMemoryFunc * const fdctrl_mem_write_strict[3] = {
533
    fdctrl_write_mem,
534
    NULL,
535
    NULL,
536
};
537

    
538
static void fdrive_media_changed_pre_save(void *opaque)
539
{
540
    FDrive *drive = opaque;
541

    
542
    drive->media_changed = drive->bs->media_changed;
543
}
544

    
545
static int fdrive_media_changed_post_load(void *opaque, int version_id)
546
{
547
    FDrive *drive = opaque;
548

    
549
    if (drive->bs != NULL) {
550
        drive->bs->media_changed = drive->media_changed;
551
    }
552

    
553
    /* User ejected the floppy when drive->bs == NULL */
554
    return 0;
555
}
556

    
557
static bool fdrive_media_changed_needed(void *opaque)
558
{
559
    FDrive *drive = opaque;
560

    
561
    return (drive->bs != NULL && drive->bs->media_changed != 1);
562
}
563

    
564
static const VMStateDescription vmstate_fdrive_media_changed = {
565
    .name = "fdrive/media_changed",
566
    .version_id = 1,
567
    .minimum_version_id = 1,
568
    .minimum_version_id_old = 1,
569
    .pre_save = fdrive_media_changed_pre_save,
570
    .post_load = fdrive_media_changed_post_load,
571
    .fields      = (VMStateField[]) {
572
        VMSTATE_UINT8(media_changed, FDrive),
573
        VMSTATE_END_OF_LIST()
574
    }
575
};
576

    
577
static const VMStateDescription vmstate_fdrive = {
578
    .name = "fdrive",
579
    .version_id = 1,
580
    .minimum_version_id = 1,
581
    .minimum_version_id_old = 1,
582
    .fields      = (VMStateField[]) {
583
        VMSTATE_UINT8(head, FDrive),
584
        VMSTATE_UINT8(track, FDrive),
585
        VMSTATE_UINT8(sect, FDrive),
586
        VMSTATE_END_OF_LIST()
587
    },
588
    .subsections = (VMStateSubsection[]) {
589
        {
590
            .vmsd = &vmstate_fdrive_media_changed,
591
            .needed = &fdrive_media_changed_needed,
592
        } , {
593
            /* empty */
594
        }
595
    }
596
};
597

    
598
static void fdc_pre_save(void *opaque)
599
{
600
    FDCtrl *s = opaque;
601

    
602
    s->dor_vmstate = s->dor | GET_CUR_DRV(s);
603
}
604

    
605
static int fdc_post_load(void *opaque, int version_id)
606
{
607
    FDCtrl *s = opaque;
608

    
609
    SET_CUR_DRV(s, s->dor_vmstate & FD_DOR_SELMASK);
610
    s->dor = s->dor_vmstate & ~FD_DOR_SELMASK;
611
    return 0;
612
}
613

    
614
static const VMStateDescription vmstate_fdc = {
615
    .name = "fdc",
616
    .version_id = 2,
617
    .minimum_version_id = 2,
618
    .minimum_version_id_old = 2,
619
    .pre_save = fdc_pre_save,
620
    .post_load = fdc_post_load,
621
    .fields      = (VMStateField []) {
622
        /* Controller State */
623
        VMSTATE_UINT8(sra, FDCtrl),
624
        VMSTATE_UINT8(srb, FDCtrl),
625
        VMSTATE_UINT8(dor_vmstate, FDCtrl),
626
        VMSTATE_UINT8(tdr, FDCtrl),
627
        VMSTATE_UINT8(dsr, FDCtrl),
628
        VMSTATE_UINT8(msr, FDCtrl),
629
        VMSTATE_UINT8(status0, FDCtrl),
630
        VMSTATE_UINT8(status1, FDCtrl),
631
        VMSTATE_UINT8(status2, FDCtrl),
632
        /* Command FIFO */
633
        VMSTATE_VARRAY_INT32(fifo, FDCtrl, fifo_size, 0, vmstate_info_uint8,
634
                             uint8_t),
635
        VMSTATE_UINT32(data_pos, FDCtrl),
636
        VMSTATE_UINT32(data_len, FDCtrl),
637
        VMSTATE_UINT8(data_state, FDCtrl),
638
        VMSTATE_UINT8(data_dir, FDCtrl),
639
        VMSTATE_UINT8(eot, FDCtrl),
640
        /* States kept only to be returned back */
641
        VMSTATE_UINT8(timer0, FDCtrl),
642
        VMSTATE_UINT8(timer1, FDCtrl),
643
        VMSTATE_UINT8(precomp_trk, FDCtrl),
644
        VMSTATE_UINT8(config, FDCtrl),
645
        VMSTATE_UINT8(lock, FDCtrl),
646
        VMSTATE_UINT8(pwrd, FDCtrl),
647
        VMSTATE_UINT8_EQUAL(num_floppies, FDCtrl),
648
        VMSTATE_STRUCT_ARRAY(drives, FDCtrl, MAX_FD, 1,
649
                             vmstate_fdrive, FDrive),
650
        VMSTATE_END_OF_LIST()
651
    }
652
};
653

    
654
static void fdctrl_external_reset_sysbus(DeviceState *d)
655
{
656
    FDCtrlSysBus *sys = container_of(d, FDCtrlSysBus, busdev.qdev);
657
    FDCtrl *s = &sys->state;
658

    
659
    fdctrl_reset(s, 0);
660
}
661

    
662
static void fdctrl_external_reset_isa(DeviceState *d)
663
{
664
    FDCtrlISABus *isa = container_of(d, FDCtrlISABus, busdev.qdev);
665
    FDCtrl *s = &isa->state;
666

    
667
    fdctrl_reset(s, 0);
668
}
669

    
670
static void fdctrl_handle_tc(void *opaque, int irq, int level)
671
{
672
    //FDCtrl *s = opaque;
673

    
674
    if (level) {
675
        // XXX
676
        FLOPPY_DPRINTF("TC pulsed\n");
677
    }
678
}
679

    
680
/* Change IRQ state */
681
static void fdctrl_reset_irq(FDCtrl *fdctrl)
682
{
683
    if (!(fdctrl->sra & FD_SRA_INTPEND))
684
        return;
685
    FLOPPY_DPRINTF("Reset interrupt\n");
686
    qemu_set_irq(fdctrl->irq, 0);
687
    fdctrl->sra &= ~FD_SRA_INTPEND;
688
}
689

    
690
static void fdctrl_raise_irq(FDCtrl *fdctrl, uint8_t status0)
691
{
692
    /* Sparc mutation */
693
    if (fdctrl->sun4m && (fdctrl->msr & FD_MSR_CMDBUSY)) {
694
        /* XXX: not sure */
695
        fdctrl->msr &= ~FD_MSR_CMDBUSY;
696
        fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
697
        fdctrl->status0 = status0;
698
        return;
699
    }
700
    if (!(fdctrl->sra & FD_SRA_INTPEND)) {
701
        qemu_set_irq(fdctrl->irq, 1);
702
        fdctrl->sra |= FD_SRA_INTPEND;
703
    }
704
    fdctrl->reset_sensei = 0;
705
    fdctrl->status0 = status0;
706
    FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", fdctrl->status0);
707
}
708

    
709
/* Reset controller */
710
static void fdctrl_reset(FDCtrl *fdctrl, int do_irq)
711
{
712
    int i;
713

    
714
    FLOPPY_DPRINTF("reset controller\n");
715
    fdctrl_reset_irq(fdctrl);
716
    /* Initialise controller */
717
    fdctrl->sra = 0;
718
    fdctrl->srb = 0xc0;
719
    if (!fdctrl->drives[1].bs)
720
        fdctrl->sra |= FD_SRA_nDRV2;
721
    fdctrl->cur_drv = 0;
722
    fdctrl->dor = FD_DOR_nRESET;
723
    fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
724
    fdctrl->msr = FD_MSR_RQM;
725
    /* FIFO state */
726
    fdctrl->data_pos = 0;
727
    fdctrl->data_len = 0;
728
    fdctrl->data_state = 0;
729
    fdctrl->data_dir = FD_DIR_WRITE;
730
    for (i = 0; i < MAX_FD; i++)
731
        fd_recalibrate(&fdctrl->drives[i]);
732
    fdctrl_reset_fifo(fdctrl);
733
    if (do_irq) {
734
        fdctrl_raise_irq(fdctrl, FD_SR0_RDYCHG);
735
        fdctrl->reset_sensei = FD_RESET_SENSEI_COUNT;
736
    }
737
}
738

    
739
static inline FDrive *drv0(FDCtrl *fdctrl)
740
{
741
    return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2];
742
}
743

    
744
static inline FDrive *drv1(FDCtrl *fdctrl)
745
{
746
    if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2))
747
        return &fdctrl->drives[1];
748
    else
749
        return &fdctrl->drives[0];
750
}
751

    
752
#if MAX_FD == 4
753
static inline FDrive *drv2(FDCtrl *fdctrl)
754
{
755
    if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2))
756
        return &fdctrl->drives[2];
757
    else
758
        return &fdctrl->drives[1];
759
}
760

    
761
static inline FDrive *drv3(FDCtrl *fdctrl)
762
{
763
    if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2))
764
        return &fdctrl->drives[3];
765
    else
766
        return &fdctrl->drives[2];
767
}
768
#endif
769

    
770
static FDrive *get_cur_drv(FDCtrl *fdctrl)
771
{
772
    switch (fdctrl->cur_drv) {
773
        case 0: return drv0(fdctrl);
774
        case 1: return drv1(fdctrl);
775
#if MAX_FD == 4
776
        case 2: return drv2(fdctrl);
777
        case 3: return drv3(fdctrl);
778
#endif
779
        default: return NULL;
780
    }
781
}
782

    
783
/* Status A register : 0x00 (read-only) */
784
static uint32_t fdctrl_read_statusA(FDCtrl *fdctrl)
785
{
786
    uint32_t retval = fdctrl->sra;
787

    
788
    FLOPPY_DPRINTF("status register A: 0x%02x\n", retval);
789

    
790
    return retval;
791
}
792

    
793
/* Status B register : 0x01 (read-only) */
794
static uint32_t fdctrl_read_statusB(FDCtrl *fdctrl)
795
{
796
    uint32_t retval = fdctrl->srb;
797

    
798
    FLOPPY_DPRINTF("status register B: 0x%02x\n", retval);
799

    
800
    return retval;
801
}
802

    
803
/* Digital output register : 0x02 */
804
static uint32_t fdctrl_read_dor(FDCtrl *fdctrl)
805
{
806
    uint32_t retval = fdctrl->dor;
807

    
808
    /* Selected drive */
809
    retval |= fdctrl->cur_drv;
810
    FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);
811

    
812
    return retval;
813
}
814

    
815
static void fdctrl_write_dor(FDCtrl *fdctrl, uint32_t value)
816
{
817
    FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
818

    
819
    /* Motors */
820
    if (value & FD_DOR_MOTEN0)
821
        fdctrl->srb |= FD_SRB_MTR0;
822
    else
823
        fdctrl->srb &= ~FD_SRB_MTR0;
824
    if (value & FD_DOR_MOTEN1)
825
        fdctrl->srb |= FD_SRB_MTR1;
826
    else
827
        fdctrl->srb &= ~FD_SRB_MTR1;
828

    
829
    /* Drive */
830
    if (value & 1)
831
        fdctrl->srb |= FD_SRB_DR0;
832
    else
833
        fdctrl->srb &= ~FD_SRB_DR0;
834

    
835
    /* Reset */
836
    if (!(value & FD_DOR_nRESET)) {
837
        if (fdctrl->dor & FD_DOR_nRESET) {
838
            FLOPPY_DPRINTF("controller enter RESET state\n");
839
        }
840
    } else {
841
        if (!(fdctrl->dor & FD_DOR_nRESET)) {
842
            FLOPPY_DPRINTF("controller out of RESET state\n");
843
            fdctrl_reset(fdctrl, 1);
844
            fdctrl->dsr &= ~FD_DSR_PWRDOWN;
845
        }
846
    }
847
    /* Selected drive */
848
    fdctrl->cur_drv = value & FD_DOR_SELMASK;
849

    
850
    fdctrl->dor = value;
851
}
852

    
853
/* Tape drive register : 0x03 */
854
static uint32_t fdctrl_read_tape(FDCtrl *fdctrl)
855
{
856
    uint32_t retval = fdctrl->tdr;
857

    
858
    FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval);
859

    
860
    return retval;
861
}
862

    
863
static void fdctrl_write_tape(FDCtrl *fdctrl, uint32_t value)
864
{
865
    /* Reset mode */
866
    if (!(fdctrl->dor & FD_DOR_nRESET)) {
867
        FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
868
        return;
869
    }
870
    FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
871
    /* Disk boot selection indicator */
872
    fdctrl->tdr = value & FD_TDR_BOOTSEL;
873
    /* Tape indicators: never allow */
874
}
875

    
876
/* Main status register : 0x04 (read) */
877
static uint32_t fdctrl_read_main_status(FDCtrl *fdctrl)
878
{
879
    uint32_t retval = fdctrl->msr;
880

    
881
    fdctrl->dsr &= ~FD_DSR_PWRDOWN;
882
    fdctrl->dor |= FD_DOR_nRESET;
883

    
884
    /* Sparc mutation */
885
    if (fdctrl->sun4m) {
886
        retval |= FD_MSR_DIO;
887
        fdctrl_reset_irq(fdctrl);
888
    };
889

    
890
    FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
891

    
892
    return retval;
893
}
894

    
895
/* Data select rate register : 0x04 (write) */
896
static void fdctrl_write_rate(FDCtrl *fdctrl, uint32_t value)
897
{
898
    /* Reset mode */
899
    if (!(fdctrl->dor & FD_DOR_nRESET)) {
900
        FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
901
        return;
902
    }
903
    FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
904
    /* Reset: autoclear */
905
    if (value & FD_DSR_SWRESET) {
906
        fdctrl->dor &= ~FD_DOR_nRESET;
907
        fdctrl_reset(fdctrl, 1);
908
        fdctrl->dor |= FD_DOR_nRESET;
909
    }
910
    if (value & FD_DSR_PWRDOWN) {
911
        fdctrl_reset(fdctrl, 1);
912
    }
913
    fdctrl->dsr = value;
914
}
915

    
916
static int fdctrl_media_changed(FDrive *drv)
917
{
918
    int ret;
919

    
920
    if (!drv->bs)
921
        return 0;
922
    ret = bdrv_media_changed(drv->bs);
923
    if (ret) {
924
        fd_revalidate(drv);
925
    }
926
    return ret;
927
}
928

    
929
/* Digital input register : 0x07 (read-only) */
930
static uint32_t fdctrl_read_dir(FDCtrl *fdctrl)
931
{
932
    uint32_t retval = 0;
933

    
934
    if (fdctrl_media_changed(drv0(fdctrl))
935
     || fdctrl_media_changed(drv1(fdctrl))
936
#if MAX_FD == 4
937
     || fdctrl_media_changed(drv2(fdctrl))
938
     || fdctrl_media_changed(drv3(fdctrl))
939
#endif
940
        )
941
        retval |= FD_DIR_DSKCHG;
942
    if (retval != 0) {
943
        FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
944
    }
945

    
946
    return retval;
947
}
948

    
949
/* FIFO state control */
950
static void fdctrl_reset_fifo(FDCtrl *fdctrl)
951
{
952
    fdctrl->data_dir = FD_DIR_WRITE;
953
    fdctrl->data_pos = 0;
954
    fdctrl->msr &= ~(FD_MSR_CMDBUSY | FD_MSR_DIO);
955
}
956

    
957
/* Set FIFO status for the host to read */
958
static void fdctrl_set_fifo(FDCtrl *fdctrl, int fifo_len, int do_irq)
959
{
960
    fdctrl->data_dir = FD_DIR_READ;
961
    fdctrl->data_len = fifo_len;
962
    fdctrl->data_pos = 0;
963
    fdctrl->msr |= FD_MSR_CMDBUSY | FD_MSR_RQM | FD_MSR_DIO;
964
    if (do_irq)
965
        fdctrl_raise_irq(fdctrl, 0x00);
966
}
967

    
968
/* Set an error: unimplemented/unknown command */
969
static void fdctrl_unimplemented(FDCtrl *fdctrl, int direction)
970
{
971
    FLOPPY_ERROR("unimplemented command 0x%02x\n", fdctrl->fifo[0]);
972
    fdctrl->fifo[0] = FD_SR0_INVCMD;
973
    fdctrl_set_fifo(fdctrl, 1, 0);
974
}
975

    
976
/* Seek to next sector */
977
static int fdctrl_seek_to_next_sect(FDCtrl *fdctrl, FDrive *cur_drv)
978
{
979
    FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d)\n",
980
                   cur_drv->head, cur_drv->track, cur_drv->sect,
981
                   fd_sector(cur_drv));
982
    /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
983
       error in fact */
984
    if (cur_drv->sect >= cur_drv->last_sect ||
985
        cur_drv->sect == fdctrl->eot) {
986
        cur_drv->sect = 1;
987
        if (FD_MULTI_TRACK(fdctrl->data_state)) {
988
            if (cur_drv->head == 0 &&
989
                (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
990
                cur_drv->head = 1;
991
            } else {
992
                cur_drv->head = 0;
993
                cur_drv->track++;
994
                if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
995
                    return 0;
996
            }
997
        } else {
998
            cur_drv->track++;
999
            return 0;
1000
        }
1001
        FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
1002
                       cur_drv->head, cur_drv->track,
1003
                       cur_drv->sect, fd_sector(cur_drv));
1004
    } else {
1005
        cur_drv->sect++;
1006
    }
1007
    return 1;
1008
}
1009

    
1010
/* Callback for transfer end (stop or abort) */
1011
static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
1012
                                 uint8_t status1, uint8_t status2)
1013
{
1014
    FDrive *cur_drv;
1015

    
1016
    cur_drv = get_cur_drv(fdctrl);
1017
    FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
1018
                   status0, status1, status2,
1019
                   status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl));
1020
    fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
1021
    fdctrl->fifo[1] = status1;
1022
    fdctrl->fifo[2] = status2;
1023
    fdctrl->fifo[3] = cur_drv->track;
1024
    fdctrl->fifo[4] = cur_drv->head;
1025
    fdctrl->fifo[5] = cur_drv->sect;
1026
    fdctrl->fifo[6] = FD_SECTOR_SC;
1027
    fdctrl->data_dir = FD_DIR_READ;
1028
    if (!(fdctrl->msr & FD_MSR_NONDMA)) {
1029
        DMA_release_DREQ(fdctrl->dma_chann);
1030
    }
1031
    fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
1032
    fdctrl->msr &= ~FD_MSR_NONDMA;
1033
    fdctrl_set_fifo(fdctrl, 7, 1);
1034
}
1035

    
1036
/* Prepare a data transfer (either DMA or FIFO) */
1037
static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
1038
{
1039
    FDrive *cur_drv;
1040
    uint8_t kh, kt, ks;
1041
    int did_seek = 0;
1042

    
1043
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1044
    cur_drv = get_cur_drv(fdctrl);
1045
    kt = fdctrl->fifo[2];
1046
    kh = fdctrl->fifo[3];
1047
    ks = fdctrl->fifo[4];
1048
    FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
1049
                   GET_CUR_DRV(fdctrl), kh, kt, ks,
1050
                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect));
1051
    switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
1052
    case 2:
1053
        /* sect too big */
1054
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1055
        fdctrl->fifo[3] = kt;
1056
        fdctrl->fifo[4] = kh;
1057
        fdctrl->fifo[5] = ks;
1058
        return;
1059
    case 3:
1060
        /* track too big */
1061
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
1062
        fdctrl->fifo[3] = kt;
1063
        fdctrl->fifo[4] = kh;
1064
        fdctrl->fifo[5] = ks;
1065
        return;
1066
    case 4:
1067
        /* No seek enabled */
1068
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1069
        fdctrl->fifo[3] = kt;
1070
        fdctrl->fifo[4] = kh;
1071
        fdctrl->fifo[5] = ks;
1072
        return;
1073
    case 1:
1074
        did_seek = 1;
1075
        break;
1076
    default:
1077
        break;
1078
    }
1079

    
1080
    /* Set the FIFO state */
1081
    fdctrl->data_dir = direction;
1082
    fdctrl->data_pos = 0;
1083
    fdctrl->msr |= FD_MSR_CMDBUSY;
1084
    if (fdctrl->fifo[0] & 0x80)
1085
        fdctrl->data_state |= FD_STATE_MULTI;
1086
    else
1087
        fdctrl->data_state &= ~FD_STATE_MULTI;
1088
    if (did_seek)
1089
        fdctrl->data_state |= FD_STATE_SEEK;
1090
    else
1091
        fdctrl->data_state &= ~FD_STATE_SEEK;
1092
    if (fdctrl->fifo[5] == 00) {
1093
        fdctrl->data_len = fdctrl->fifo[8];
1094
    } else {
1095
        int tmp;
1096
        fdctrl->data_len = 128 << (fdctrl->fifo[5] > 7 ? 7 : fdctrl->fifo[5]);
1097
        tmp = (fdctrl->fifo[6] - ks + 1);
1098
        if (fdctrl->fifo[0] & 0x80)
1099
            tmp += fdctrl->fifo[6];
1100
        fdctrl->data_len *= tmp;
1101
    }
1102
    fdctrl->eot = fdctrl->fifo[6];
1103
    if (fdctrl->dor & FD_DOR_DMAEN) {
1104
        int dma_mode;
1105
        /* DMA transfer are enabled. Check if DMA channel is well programmed */
1106
        dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
1107
        dma_mode = (dma_mode >> 2) & 3;
1108
        FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
1109
                       dma_mode, direction,
1110
                       (128 << fdctrl->fifo[5]) *
1111
                       (cur_drv->last_sect - ks + 1), fdctrl->data_len);
1112
        if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
1113
              direction == FD_DIR_SCANH) && dma_mode == 0) ||
1114
            (direction == FD_DIR_WRITE && dma_mode == 2) ||
1115
            (direction == FD_DIR_READ && dma_mode == 1)) {
1116
            /* No access is allowed until DMA transfer has completed */
1117
            fdctrl->msr &= ~FD_MSR_RQM;
1118
            /* Now, we just have to wait for the DMA controller to
1119
             * recall us...
1120
             */
1121
            DMA_hold_DREQ(fdctrl->dma_chann);
1122
            DMA_schedule(fdctrl->dma_chann);
1123
            return;
1124
        } else {
1125
            FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
1126
        }
1127
    }
1128
    FLOPPY_DPRINTF("start non-DMA transfer\n");
1129
    fdctrl->msr |= FD_MSR_NONDMA;
1130
    if (direction != FD_DIR_WRITE)
1131
        fdctrl->msr |= FD_MSR_DIO;
1132
    /* IO based transfer: calculate len */
1133
    fdctrl_raise_irq(fdctrl, 0x00);
1134

    
1135
    return;
1136
}
1137

    
1138
/* Prepare a transfer of deleted data */
1139
static void fdctrl_start_transfer_del(FDCtrl *fdctrl, int direction)
1140
{
1141
    FLOPPY_ERROR("fdctrl_start_transfer_del() unimplemented\n");
1142

    
1143
    /* We don't handle deleted data,
1144
     * so we don't return *ANYTHING*
1145
     */
1146
    fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1147
}
1148

    
1149
/* handlers for DMA transfers */
1150
static int fdctrl_transfer_handler (void *opaque, int nchan,
1151
                                    int dma_pos, int dma_len)
1152
{
1153
    FDCtrl *fdctrl;
1154
    FDrive *cur_drv;
1155
    int len, start_pos, rel_pos;
1156
    uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
1157

    
1158
    fdctrl = opaque;
1159
    if (fdctrl->msr & FD_MSR_RQM) {
1160
        FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
1161
        return 0;
1162
    }
1163
    cur_drv = get_cur_drv(fdctrl);
1164
    if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
1165
        fdctrl->data_dir == FD_DIR_SCANH)
1166
        status2 = FD_SR2_SNS;
1167
    if (dma_len > fdctrl->data_len)
1168
        dma_len = fdctrl->data_len;
1169
    if (cur_drv->bs == NULL) {
1170
        if (fdctrl->data_dir == FD_DIR_WRITE)
1171
            fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1172
        else
1173
            fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1174
        len = 0;
1175
        goto transfer_error;
1176
    }
1177
    rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
1178
    for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
1179
        len = dma_len - fdctrl->data_pos;
1180
        if (len + rel_pos > FD_SECTOR_LEN)
1181
            len = FD_SECTOR_LEN - rel_pos;
1182
        FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x "
1183
                       "(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos,
1184
                       fdctrl->data_len, GET_CUR_DRV(fdctrl), cur_drv->head,
1185
                       cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
1186
                       fd_sector(cur_drv) * FD_SECTOR_LEN);
1187
        if (fdctrl->data_dir != FD_DIR_WRITE ||
1188
            len < FD_SECTOR_LEN || rel_pos != 0) {
1189
            /* READ & SCAN commands and realign to a sector for WRITE */
1190
            if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
1191
                          fdctrl->fifo, 1) < 0) {
1192
                FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
1193
                               fd_sector(cur_drv));
1194
                /* Sure, image size is too small... */
1195
                memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1196
            }
1197
        }
1198
        switch (fdctrl->data_dir) {
1199
        case FD_DIR_READ:
1200
            /* READ commands */
1201
            DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
1202
                              fdctrl->data_pos, len);
1203
            break;
1204
        case FD_DIR_WRITE:
1205
            /* WRITE commands */
1206
            DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
1207
                             fdctrl->data_pos, len);
1208
            if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
1209
                           fdctrl->fifo, 1) < 0) {
1210
                FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv));
1211
                fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1212
                goto transfer_error;
1213
            }
1214
            break;
1215
        default:
1216
            /* SCAN commands */
1217
            {
1218
                uint8_t tmpbuf[FD_SECTOR_LEN];
1219
                int ret;
1220
                DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
1221
                ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
1222
                if (ret == 0) {
1223
                    status2 = FD_SR2_SEH;
1224
                    goto end_transfer;
1225
                }
1226
                if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||
1227
                    (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {
1228
                    status2 = 0x00;
1229
                    goto end_transfer;
1230
                }
1231
            }
1232
            break;
1233
        }
1234
        fdctrl->data_pos += len;
1235
        rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
1236
        if (rel_pos == 0) {
1237
            /* Seek to next sector */
1238
            if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv))
1239
                break;
1240
        }
1241
    }
1242
 end_transfer:
1243
    len = fdctrl->data_pos - start_pos;
1244
    FLOPPY_DPRINTF("end transfer %d %d %d\n",
1245
                   fdctrl->data_pos, len, fdctrl->data_len);
1246
    if (fdctrl->data_dir == FD_DIR_SCANE ||
1247
        fdctrl->data_dir == FD_DIR_SCANL ||
1248
        fdctrl->data_dir == FD_DIR_SCANH)
1249
        status2 = FD_SR2_SEH;
1250
    if (FD_DID_SEEK(fdctrl->data_state))
1251
        status0 |= FD_SR0_SEEK;
1252
    fdctrl->data_len -= len;
1253
    fdctrl_stop_transfer(fdctrl, status0, status1, status2);
1254
 transfer_error:
1255

    
1256
    return len;
1257
}
1258

    
1259
/* Data register : 0x05 */
1260
static uint32_t fdctrl_read_data(FDCtrl *fdctrl)
1261
{
1262
    FDrive *cur_drv;
1263
    uint32_t retval = 0;
1264
    int pos;
1265

    
1266
    cur_drv = get_cur_drv(fdctrl);
1267
    fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1268
    if (!(fdctrl->msr & FD_MSR_RQM) || !(fdctrl->msr & FD_MSR_DIO)) {
1269
        FLOPPY_ERROR("controller not ready for reading\n");
1270
        return 0;
1271
    }
1272
    pos = fdctrl->data_pos;
1273
    if (fdctrl->msr & FD_MSR_NONDMA) {
1274
        pos %= FD_SECTOR_LEN;
1275
        if (pos == 0) {
1276
            if (fdctrl->data_pos != 0)
1277
                if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
1278
                    FLOPPY_DPRINTF("error seeking to next sector %d\n",
1279
                                   fd_sector(cur_drv));
1280
                    return 0;
1281
                }
1282
            if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
1283
                FLOPPY_DPRINTF("error getting sector %d\n",
1284
                               fd_sector(cur_drv));
1285
                /* Sure, image size is too small... */
1286
                memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1287
            }
1288
        }
1289
    }
1290
    retval = fdctrl->fifo[pos];
1291
    if (++fdctrl->data_pos == fdctrl->data_len) {
1292
        fdctrl->data_pos = 0;
1293
        /* Switch from transfer mode to status mode
1294
         * then from status mode to command mode
1295
         */
1296
        if (fdctrl->msr & FD_MSR_NONDMA) {
1297
            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
1298
        } else {
1299
            fdctrl_reset_fifo(fdctrl);
1300
            fdctrl_reset_irq(fdctrl);
1301
        }
1302
    }
1303
    FLOPPY_DPRINTF("data register: 0x%02x\n", retval);
1304

    
1305
    return retval;
1306
}
1307

    
1308
static void fdctrl_format_sector(FDCtrl *fdctrl)
1309
{
1310
    FDrive *cur_drv;
1311
    uint8_t kh, kt, ks;
1312

    
1313
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1314
    cur_drv = get_cur_drv(fdctrl);
1315
    kt = fdctrl->fifo[6];
1316
    kh = fdctrl->fifo[7];
1317
    ks = fdctrl->fifo[8];
1318
    FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
1319
                   GET_CUR_DRV(fdctrl), kh, kt, ks,
1320
                   fd_sector_calc(kh, kt, ks, cur_drv->last_sect));
1321
    switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & FD_CONFIG_EIS)) {
1322
    case 2:
1323
        /* sect too big */
1324
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1325
        fdctrl->fifo[3] = kt;
1326
        fdctrl->fifo[4] = kh;
1327
        fdctrl->fifo[5] = ks;
1328
        return;
1329
    case 3:
1330
        /* track too big */
1331
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, FD_SR1_EC, 0x00);
1332
        fdctrl->fifo[3] = kt;
1333
        fdctrl->fifo[4] = kh;
1334
        fdctrl->fifo[5] = ks;
1335
        return;
1336
    case 4:
1337
        /* No seek enabled */
1338
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM, 0x00, 0x00);
1339
        fdctrl->fifo[3] = kt;
1340
        fdctrl->fifo[4] = kh;
1341
        fdctrl->fifo[5] = ks;
1342
        return;
1343
    case 1:
1344
        fdctrl->data_state |= FD_STATE_SEEK;
1345
        break;
1346
    default:
1347
        break;
1348
    }
1349
    memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
1350
    if (cur_drv->bs == NULL ||
1351
        bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
1352
        FLOPPY_ERROR("formatting sector %d\n", fd_sector(cur_drv));
1353
        fdctrl_stop_transfer(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK, 0x00, 0x00);
1354
    } else {
1355
        if (cur_drv->sect == cur_drv->last_sect) {
1356
            fdctrl->data_state &= ~FD_STATE_FORMAT;
1357
            /* Last sector done */
1358
            if (FD_DID_SEEK(fdctrl->data_state))
1359
                fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
1360
            else
1361
                fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1362
        } else {
1363
            /* More to do */
1364
            fdctrl->data_pos = 0;
1365
            fdctrl->data_len = 4;
1366
        }
1367
    }
1368
}
1369

    
1370
static void fdctrl_handle_lock(FDCtrl *fdctrl, int direction)
1371
{
1372
    fdctrl->lock = (fdctrl->fifo[0] & 0x80) ? 1 : 0;
1373
    fdctrl->fifo[0] = fdctrl->lock << 4;
1374
    fdctrl_set_fifo(fdctrl, 1, fdctrl->lock);
1375
}
1376

    
1377
static void fdctrl_handle_dumpreg(FDCtrl *fdctrl, int direction)
1378
{
1379
    FDrive *cur_drv = get_cur_drv(fdctrl);
1380

    
1381
    /* Drives position */
1382
    fdctrl->fifo[0] = drv0(fdctrl)->track;
1383
    fdctrl->fifo[1] = drv1(fdctrl)->track;
1384
#if MAX_FD == 4
1385
    fdctrl->fifo[2] = drv2(fdctrl)->track;
1386
    fdctrl->fifo[3] = drv3(fdctrl)->track;
1387
#else
1388
    fdctrl->fifo[2] = 0;
1389
    fdctrl->fifo[3] = 0;
1390
#endif
1391
    /* timers */
1392
    fdctrl->fifo[4] = fdctrl->timer0;
1393
    fdctrl->fifo[5] = (fdctrl->timer1 << 1) | (fdctrl->dor & FD_DOR_DMAEN ? 1 : 0);
1394
    fdctrl->fifo[6] = cur_drv->last_sect;
1395
    fdctrl->fifo[7] = (fdctrl->lock << 7) |
1396
        (cur_drv->perpendicular << 2);
1397
    fdctrl->fifo[8] = fdctrl->config;
1398
    fdctrl->fifo[9] = fdctrl->precomp_trk;
1399
    fdctrl_set_fifo(fdctrl, 10, 0);
1400
}
1401

    
1402
static void fdctrl_handle_version(FDCtrl *fdctrl, int direction)
1403
{
1404
    /* Controller's version */
1405
    fdctrl->fifo[0] = fdctrl->version;
1406
    fdctrl_set_fifo(fdctrl, 1, 1);
1407
}
1408

    
1409
static void fdctrl_handle_partid(FDCtrl *fdctrl, int direction)
1410
{
1411
    fdctrl->fifo[0] = 0x41; /* Stepping 1 */
1412
    fdctrl_set_fifo(fdctrl, 1, 0);
1413
}
1414

    
1415
static void fdctrl_handle_restore(FDCtrl *fdctrl, int direction)
1416
{
1417
    FDrive *cur_drv = get_cur_drv(fdctrl);
1418

    
1419
    /* Drives position */
1420
    drv0(fdctrl)->track = fdctrl->fifo[3];
1421
    drv1(fdctrl)->track = fdctrl->fifo[4];
1422
#if MAX_FD == 4
1423
    drv2(fdctrl)->track = fdctrl->fifo[5];
1424
    drv3(fdctrl)->track = fdctrl->fifo[6];
1425
#endif
1426
    /* timers */
1427
    fdctrl->timer0 = fdctrl->fifo[7];
1428
    fdctrl->timer1 = fdctrl->fifo[8];
1429
    cur_drv->last_sect = fdctrl->fifo[9];
1430
    fdctrl->lock = fdctrl->fifo[10] >> 7;
1431
    cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
1432
    fdctrl->config = fdctrl->fifo[11];
1433
    fdctrl->precomp_trk = fdctrl->fifo[12];
1434
    fdctrl->pwrd = fdctrl->fifo[13];
1435
    fdctrl_reset_fifo(fdctrl);
1436
}
1437

    
1438
static void fdctrl_handle_save(FDCtrl *fdctrl, int direction)
1439
{
1440
    FDrive *cur_drv = get_cur_drv(fdctrl);
1441

    
1442
    fdctrl->fifo[0] = 0;
1443
    fdctrl->fifo[1] = 0;
1444
    /* Drives position */
1445
    fdctrl->fifo[2] = drv0(fdctrl)->track;
1446
    fdctrl->fifo[3] = drv1(fdctrl)->track;
1447
#if MAX_FD == 4
1448
    fdctrl->fifo[4] = drv2(fdctrl)->track;
1449
    fdctrl->fifo[5] = drv3(fdctrl)->track;
1450
#else
1451
    fdctrl->fifo[4] = 0;
1452
    fdctrl->fifo[5] = 0;
1453
#endif
1454
    /* timers */
1455
    fdctrl->fifo[6] = fdctrl->timer0;
1456
    fdctrl->fifo[7] = fdctrl->timer1;
1457
    fdctrl->fifo[8] = cur_drv->last_sect;
1458
    fdctrl->fifo[9] = (fdctrl->lock << 7) |
1459
        (cur_drv->perpendicular << 2);
1460
    fdctrl->fifo[10] = fdctrl->config;
1461
    fdctrl->fifo[11] = fdctrl->precomp_trk;
1462
    fdctrl->fifo[12] = fdctrl->pwrd;
1463
    fdctrl->fifo[13] = 0;
1464
    fdctrl->fifo[14] = 0;
1465
    fdctrl_set_fifo(fdctrl, 15, 1);
1466
}
1467

    
1468
static void fdctrl_handle_readid(FDCtrl *fdctrl, int direction)
1469
{
1470
    FDrive *cur_drv = get_cur_drv(fdctrl);
1471

    
1472
    /* XXX: should set main status register to busy */
1473
    cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
1474
    qemu_mod_timer(fdctrl->result_timer,
1475
                   qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() / 50));
1476
}
1477

    
1478
static void fdctrl_handle_format_track(FDCtrl *fdctrl, int direction)
1479
{
1480
    FDrive *cur_drv;
1481

    
1482
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1483
    cur_drv = get_cur_drv(fdctrl);
1484
    fdctrl->data_state |= FD_STATE_FORMAT;
1485
    if (fdctrl->fifo[0] & 0x80)
1486
        fdctrl->data_state |= FD_STATE_MULTI;
1487
    else
1488
        fdctrl->data_state &= ~FD_STATE_MULTI;
1489
    fdctrl->data_state &= ~FD_STATE_SEEK;
1490
    cur_drv->bps =
1491
        fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
1492
#if 0
1493
    cur_drv->last_sect =
1494
        cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
1495
        fdctrl->fifo[3] / 2;
1496
#else
1497
    cur_drv->last_sect = fdctrl->fifo[3];
1498
#endif
1499
    /* TODO: implement format using DMA expected by the Bochs BIOS
1500
     * and Linux fdformat (read 3 bytes per sector via DMA and fill
1501
     * the sector with the specified fill byte
1502
     */
1503
    fdctrl->data_state &= ~FD_STATE_FORMAT;
1504
    fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1505
}
1506

    
1507
static void fdctrl_handle_specify(FDCtrl *fdctrl, int direction)
1508
{
1509
    fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
1510
    fdctrl->timer1 = fdctrl->fifo[2] >> 1;
1511
    if (fdctrl->fifo[2] & 1)
1512
        fdctrl->dor &= ~FD_DOR_DMAEN;
1513
    else
1514
        fdctrl->dor |= FD_DOR_DMAEN;
1515
    /* No result back */
1516
    fdctrl_reset_fifo(fdctrl);
1517
}
1518

    
1519
static void fdctrl_handle_sense_drive_status(FDCtrl *fdctrl, int direction)
1520
{
1521
    FDrive *cur_drv;
1522

    
1523
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1524
    cur_drv = get_cur_drv(fdctrl);
1525
    cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
1526
    /* 1 Byte status back */
1527
    fdctrl->fifo[0] = (cur_drv->ro << 6) |
1528
        (cur_drv->track == 0 ? 0x10 : 0x00) |
1529
        (cur_drv->head << 2) |
1530
        GET_CUR_DRV(fdctrl) |
1531
        0x28;
1532
    fdctrl_set_fifo(fdctrl, 1, 0);
1533
}
1534

    
1535
static void fdctrl_handle_recalibrate(FDCtrl *fdctrl, int direction)
1536
{
1537
    FDrive *cur_drv;
1538

    
1539
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1540
    cur_drv = get_cur_drv(fdctrl);
1541
    fd_recalibrate(cur_drv);
1542
    fdctrl_reset_fifo(fdctrl);
1543
    /* Raise Interrupt */
1544
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
1545
}
1546

    
1547
static void fdctrl_handle_sense_interrupt_status(FDCtrl *fdctrl, int direction)
1548
{
1549
    FDrive *cur_drv = get_cur_drv(fdctrl);
1550

    
1551
    if(fdctrl->reset_sensei > 0) {
1552
        fdctrl->fifo[0] =
1553
            FD_SR0_RDYCHG + FD_RESET_SENSEI_COUNT - fdctrl->reset_sensei;
1554
        fdctrl->reset_sensei--;
1555
    } else {
1556
        /* XXX: status0 handling is broken for read/write
1557
           commands, so we do this hack. It should be suppressed
1558
           ASAP */
1559
        fdctrl->fifo[0] =
1560
            FD_SR0_SEEK | (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
1561
    }
1562

    
1563
    fdctrl->fifo[1] = cur_drv->track;
1564
    fdctrl_set_fifo(fdctrl, 2, 0);
1565
    fdctrl_reset_irq(fdctrl);
1566
    fdctrl->status0 = FD_SR0_RDYCHG;
1567
}
1568

    
1569
static void fdctrl_handle_seek(FDCtrl *fdctrl, int direction)
1570
{
1571
    FDrive *cur_drv;
1572

    
1573
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1574
    cur_drv = get_cur_drv(fdctrl);
1575
    fdctrl_reset_fifo(fdctrl);
1576
    if (fdctrl->fifo[2] > cur_drv->max_track) {
1577
        fdctrl_raise_irq(fdctrl, FD_SR0_ABNTERM | FD_SR0_SEEK);
1578
    } else {
1579
        cur_drv->track = fdctrl->fifo[2];
1580
        /* Raise Interrupt */
1581
        fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
1582
    }
1583
}
1584

    
1585
static void fdctrl_handle_perpendicular_mode(FDCtrl *fdctrl, int direction)
1586
{
1587
    FDrive *cur_drv = get_cur_drv(fdctrl);
1588

    
1589
    if (fdctrl->fifo[1] & 0x80)
1590
        cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
1591
    /* No result back */
1592
    fdctrl_reset_fifo(fdctrl);
1593
}
1594

    
1595
static void fdctrl_handle_configure(FDCtrl *fdctrl, int direction)
1596
{
1597
    fdctrl->config = fdctrl->fifo[2];
1598
    fdctrl->precomp_trk =  fdctrl->fifo[3];
1599
    /* No result back */
1600
    fdctrl_reset_fifo(fdctrl);
1601
}
1602

    
1603
static void fdctrl_handle_powerdown_mode(FDCtrl *fdctrl, int direction)
1604
{
1605
    fdctrl->pwrd = fdctrl->fifo[1];
1606
    fdctrl->fifo[0] = fdctrl->fifo[1];
1607
    fdctrl_set_fifo(fdctrl, 1, 1);
1608
}
1609

    
1610
static void fdctrl_handle_option(FDCtrl *fdctrl, int direction)
1611
{
1612
    /* No result back */
1613
    fdctrl_reset_fifo(fdctrl);
1614
}
1615

    
1616
static void fdctrl_handle_drive_specification_command(FDCtrl *fdctrl, int direction)
1617
{
1618
    FDrive *cur_drv = get_cur_drv(fdctrl);
1619

    
1620
    if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
1621
        /* Command parameters done */
1622
        if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
1623
            fdctrl->fifo[0] = fdctrl->fifo[1];
1624
            fdctrl->fifo[2] = 0;
1625
            fdctrl->fifo[3] = 0;
1626
            fdctrl_set_fifo(fdctrl, 4, 1);
1627
        } else {
1628
            fdctrl_reset_fifo(fdctrl);
1629
        }
1630
    } else if (fdctrl->data_len > 7) {
1631
        /* ERROR */
1632
        fdctrl->fifo[0] = 0x80 |
1633
            (cur_drv->head << 2) | GET_CUR_DRV(fdctrl);
1634
        fdctrl_set_fifo(fdctrl, 1, 1);
1635
    }
1636
}
1637

    
1638
static void fdctrl_handle_relative_seek_out(FDCtrl *fdctrl, int direction)
1639
{
1640
    FDrive *cur_drv;
1641

    
1642
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1643
    cur_drv = get_cur_drv(fdctrl);
1644
    if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
1645
        cur_drv->track = cur_drv->max_track - 1;
1646
    } else {
1647
        cur_drv->track += fdctrl->fifo[2];
1648
    }
1649
    fdctrl_reset_fifo(fdctrl);
1650
    /* Raise Interrupt */
1651
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
1652
}
1653

    
1654
static void fdctrl_handle_relative_seek_in(FDCtrl *fdctrl, int direction)
1655
{
1656
    FDrive *cur_drv;
1657

    
1658
    SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
1659
    cur_drv = get_cur_drv(fdctrl);
1660
    if (fdctrl->fifo[2] > cur_drv->track) {
1661
        cur_drv->track = 0;
1662
    } else {
1663
        cur_drv->track -= fdctrl->fifo[2];
1664
    }
1665
    fdctrl_reset_fifo(fdctrl);
1666
    /* Raise Interrupt */
1667
    fdctrl_raise_irq(fdctrl, FD_SR0_SEEK);
1668
}
1669

    
1670
static const struct {
1671
    uint8_t value;
1672
    uint8_t mask;
1673
    const char* name;
1674
    int parameters;
1675
    void (*handler)(FDCtrl *fdctrl, int direction);
1676
    int direction;
1677
} handlers[] = {
1678
    { FD_CMD_READ, 0x1f, "READ", 8, fdctrl_start_transfer, FD_DIR_READ },
1679
    { FD_CMD_WRITE, 0x3f, "WRITE", 8, fdctrl_start_transfer, FD_DIR_WRITE },
1680
    { FD_CMD_SEEK, 0xff, "SEEK", 2, fdctrl_handle_seek },
1681
    { FD_CMD_SENSE_INTERRUPT_STATUS, 0xff, "SENSE INTERRUPT STATUS", 0, fdctrl_handle_sense_interrupt_status },
1682
    { FD_CMD_RECALIBRATE, 0xff, "RECALIBRATE", 1, fdctrl_handle_recalibrate },
1683
    { FD_CMD_FORMAT_TRACK, 0xbf, "FORMAT TRACK", 5, fdctrl_handle_format_track },
1684
    { FD_CMD_READ_TRACK, 0xbf, "READ TRACK", 8, fdctrl_start_transfer, FD_DIR_READ },
1685
    { FD_CMD_RESTORE, 0xff, "RESTORE", 17, fdctrl_handle_restore }, /* part of READ DELETED DATA */
1686
    { FD_CMD_SAVE, 0xff, "SAVE", 0, fdctrl_handle_save }, /* part of READ DELETED DATA */
1687
    { FD_CMD_READ_DELETED, 0x1f, "READ DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_READ },
1688
    { FD_CMD_SCAN_EQUAL, 0x1f, "SCAN EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANE },
1689
    { FD_CMD_VERIFY, 0x1f, "VERIFY", 8, fdctrl_unimplemented },
1690
    { FD_CMD_SCAN_LOW_OR_EQUAL, 0x1f, "SCAN LOW OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANL },
1691
    { FD_CMD_SCAN_HIGH_OR_EQUAL, 0x1f, "SCAN HIGH OR EQUAL", 8, fdctrl_start_transfer, FD_DIR_SCANH },
1692
    { FD_CMD_WRITE_DELETED, 0x3f, "WRITE DELETED DATA", 8, fdctrl_start_transfer_del, FD_DIR_WRITE },
1693
    { FD_CMD_READ_ID, 0xbf, "READ ID", 1, fdctrl_handle_readid },
1694
    { FD_CMD_SPECIFY, 0xff, "SPECIFY", 2, fdctrl_handle_specify },
1695
    { FD_CMD_SENSE_DRIVE_STATUS, 0xff, "SENSE DRIVE STATUS", 1, fdctrl_handle_sense_drive_status },
1696
    { FD_CMD_PERPENDICULAR_MODE, 0xff, "PERPENDICULAR MODE", 1, fdctrl_handle_perpendicular_mode },
1697
    { FD_CMD_CONFIGURE, 0xff, "CONFIGURE", 3, fdctrl_handle_configure },
1698
    { FD_CMD_POWERDOWN_MODE, 0xff, "POWERDOWN MODE", 2, fdctrl_handle_powerdown_mode },
1699
    { FD_CMD_OPTION, 0xff, "OPTION", 1, fdctrl_handle_option },
1700
    { FD_CMD_DRIVE_SPECIFICATION_COMMAND, 0xff, "DRIVE SPECIFICATION COMMAND", 5, fdctrl_handle_drive_specification_command },
1701
    { FD_CMD_RELATIVE_SEEK_OUT, 0xff, "RELATIVE SEEK OUT", 2, fdctrl_handle_relative_seek_out },
1702
    { FD_CMD_FORMAT_AND_WRITE, 0xff, "FORMAT AND WRITE", 10, fdctrl_unimplemented },
1703
    { FD_CMD_RELATIVE_SEEK_IN, 0xff, "RELATIVE SEEK IN", 2, fdctrl_handle_relative_seek_in },
1704
    { FD_CMD_LOCK, 0x7f, "LOCK", 0, fdctrl_handle_lock },
1705
    { FD_CMD_DUMPREG, 0xff, "DUMPREG", 0, fdctrl_handle_dumpreg },
1706
    { FD_CMD_VERSION, 0xff, "VERSION", 0, fdctrl_handle_version },
1707
    { FD_CMD_PART_ID, 0xff, "PART ID", 0, fdctrl_handle_partid },
1708
    { FD_CMD_WRITE, 0x1f, "WRITE (BeOS)", 8, fdctrl_start_transfer, FD_DIR_WRITE }, /* not in specification ; BeOS 4.5 bug */
1709
    { 0, 0, "unknown", 0, fdctrl_unimplemented }, /* default handler */
1710
};
1711
/* Associate command to an index in the 'handlers' array */
1712
static uint8_t command_to_handler[256];
1713

    
1714
static void fdctrl_write_data(FDCtrl *fdctrl, uint32_t value)
1715
{
1716
    FDrive *cur_drv;
1717
    int pos;
1718

    
1719
    /* Reset mode */
1720
    if (!(fdctrl->dor & FD_DOR_nRESET)) {
1721
        FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
1722
        return;
1723
    }
1724
    if (!(fdctrl->msr & FD_MSR_RQM) || (fdctrl->msr & FD_MSR_DIO)) {
1725
        FLOPPY_ERROR("controller not ready for writing\n");
1726
        return;
1727
    }
1728
    fdctrl->dsr &= ~FD_DSR_PWRDOWN;
1729
    /* Is it write command time ? */
1730
    if (fdctrl->msr & FD_MSR_NONDMA) {
1731
        /* FIFO data write */
1732
        pos = fdctrl->data_pos++;
1733
        pos %= FD_SECTOR_LEN;
1734
        fdctrl->fifo[pos] = value;
1735
        if (pos == FD_SECTOR_LEN - 1 ||
1736
            fdctrl->data_pos == fdctrl->data_len) {
1737
            cur_drv = get_cur_drv(fdctrl);
1738
            if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
1739
                FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv));
1740
                return;
1741
            }
1742
            if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) {
1743
                FLOPPY_DPRINTF("error seeking to next sector %d\n",
1744
                               fd_sector(cur_drv));
1745
                return;
1746
            }
1747
        }
1748
        /* Switch from transfer mode to status mode
1749
         * then from status mode to command mode
1750
         */
1751
        if (fdctrl->data_pos == fdctrl->data_len)
1752
            fdctrl_stop_transfer(fdctrl, FD_SR0_SEEK, 0x00, 0x00);
1753
        return;
1754
    }
1755
    if (fdctrl->data_pos == 0) {
1756
        /* Command */
1757
        pos = command_to_handler[value & 0xff];
1758
        FLOPPY_DPRINTF("%s command\n", handlers[pos].name);
1759
        fdctrl->data_len = handlers[pos].parameters + 1;
1760
    }
1761

    
1762
    FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
1763
    fdctrl->fifo[fdctrl->data_pos++] = value;
1764
    if (fdctrl->data_pos == fdctrl->data_len) {
1765
        /* We now have all parameters
1766
         * and will be able to treat the command
1767
         */
1768
        if (fdctrl->data_state & FD_STATE_FORMAT) {
1769
            fdctrl_format_sector(fdctrl);
1770
            return;
1771
        }
1772

    
1773
        pos = command_to_handler[fdctrl->fifo[0] & 0xff];
1774
        FLOPPY_DPRINTF("treat %s command\n", handlers[pos].name);
1775
        (*handlers[pos].handler)(fdctrl, handlers[pos].direction);
1776
    }
1777
}
1778

    
1779
static void fdctrl_result_timer(void *opaque)
1780
{
1781
    FDCtrl *fdctrl = opaque;
1782
    FDrive *cur_drv = get_cur_drv(fdctrl);
1783

    
1784
    /* Pretend we are spinning.
1785
     * This is needed for Coherent, which uses READ ID to check for
1786
     * sector interleaving.
1787
     */
1788
    if (cur_drv->last_sect != 0) {
1789
        cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1;
1790
    }
1791
    fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
1792
}
1793

    
1794
/* Init functions */
1795
static int fdctrl_connect_drives(FDCtrl *fdctrl)
1796
{
1797
    unsigned int i;
1798
    FDrive *drive;
1799

    
1800
    for (i = 0; i < MAX_FD; i++) {
1801
        drive = &fdctrl->drives[i];
1802

    
1803
        if (drive->bs) {
1804
            if (bdrv_get_on_error(drive->bs, 0) != BLOCK_ERR_STOP_ENOSPC) {
1805
                error_report("fdc doesn't support drive option werror");
1806
                return -1;
1807
            }
1808
            if (bdrv_get_on_error(drive->bs, 1) != BLOCK_ERR_REPORT) {
1809
                error_report("fdc doesn't support drive option rerror");
1810
                return -1;
1811
            }
1812
        }
1813

    
1814
        fd_init(drive);
1815
        fd_revalidate(drive);
1816
        if (drive->bs) {
1817
            bdrv_set_removable(drive->bs, 1);
1818
        }
1819
    }
1820
    return 0;
1821
}
1822

    
1823
void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
1824
                        target_phys_addr_t mmio_base, DriveInfo **fds)
1825
{
1826
    FDCtrl *fdctrl;
1827
    DeviceState *dev;
1828
    FDCtrlSysBus *sys;
1829

    
1830
    dev = qdev_create(NULL, "sysbus-fdc");
1831
    sys = DO_UPCAST(FDCtrlSysBus, busdev.qdev, dev);
1832
    fdctrl = &sys->state;
1833
    fdctrl->dma_chann = dma_chann; /* FIXME */
1834
    if (fds[0]) {
1835
        qdev_prop_set_drive_nofail(dev, "driveA", fds[0]->bdrv);
1836
    }
1837
    if (fds[1]) {
1838
        qdev_prop_set_drive_nofail(dev, "driveB", fds[1]->bdrv);
1839
    }
1840
    qdev_init_nofail(dev);
1841
    sysbus_connect_irq(&sys->busdev, 0, irq);
1842
    sysbus_mmio_map(&sys->busdev, 0, mmio_base);
1843
}
1844

    
1845
void sun4m_fdctrl_init(qemu_irq irq, target_phys_addr_t io_base,
1846
                       DriveInfo **fds, qemu_irq *fdc_tc)
1847
{
1848
    DeviceState *dev;
1849
    FDCtrlSysBus *sys;
1850

    
1851
    dev = qdev_create(NULL, "SUNW,fdtwo");
1852
    if (fds[0]) {
1853
        qdev_prop_set_drive_nofail(dev, "drive", fds[0]->bdrv);
1854
    }
1855
    qdev_init_nofail(dev);
1856
    sys = DO_UPCAST(FDCtrlSysBus, busdev.qdev, dev);
1857
    sysbus_connect_irq(&sys->busdev, 0, irq);
1858
    sysbus_mmio_map(&sys->busdev, 0, io_base);
1859
    *fdc_tc = qdev_get_gpio_in(dev, 0);
1860
}
1861

    
1862
static int fdctrl_init_common(FDCtrl *fdctrl)
1863
{
1864
    int i, j;
1865
    static int command_tables_inited = 0;
1866

    
1867
    /* Fill 'command_to_handler' lookup table */
1868
    if (!command_tables_inited) {
1869
        command_tables_inited = 1;
1870
        for (i = ARRAY_SIZE(handlers) - 1; i >= 0; i--) {
1871
            for (j = 0; j < sizeof(command_to_handler); j++) {
1872
                if ((j & handlers[i].mask) == handlers[i].value) {
1873
                    command_to_handler[j] = i;
1874
                }
1875
            }
1876
        }
1877
    }
1878

    
1879
    FLOPPY_DPRINTF("init controller\n");
1880
    fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);
1881
    fdctrl->fifo_size = 512;
1882
    fdctrl->result_timer = qemu_new_timer_ns(vm_clock,
1883
                                          fdctrl_result_timer, fdctrl);
1884

    
1885
    fdctrl->version = 0x90; /* Intel 82078 controller */
1886
    fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
1887
    fdctrl->num_floppies = MAX_FD;
1888

    
1889
    if (fdctrl->dma_chann != -1)
1890
        DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl);
1891
    return fdctrl_connect_drives(fdctrl);
1892
}
1893

    
1894
static int isabus_fdc_init1(ISADevice *dev)
1895
{
1896
    FDCtrlISABus *isa = DO_UPCAST(FDCtrlISABus, busdev, dev);
1897
    FDCtrl *fdctrl = &isa->state;
1898
    int iobase = 0x3f0;
1899
    int isairq = 6;
1900
    int dma_chann = 2;
1901
    int ret;
1902

    
1903
    register_ioport_read(iobase + 0x01, 5, 1,
1904
                         &fdctrl_read_port, fdctrl);
1905
    register_ioport_read(iobase + 0x07, 1, 1,
1906
                         &fdctrl_read_port, fdctrl);
1907
    register_ioport_write(iobase + 0x01, 5, 1,
1908
                          &fdctrl_write_port, fdctrl);
1909
    register_ioport_write(iobase + 0x07, 1, 1,
1910
                          &fdctrl_write_port, fdctrl);
1911
    isa_init_ioport_range(dev, iobase, 6);
1912
    isa_init_ioport(dev, iobase + 7);
1913

    
1914
    isa_init_irq(&isa->busdev, &fdctrl->irq, isairq);
1915
    fdctrl->dma_chann = dma_chann;
1916

    
1917
    qdev_set_legacy_instance_id(&dev->qdev, iobase, 2);
1918
    ret = fdctrl_init_common(fdctrl);
1919

    
1920
    add_boot_device_path(isa->bootindexA, &dev->qdev, "/floppy@0");
1921
    add_boot_device_path(isa->bootindexB, &dev->qdev, "/floppy@1");
1922

    
1923
    return ret;
1924
}
1925

    
1926
static int sysbus_fdc_init1(SysBusDevice *dev)
1927
{
1928
    FDCtrlSysBus *sys = DO_UPCAST(FDCtrlSysBus, busdev, dev);
1929
    FDCtrl *fdctrl = &sys->state;
1930
    int io;
1931
    int ret;
1932

    
1933
    io = cpu_register_io_memory(fdctrl_mem_read, fdctrl_mem_write, fdctrl,
1934
                                DEVICE_NATIVE_ENDIAN);
1935
    sysbus_init_mmio(dev, 0x08, io);
1936
    sysbus_init_irq(dev, &fdctrl->irq);
1937
    qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
1938
    fdctrl->dma_chann = -1;
1939

    
1940
    qdev_set_legacy_instance_id(&dev->qdev, io, 2);
1941
    ret = fdctrl_init_common(fdctrl);
1942

    
1943
    return ret;
1944
}
1945

    
1946
static int sun4m_fdc_init1(SysBusDevice *dev)
1947
{
1948
    FDCtrl *fdctrl = &(FROM_SYSBUS(FDCtrlSysBus, dev)->state);
1949
    int io;
1950

    
1951
    io = cpu_register_io_memory(fdctrl_mem_read_strict,
1952
                                fdctrl_mem_write_strict, fdctrl,
1953
                                DEVICE_NATIVE_ENDIAN);
1954
    sysbus_init_mmio(dev, 0x08, io);
1955
    sysbus_init_irq(dev, &fdctrl->irq);
1956
    qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1);
1957

    
1958
    fdctrl->sun4m = 1;
1959
    qdev_set_legacy_instance_id(&dev->qdev, io, 2);
1960
    return fdctrl_init_common(fdctrl);
1961
}
1962

    
1963
static const VMStateDescription vmstate_isa_fdc ={
1964
    .name = "fdc",
1965
    .version_id = 2,
1966
    .minimum_version_id = 2,
1967
    .fields = (VMStateField []) {
1968
        VMSTATE_STRUCT(state, FDCtrlISABus, 0, vmstate_fdc, FDCtrl),
1969
        VMSTATE_END_OF_LIST()
1970
    }
1971
};
1972

    
1973
static ISADeviceInfo isa_fdc_info = {
1974
    .init = isabus_fdc_init1,
1975
    .qdev.name  = "isa-fdc",
1976
    .qdev.fw_name  = "fdc",
1977
    .qdev.size  = sizeof(FDCtrlISABus),
1978
    .qdev.no_user = 1,
1979
    .qdev.vmsd  = &vmstate_isa_fdc,
1980
    .qdev.reset = fdctrl_external_reset_isa,
1981
    .qdev.props = (Property[]) {
1982
        DEFINE_PROP_DRIVE("driveA", FDCtrlISABus, state.drives[0].bs),
1983
        DEFINE_PROP_DRIVE("driveB", FDCtrlISABus, state.drives[1].bs),
1984
        DEFINE_PROP_INT32("bootindexA", FDCtrlISABus, bootindexA, -1),
1985
        DEFINE_PROP_INT32("bootindexB", FDCtrlISABus, bootindexB, -1),
1986
        DEFINE_PROP_END_OF_LIST(),
1987
    },
1988
};
1989

    
1990
static const VMStateDescription vmstate_sysbus_fdc ={
1991
    .name = "fdc",
1992
    .version_id = 2,
1993
    .minimum_version_id = 2,
1994
    .fields = (VMStateField []) {
1995
        VMSTATE_STRUCT(state, FDCtrlSysBus, 0, vmstate_fdc, FDCtrl),
1996
        VMSTATE_END_OF_LIST()
1997
    }
1998
};
1999

    
2000
static SysBusDeviceInfo sysbus_fdc_info = {
2001
    .init = sysbus_fdc_init1,
2002
    .qdev.name  = "sysbus-fdc",
2003
    .qdev.size  = sizeof(FDCtrlSysBus),
2004
    .qdev.vmsd  = &vmstate_sysbus_fdc,
2005
    .qdev.reset = fdctrl_external_reset_sysbus,
2006
    .qdev.props = (Property[]) {
2007
        DEFINE_PROP_DRIVE("driveA", FDCtrlSysBus, state.drives[0].bs),
2008
        DEFINE_PROP_DRIVE("driveB", FDCtrlSysBus, state.drives[1].bs),
2009
        DEFINE_PROP_END_OF_LIST(),
2010
    },
2011
};
2012

    
2013
static SysBusDeviceInfo sun4m_fdc_info = {
2014
    .init = sun4m_fdc_init1,
2015
    .qdev.name  = "SUNW,fdtwo",
2016
    .qdev.size  = sizeof(FDCtrlSysBus),
2017
    .qdev.vmsd  = &vmstate_sysbus_fdc,
2018
    .qdev.reset = fdctrl_external_reset_sysbus,
2019
    .qdev.props = (Property[]) {
2020
        DEFINE_PROP_DRIVE("drive", FDCtrlSysBus, state.drives[0].bs),
2021
        DEFINE_PROP_END_OF_LIST(),
2022
    },
2023
};
2024

    
2025
static void fdc_register_devices(void)
2026
{
2027
    isa_qdev_register(&isa_fdc_info);
2028
    sysbus_register_withprop(&sysbus_fdc_info);
2029
    sysbus_register_withprop(&sun4m_fdc_info);
2030
}
2031

    
2032
device_init(fdc_register_devices)