Annotation of qemu/roms/seabios/src/floppy.c, revision 1.1.1.3

1.1       root        1: // 16bit code to access floppy drives.
                      2: //
                      3: // Copyright (C) 2008,2009  Kevin O'Connor <[email protected]>
                      4: // Copyright (C) 2002  MandrakeSoft S.A.
                      5: //
                      6: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      7: 
                      8: #include "types.h" // u8
                      9: #include "disk.h" // DISK_RET_SUCCESS
                     10: #include "config.h" // CONFIG_FLOPPY
                     11: #include "biosvar.h" // SET_BDA
                     12: #include "util.h" // wait_irq
                     13: #include "cmos.h" // inb_cmos
                     14: #include "pic.h" // eoi_pic1
                     15: #include "bregs.h" // struct bregs
                     16: 
                     17: #define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors
                     18: #define FLOPPY_DATALEN 0xff   // Not used - because size code is 0x02
                     19: #define FLOPPY_MOTOR_TICKS 37 // ~2 seconds
                     20: #define FLOPPY_FILLBYTE 0xf6
                     21: #define FLOPPY_GAPLEN 0x1B
                     22: #define FLOPPY_FORMAT_GAPLEN 0x6c
                     23: 
                     24: // New diskette parameter table adding 3 parameters from IBM
                     25: // Since no provisions are made for multiple drive types, most
                     26: // values in this table are ignored.  I set parameters for 1.44M
                     27: // floppy here
                     28: struct floppy_ext_dbt_s diskette_param_table2 VAR16VISIBLE = {
                     29:     .dbt = {
                     30:         .specify1       = 0xAF, // step rate 12ms, head unload 240ms
                     31:         .specify2       = 0x02, // head load time 4ms, DMA used
                     32:         .shutoff_ticks  = FLOPPY_MOTOR_TICKS, // ~2 seconds
                     33:         .bps_code       = FLOPPY_SIZE_CODE,
                     34:         .sectors        = 18,
                     35:         .interblock_len = FLOPPY_GAPLEN,
                     36:         .data_len       = FLOPPY_DATALEN,
                     37:         .gap_len        = FLOPPY_FORMAT_GAPLEN,
                     38:         .fill_byte      = FLOPPY_FILLBYTE,
                     39:         .settle_time    = 0x0F, // 15ms
                     40:         .startup_time   = 0x08, // 1 second
                     41:     },
                     42:     .max_track      = 79,   // maximum track
                     43:     .data_rate      = 0,    // data transfer rate
                     44:     .drive_type     = 4,    // drive type in cmos
                     45: };
                     46: 
                     47: // Since no provisions are made for multiple drive types, most
                     48: // values in this table are ignored.  I set parameters for 1.44M
                     49: // floppy here
                     50: struct floppy_dbt_s diskette_param_table VAR16FIXED(0xefc7) = {
                     51:     .specify1       = 0xAF,
                     52:     .specify2       = 0x02,
                     53:     .shutoff_ticks  = FLOPPY_MOTOR_TICKS,
                     54:     .bps_code       = FLOPPY_SIZE_CODE,
                     55:     .sectors        = 18,
                     56:     .interblock_len = FLOPPY_GAPLEN,
                     57:     .data_len       = FLOPPY_DATALEN,
                     58:     .gap_len        = FLOPPY_FORMAT_GAPLEN,
                     59:     .fill_byte      = FLOPPY_FILLBYTE,
                     60:     .settle_time    = 0x0F,
                     61:     .startup_time   = 0x08,
                     62: };
                     63: 
                     64: struct floppyinfo_s {
                     65:     struct chs_s chs;
                     66:     u8 config_data;
                     67:     u8 media_state;
                     68: };
                     69: 
                     70: struct floppyinfo_s FloppyInfo[] VAR16VISIBLE = {
                     71:     // Unknown
                     72:     { {0, 0, 0}, 0x00, 0x00},
                     73:     // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors
                     74:     { {2, 40, 9}, 0x00, 0x25},
                     75:     // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors
                     76:     { {2, 80, 15}, 0x00, 0x25},
                     77:     // 3 - 720KB, 3.5"  - 2 heads, 80 tracks, 9 sectors
                     78:     { {2, 80, 9}, 0x00, 0x17},
                     79:     // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors
                     80:     { {2, 80, 18}, 0x00, 0x17},
                     81:     // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors
                     82:     { {2, 80, 36}, 0xCC, 0xD7},
                     83:     // 6 - 160k, 5.25"  - 1 heads, 40 tracks, 8 sectors
                     84:     { {1, 40, 8}, 0x00, 0x27},
                     85:     // 7 - 180k, 5.25"  - 1 heads, 40 tracks, 9 sectors
                     86:     { {1, 40, 9}, 0x00, 0x27},
                     87:     // 8 - 320k, 5.25"  - 2 heads, 40 tracks, 8 sectors
                     88:     { {2, 40, 8}, 0x00, 0x27},
                     89: };
                     90: 
                     91: struct drive_s *
                     92: addFloppy(int floppyid, int ftype, int driver)
                     93: {
                     94:     if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) {
                     95:         dprintf(1, "Bad floppy type %d\n", ftype);
                     96:         return NULL;
                     97:     }
                     98: 
