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

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
        !           122: floppy_setup()
        !           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
        !           162: floppy_reset_controller()
        !           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
        !           175: wait_floppy_irq()
        !           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
        !           573: handle_0e()
        !           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
        !           596: floppy_tick()
        !           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.