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

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

unix.superglobalmegacorp.com

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