1.1.1.3 ! root       99:     char *desc = malloc_tmp(MAXDESCSIZE);
        !           100:     struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
        !           101:     if (!drive_g || !desc) {
        !           102:         warn_noalloc();
        !           103:         free(desc);
        !           104:         free(drive_g);
1.1       root      105:         return NULL;
1.1.1.3 ! root      106:     }
        !           107:     memset(drive_g, 0, sizeof(*drive_g));
1.1       root      108:     drive_g->cntl_id = floppyid;
                    109:     drive_g->type = driver;
                    110:     drive_g->blksize = DISK_SECTOR_SIZE;
                    111:     drive_g->floppy_type = ftype;
                    112:     drive_g->sectors = (u64)-1;
1.1.1.3 ! root      113:     drive_g->desc = desc;
        !           114:     snprintf(desc, MAXDESCSIZE, "drive %c", 'A' + floppyid);
1.1       root      115: 
                    116:     memcpy(&drive_g->lchs, &FloppyInfo[ftype].chs
                    117:            , sizeof(FloppyInfo[ftype].chs));
                    118: 
                    119:     map_floppy_drive(drive_g);
                    120:     return drive_g;
                    121: }
                    122: 
                    123: void
1.1.1.2   root      124: floppy_setup(void)
1.1       root      125: {
                    126:     if (! CONFIG_FLOPPY)
                    127:         return;
                    128:     dprintf(3, "init floppy drives\n");
                    129: 
                    130:     if (CONFIG_COREBOOT) {
                    131:         // XXX - disable floppies on coreboot for now.
                    132:     } else {
                    133:         u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE);
                    134:         if (type & 0xf0)
                    135:             addFloppy(0, type >> 4, DTYPE_FLOPPY);
                    136:         if (type & 0x0f)
                    137:             addFloppy(1, type & 0x0f, DTYPE_FLOPPY);
                    138:     }
                    139: 
                    140:     outb(0x02, PORT_DMA1_MASK_REG);
                    141: 
                    142:     enable_hwirq(6, entry_0e);
                    143: }
                    144: 
                    145: // Find a floppy type that matches a given image size.
                    146: int
                    147: find_floppy_type(u32 size)
                    148: {
                    149:     int i;
                    150:     for (i=1; i<ARRAY_SIZE(FloppyInfo); i++) {
                    151:         struct chs_s *c = &FloppyInfo[i].chs;
                    152:         if (c->cylinders * c->heads * c->spt * DISK_SECTOR_SIZE == size)
                    153:             return i;
                    154:     }
                    155:     return -1;
                    156: }
                    157: 
                    158: 
                    159: /****************************************************************
                    160:  * Low-level floppy IO
                    161:  ****************************************************************/
                    162: 
                    163: static void
1.1.1.2   root      164: floppy_reset_controller(void)
1.1       root      165: {
                    166:     // Reset controller
                    167:     u8 val8 = inb(PORT_FD_DOR);
                    168:     outb(val8 & ~0x04, PORT_FD_DOR);
                    169:     outb(val8 | 0x04, PORT_FD_DOR);
                    170: 
                    171:     // Wait for controller to come out of reset
                    172:     while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80)
                    173:         ;
                    174: }
                    175: 
                    176: static int
