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

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

unix.superglobalmegacorp.com

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