1.1.1.2   root      177: wait_floppy_irq(void)
1.1       root      178: {
                    179:     ASSERT16();
                    180:     u8 v;
                    181:     for (;;) {
                    182:         if (!GET_BDA(floppy_motor_counter))
                    183:             return -1;
                    184:         v = GET_BDA(floppy_recalibration_status);
                    185:         if (v & FRS_TIMEOUT)
                    186:             break;
1.1.1.3 ! root      187:         // Could use wait_irq() here, but that causes issues on
        !           188:         // bochs, so use yield() instead.
        !           189:         yield();
1.1       root      190:     }
                    191: 
                    192:     v &= ~FRS_TIMEOUT;
                    193:     SET_BDA(floppy_recalibration_status, v);
                    194:     return 0;
                    195: }
                    196: 
                    197: static void
                    198: floppy_prepare_controller(u8 floppyid)
                    199: {
                    200:     CLEARBITS_BDA(floppy_recalibration_status, FRS_TIMEOUT);
                    201: 
                    202:     // turn on motor of selected drive, DMA & int enabled, normal operation
                    203:     u8 prev_reset = inb(PORT_FD_DOR) & 0x04;
                    204:     u8 dor = 0x10;
                    205:     if (floppyid)
                    206:         dor = 0x20;
                    207:     dor |= 0x0c;
                    208:     dor |= floppyid;
                    209:     outb(dor, PORT_FD_DOR);
                    210: 
                    211:     // reset the disk motor timeout value of INT 08
                    212:     SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS);
                    213: 
                    214:     // wait for drive readiness
                    215:     while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80)
                    216:         ;
                    217: 
                    218:     if (!prev_reset)
                    219:         wait_floppy_irq();
                    220: }
                    221: 
                    222: static int
                    223: floppy_pio(u8 *cmd, u8 cmdlen)
                    224: {
                    225:     floppy_prepare_controller(cmd[1] & 1);
                    226: 
                    227:     // send command to controller
                    228:     u8 i;
                    229:     for (i=0; i<cmdlen; i++)
                    230:         outb(cmd[i], PORT_FD_DATA);
                    231: 
                    232:     int ret = wait_floppy_irq();
                    233:     if (ret) {
                    234:         floppy_reset_controller();
                    235:         return -1;
                    236:     }
                    237: 
                    238:     return 0;
                    239: }
                    240: 
                    241: static int
                    242: floppy_cmd(struct disk_op_s *op, u16 count, u8 *cmd, u8 cmdlen)
                    243: {
                    244:     // es:bx = pointer to where to place information from diskette
                    245:     u32 addr = (u32)op->buf_fl;
                    246: 
                    247:     // check for 64K boundary overrun
                    248:     u16 end = count - 1;
                    249:     u32 last_addr = addr + end;
                    250:     if ((addr >> 16) != (last_addr >> 16))
                    251:         return DISK_RET_EBOUNDARY;
                    252: 
                    253:     u8 mode_register = 0x4a; // single mode, increment, autoinit disable,
                    254:     if (cmd[0] == 0xe6)
                    255:         // read
                    256:         mode_register = 0x46;
                    257: 
                    258:     //DEBUGF("floppy dma c2\n");
                    259:     outb(0x06, PORT_DMA1_MASK_REG);
                    260:     outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
                    261:     outb(addr, PORT_DMA_ADDR_2);
                    262:     outb(addr>>8, PORT_DMA_ADDR_2);
                    263:     outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
                    264:     outb(end, PORT_DMA_CNT_2);
                    265:     outb(end>>8, PORT_DMA_CNT_2);
                    266: 
                    267:     // port 0b: DMA-1 Mode Register
                    268:     // transfer type=write, channel 2
                    269:     outb(mode_register, PORT_DMA1_MODE_REG);
                    270: 
                    271:     // port 81: DMA-1 Page Register, channel 2
                    272:     outb(addr>>16, PORT_DMA_PAGE_2);
                    273: 
                    274:     outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2
                    275: 
                    276:     int ret = floppy_pio(cmd, cmdlen);
                    277:     if (ret)
                    278:         return DISK_RET_ETIMEOUT;
                    279: 
                    280:     // check port 3f4 for accessibility to status bytes
                    281:     if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0)
                    282:         return DISK_RET_ECONTROLLER;
                    283: 
                    284:     // read 7 return status bytes from controller
                    285:     u8 i;
                    286:     for (i=0; i<7; i++) {
                    287:         u8 v = inb(PORT_FD_DATA);
                    288:         cmd[i] = v;
                    289:         SET_BDA(floppy_return_status[i], v);
                    290:     }
                    291: 
                    292:     return DISK_RET_SUCCESS;
                    293: }
                    294: 
                    295: 
                    296: /****************************************************************
                    297:  * Floppy media sense
                    298:  ****************************************************************/
                    299: 
                    300: static inline void
                    301: set_diskette_current_cyl(u8 floppyid, u8 cyl)
                    302: {
                    303:     SET_BDA(floppy_track[floppyid], cyl);
                    304: }
                    305: 
                    306: static void
                    307: floppy_drive_recal(u8 floppyid)
                    308: {
                    309:     // send Recalibrate command (2 bytes) to controller
                    310:     u8 data[12];
                    311:     data[0] = 0x07;  // 07: Recalibrate
                    312:     data[1] = floppyid; // 0=drive0, 1=drive1
                    313:     floppy_pio(data, 2);
                    314: 
                    315:     SETBITS_BDA(floppy_recalibration_status, 1<<floppyid);
                    316:     set_diskette_current_cyl(floppyid, 0);
                    317: }
                    318: 
                    319: static int
                    320: floppy_media_sense(struct drive_s *drive_g)
                    321: {
                    322:     // for now cheat and get drive type from CMOS,
                    323:     // assume media is same as drive type
                    324: 
                    325:     // ** config_data **
                    326:     // Bitfields for diskette media control:
                    327:     // Bit(s)  Description (Table M0028)
                    328:     //  7-6  last data rate set by controller
                    329:     //        00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
                    330:     //  5-4  last diskette drive step rate selected
                    331:     //        00=0Ch, 01=0Dh, 10=0Eh, 11=0Ah
                    332:     //  3-2  {data rate at start of operation}
                    333:     //  1-0  reserved
                    334: 
                    335:     // ** media_state **
                    336:     // Bitfields for diskette drive media state:
                    337:     // Bit(s)  Description (Table M0030)
                    338:     //  7-6  data rate
                    339:     //    00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
                    340:     //  5  double stepping required (e.g. 360kB in 1.2MB)
                    341:     //  4  media type established
                    342:     //  3  drive capable of supporting 4MB media
                    343:     //  2-0  on exit from BIOS, contains
                    344:     //    000 trying 360kB in 360kB
                    345:     //    001 trying 360kB in 1.2MB
                    346:     //    010 trying 1.2MB in 1.2MB
                    347:     //    011 360kB in 360kB established
                    348:     //    100 360kB in 1.2MB established
                    349:     //    101 1.2MB in 1.2MB established
                    350:     //    110 reserved
                    351:     //    111 all other formats/drives
                    352: 
                    353:     u8 ftype = GET_GLOBAL(drive_g->floppy_type);
                    354:     SET_BDA(floppy_last_data_rate, GET_GLOBAL(FloppyInfo[ftype].config_data));
                    355:     u8 floppyid = GET_GLOBAL(drive_g->cntl_id);
                    356:     SET_BDA(floppy_media_state[floppyid]
                    357:             , GET_GLOBAL(FloppyInfo[ftype].media_state));
                    358:     return DISK_RET_SUCCESS;
                    359: }
                    360: 
                    361: static int
                    362: check_recal_drive(struct drive_s *drive_g)
                    363: {
                    364:     u8 floppyid = GET_GLOBAL(drive_g->cntl_id);
                    365:     if ((GET_BDA(floppy_recalibration_status) & (1<<floppyid))
                    366:         && (GET_BDA(floppy_media_state[floppyid]) & FMS_MEDIA_DRIVE_ESTABLISHED))
                    367:         // Media is known.
                    368:         return DISK_RET_SUCCESS;
                    369: 
                    370:     // Recalibrate drive.
                    371:     floppy_drive_recal(floppyid);
                    372: 
                    373:     // Sense media.
                    374:     return floppy_media_sense(drive_g);
                    375: }
                    376: 
                    377: 
                    378: /****************************************************************
                    379:  * Floppy handlers
                    380:  ****************************************************************/
                    381: 
                    382: static void
                    383: lba2chs(struct disk_op_s *op, u8 *track, u8 *sector, u8 *head)
                    384: {
                    385:     u32 lba = op->lba;
                    386: 
                    387:     u32 tmp = lba + 1;
                    388:     u16 nlspt = GET_GLOBAL(op->drive_g->lchs.spt);
                    389:     *sector = tmp % nlspt;
                    390: 
                    391:     tmp /= nlspt;
                    392:     u16 nlh = GET_GLOBAL(op->drive_g->lchs.heads);
                    393:     *head = tmp % nlh;
                    394: 
                    395:     tmp /= nlh;
                    396:     *track = tmp;
                    397: }
                    398: 
                    399: // diskette controller reset
                    400: static int
                    401: floppy_reset(struct disk_op_s *op)
                    402: {
                    403:     u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
                    404:     set_diskette_current_cyl(floppyid, 0); // current cylinder
                    405:     return DISK_RET_SUCCESS;
                    406: }
                    407: 
                    408: // Read Diskette Sectors
                    409: static int
                    410: floppy_read(struct disk_op_s *op)
                    411: {
                    412:     int res = check_recal_drive(op->drive_g);
                    413:     if (res)
                    414:         goto fail;
                    415: 
                    416:     u8 track, sector, head;
                    417:     lba2chs(op, &track, &sector, &head);
                    418: 
                    419:     // send read-normal-data command (9 bytes) to controller
                    420:     u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
                    421:     u8 data[12];
                    422:     data[0] = 0xe6; // e6: read normal data
                    423:     data[1] = (head << 2) | floppyid; // HD DR1 DR2
                    424:     data[2] = track;
                    425:     data[3] = head;
                    426:     data[4] = sector;
                    427:     data[5] = FLOPPY_SIZE_CODE;
                    428:     data[6] = sector + op->count - 1; // last sector to read on track
                    429:     data[7] = FLOPPY_GAPLEN;
                    430:     data[8] = FLOPPY_DATALEN;
                    431: 
                    432:     res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9);
                    433:     if (res)
                    434:         goto fail;
                    435: 
                    436:     if (data[0] & 0xc0) {
                    437:         res = DISK_RET_ECONTROLLER;
                    438:         goto fail;
                    439:     }
                    440: 
                    441:     // ??? should track be new val from return_status[3] ?
                    442:     set_diskette_current_cyl(floppyid, track);
                    443:     return DISK_RET_SUCCESS;
                    444: fail:
                    445:     op->count = 0; // no sectors read
                    446:     return res;
                    447: }
                    448: 
                    449: // Write Diskette Sectors
                    450: static int
                    451: floppy_write(struct disk_op_s *op)
                    452: {
                    453:     int res = check_recal_drive(op->drive_g);
                    454:     if (res)
                    455:         goto fail;
                    456: 
                    457:     u8 track, sector, head;
                    458:     lba2chs(op, &track, &sector, &head);
                    459: 
                    460:     // send write-normal-data command (9 bytes) to controller
                    461:     u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
                    462:     u8 data[12];
                    463:     data[0] = 0xc5; // c5: write normal data
                    464:     data[1] = (head << 2) | floppyid; // HD DR1 DR2
                    465:     data[2] = track;
                    466:     data[3] = head;
                    467:     data[4] = sector;
                    468:     data[5] = FLOPPY_SIZE_CODE;
                    469:     data[6] = sector + op->count - 1; // last sector to write on track
                    470:     data[7] = FLOPPY_GAPLEN;
                    471:     data[8] = FLOPPY_DATALEN;
                    472: 
                    473:     res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9);
                    474:     if (res)
                    475:         goto fail;
                    476: 
                    477:     if (data[0] & 0xc0) {
                    478:         if (data[1] & 0x02)
                    479:             res = DISK_RET_EWRITEPROTECT;
                    480:         else
                    481:             res = DISK_RET_ECONTROLLER;
                    482:         goto fail;
                    483:     }
                    484: 
                    485:     // ??? should track be new val from return_status[3] ?
                    486:     set_diskette_current_cyl(floppyid, track);
                    487:     return DISK_RET_SUCCESS;
                    488: fail:
                    489:     op->count = 0; // no sectors read
                    490:     return res;
                    491: }
                    492: 
                    493: // Verify Diskette Sectors
                    494: static int
                    495: floppy_verify(struct disk_op_s *op)
                    496: {
                    497:     int res = check_recal_drive(op->drive_g);
                    498:     if (res)
                    499:         goto fail;
                    500: 
                    501:     u8 track, sector, head;
                    502:     lba2chs(op, &track, &sector, &head);
                    503: 
                    504:     // ??? should track be new val from return_status[3] ?
                    505:     u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
                    506:     set_diskette_current_cyl(floppyid, track);
                    507:     return DISK_RET_SUCCESS;
                    508: fail:
                    509:     op->count = 0; // no sectors read
                    510:     return res;
                    511: }
                    512: 
                    513: // format diskette track
                    514: static int
                    515: floppy_format(struct disk_op_s *op)
                    516: {
                    517:     int ret = check_recal_drive(op->drive_g);
                    518:     if (ret)
                    519:         return ret;
                    520: 
                    521:     u8 head = op->lba;
                    522: 
                    523:     // send format-track command (6 bytes) to controller
                    524:     u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
                    525:     u8 data[12];
                    526:     data[0] = 0x4d; // 4d: format track
                    527:     data[1] = (head << 2) | floppyid; // HD DR1 DR2
                    528:     data[2] = FLOPPY_SIZE_CODE;
                    529:     data[3] = op->count; // number of sectors per track
                    530:     data[4] = FLOPPY_FORMAT_GAPLEN;
                    531:     data[5] = FLOPPY_FILLBYTE;
                    532: 
                    533:     ret = floppy_cmd(op, op->count * 4, data, 6);
                    534:     if (ret)
                    535:         return ret;
                    536: 
                    537:     if (data[0] & 0xc0) {
                    538:         if (data[1] & 0x02)
                    539:             return DISK_RET_EWRITEPROTECT;
                    540:         return DISK_RET_ECONTROLLER;
                    541:     }
                    542: 
                    543:     set_diskette_current_cyl(floppyid, 0);
                    544:     return DISK_RET_SUCCESS;
                    545: }
                    546: 
                    547: int
                    548: process_floppy_op(struct disk_op_s *op)
                    549: {
                    550:     if (!CONFIG_FLOPPY)
                    551:         return 0;
                    552: 
                    553:     switch (op->command) {
                    554:     case CMD_RESET:
                    555:         return floppy_reset(op);
                    556:     case CMD_READ:
                    557:         return floppy_read(op);
                    558:     case CMD_WRITE:
                    559:         return floppy_write(op);
                    560:     case CMD_VERIFY:
                    561:         return floppy_verify(op);
                    562:     case CMD_FORMAT:
                    563:         return floppy_format(op);
                    564:     default:
                    565:         op->count = 0;
                    566:         return DISK_RET_EPARAM;
                    567:     }
                    568: }
                    569: 
                    570: 
                    571: /****************************************************************
                    572:  * HW irqs
                    573:  ****************************************************************/
                    574: 
                    575: // INT 0Eh Diskette Hardware ISR Entry Point
                    576: void VISIBLE16
1.1.1.2   root      577: handle_0e(void)
1.1       root      578: {
                    579:     debug_isr(DEBUG_ISR_0e);
                    580:     if (! CONFIG_FLOPPY)
                    581:         goto done;
                    582: 
                    583:     if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) {
                    584:         outb(0x08, PORT_FD_DATA); // sense interrupt status
                    585:         while ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0)
                    586:             ;
                    587:         do {
                    588:             inb(PORT_FD_DATA);
                    589:         } while ((inb(PORT_FD_STATUS) & 0xc0) == 0xc0);
                    590:     }
                    591:     // diskette interrupt has occurred
                    592:     SETBITS_BDA(floppy_recalibration_status, FRS_TIMEOUT);
                    593: 
                    594: done:
                    595:     eoi_pic1();
                    596: }
                    597: 
                    598: // Called from int08 handler.
                    599: void
1.1.1.2   root      600: floppy_tick(void)
1.1       root      601: {
                    602:     if (! CONFIG_FLOPPY)
                    603:         return;
                    604: 
                    605:     // time to turn off drive(s)?
                    606:     u8 fcount = GET_BDA(floppy_motor_counter);
                    607:     if (fcount) {
                    608:         fcount--;
                    609:         SET_BDA(floppy_motor_counter, fcount);
                    610:         if (fcount == 0)
                    611:             // turn motor(s) off
                    612:             outb(inb(PORT_FD_DOR) & 0xcf, PORT_FD_DOR);
                    613:     }
                    614: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.