VirtualBox

Changeset 54563 in vbox for trunk/src/VBox/Devices/PC


Ignore:
Timestamp:
Feb 27, 2015 5:38:36 PM (10 years ago)
Author:
vboxsync
Message:

BIOS: INT13h function 17h/18h support. Contributed by Dave Meagher.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS/floppy.c

    r53624 r54563  
    451451    uint8_t     drive, num_sectors, track, sector, head;
    452452    uint16_t    base_address, base_count, base_es;
    453     uint8_t     page, mode_register, val8;
     453    uint8_t     page, mode_register, val8, media_state;
    454454    uint8_t     return_status[7];
    455455    uint8_t     drive_type, num_floppies, ah;
     
    11111111    case 0x17: // set diskette type for format(old)
    11121112        BX_DEBUG_INT13_FL("floppy f17\n");
    1113         /* not used for 1.44M floppies */
    1114         SET_AH(0x01); // not supported
    1115         set_diskette_ret_status(1); /* not supported */
    1116         SET_CF();
     1113        // NOTE: 1.44M diskette not supported by this function, use INT14h/18h instead.
     1114        // Drive number (0 or 1) values allowed
     1115        drive = GET_ELDL();
     1116
     1117        // Format type (AL)
     1118        // 00 - NOT USED   
     1119        // 01 - DISKETTE 360K IN 360K DRIVE   
     1120        // 02 - DISKETTE 360K IN 1.2M DRIVE
     1121        // 03 - DISKETTE 1.2M IN 1.2M DRIVE
     1122        // 04 - DISKETTE 720K IN 720K DRIVE
     1123        val8 = GET_AL();
     1124
     1125        BX_DEBUG_INT13_FL("floppy f17 - drive: %d, format type: %d\n", drive, val8);
     1126
     1127        if (drive > 1) {
     1128            SET_AH(0x01); // invalid drive
     1129            set_diskette_ret_status(0x01); // bad parameter
     1130            SET_CF();
     1131            return;
     1132        }
     1133   
     1134        // see if drive exists
     1135        if (floppy_drive_exists(drive) == 0) {
     1136            SET_AH(0x80); // not responding/time out
     1137            set_diskette_ret_status(0x80);
     1138            SET_CF();
     1139            return;
     1140        }
     1141
     1142        // Get current drive state. Set 'base_address' to media status offset address
     1143        base_address = (drive) ? 0x0091 : 0x0090;
     1144        media_state = read_byte(0x0040, base_address);
     1145
     1146        // Mask out (clear) bits 4-7 (4:media type established, 5:double stepping, 6-7:data rate)
     1147        media_state &= 0x0f;
     1148
     1149        switch (val8) {
     1150        case 1:
     1151            // 360K media in 360K drive
     1152            media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
     1153            break;
     1154        case 2:
     1155            // 360K media in 1.2M drive
     1156            media_state |= 0x70; // 0111 0000 (media type established, double stepping, 300 kbps)
     1157            break;
     1158        case 3:
     1159            // 1.2M media in 1.2M drive
     1160            media_state |= 0x10; // 0001 0000 (media type established, 500 kbps)
     1161            break;
     1162        case 4:
     1163            // 720K media in 720K drive
     1164            media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
     1165            break;
     1166        default:
     1167            // bad parameter
     1168            SET_AH(0x01); // invalid format mode parameter
     1169            set_diskette_ret_status(0x01);
     1170            SET_CF();
     1171            return;
     1172        }
     1173
     1174        // Update media status
     1175        write_byte(0x0040, base_address, media_state);
     1176        BX_DEBUG_INT13_FL("floppy f17 - media status set to: %02x\n", media_state);
     1177
     1178        // return success!
     1179        SET_AH(0);
     1180        set_diskette_ret_status(0);
     1181        CLEAR_CF();
    11171182        return;
    11181183
    11191184    case 0x18: // set diskette type for format(new)
    11201185        BX_DEBUG_INT13_FL("floppy f18\n");
    1121         SET_AH(0x01); // do later
    1122         set_diskette_ret_status(1);
    1123         SET_CF();
     1186        // Set Media Type for Format. Verifies that the device supports a specific geometry.
     1187        // Unlike INT13h/17h, this service supports higher capacity drives (1.44M and 2.88M).
     1188        // Drive number (0 or 1) values allowed
     1189        drive = GET_ELDL();
     1190
     1191        val8 = GET_CL();
     1192        num_sectors = val8 & 0x3f;             // max sector number per cylinder
     1193        track = ((val8 >> 6) << 8) + GET_CH(); // max cylinder number (max cylinders - 1)
     1194
     1195        BX_DEBUG_INT13_FL("floppy f18 - drive: %d, max cylinder/track number: %d, sectors-per-tracks: %d\n",
     1196           drive, track, num_sectors);
     1197
     1198        if (drive > 1) {
     1199            SET_AH(0x01); // invalid drive
     1200            set_diskette_ret_status(0x01);
     1201            SET_CF();
     1202            return;
     1203        }
     1204
     1205        // see if drive exists
     1206        if (floppy_drive_exists(drive) == 0) {
     1207            SET_AH(0x80); // not responding/time out
     1208            set_diskette_ret_status(0x80);
     1209            SET_CF();
     1210            return;
     1211        }
     1212
     1213        // see if media in drive, and media type is known
     1214        if (floppy_media_known(drive) == 0) {
     1215            if (floppy_media_sense(drive) == 0) {
     1216                SET_AH(0x0C); // drive/media type unknown
     1217                set_diskette_ret_status(0x0C);
     1218                SET_CF();
     1219                return;
     1220            }
     1221        }
     1222
     1223        // @todo: break out drive type determination
     1224        drive_type = inb_cmos(0x10);
     1225        if (drive == 0)
     1226            drive_type >>= 4;
     1227        else
     1228            drive_type &= 0x0f;
     1229     
     1230        // Get current drive state. Set 'base_address' to media status offset address
     1231        base_address = (drive) ? 0x0091 : 0x0090;
     1232        media_state = read_byte(0x0040, base_address);
     1233
     1234        // Mask out (clear) bits 4-7 (4:media type established, 5:double stepping, 6-7:data rate)
     1235        media_state &= 0x0f;
     1236
     1237        switch (drive_type) {
     1238        case 1: // 360KB, 5.25"
     1239            if (track == 39 && num_sectors == 9)
     1240                media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
     1241
     1242            break;
     1243        case 2: // 1.2MB, 5.25"
     1244            if (track == 39 && num_sectors == 9) {          // 360K disk in 1.2M drive
     1245                media_state |= 0x70; // 0111 0000 (media type established, double stepping, 300 kbps)
     1246            } else if (track == 79 && num_sectors == 15) {  // 1.2M disk in 1.2M drive
     1247                media_state |= 0x10; // 0001 0000 (media type established, 500 kbps)
     1248            }
     1249            break;
     1250        case 3: // 720KB, 3.5"
     1251            if (track == 79 && num_sectors == 9)
     1252                media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
     1253
     1254                        break;
     1255        case 4: // 1.44MB, 3.5"
     1256            if (track == 79) {
     1257                if (num_sectors == 9) {          // 720K disk in 1.44M drive
     1258                    media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
     1259                } else if (num_sectors == 18) {  // 1.44M disk in 1.44M drive
     1260                    media_state |= 0x10; // 0001 0000 (media type established, 500 kbps)
     1261                }
     1262            }
     1263            break;
     1264        case 5: // 2.88MB, 3.5"
     1265            if (track == 79) {
     1266                if (num_sectors == 9) {          // 720K disk in 2.88M drive
     1267                    media_state |= 0x90; // 1001 0000 (media type established, 250 kbps)
     1268                } else if (num_sectors == 18) {  // 1.44M disk in 2.88M drive
     1269                    media_state |= 0x10; // 0001 0000 (media type established, 500 kbps)
     1270                } else if (num_sectors == 36) {  // 2.88M disk in 2.88M drive
     1271                    media_state |= 0xD0; // 1101 0000 (media type established, 1 Mbps)
     1272                }
     1273            }
     1274            break;
     1275        default:
     1276            break;
     1277        }
     1278
     1279        // Error if bit 4 (media type established) has not just been set above.
     1280        if (((media_state >> 4) & 0x01) == 0) {
     1281            // Error - assume requested tracks/sectors-per-track not supported
     1282            // for current drive type - or drive type is unknown!
     1283            SET_AH(0x0C);
     1284            set_diskette_ret_status(0x0C);
     1285            SET_CF();
     1286            return;
     1287        }
     1288
     1289        // Update media status
     1290        write_byte(0x0040, base_address, media_state);
     1291
     1292        // set es & di to point to 11 byte diskette param table in ROM
     1293        ES = 0xF000;    // @todo: any way to make this relocatable?
     1294        DI = get_floppy_dpt(drive_type);
     1295
     1296        // return success!
     1297        SET_AH(0);
     1298        set_diskette_ret_status(0);
     1299        CLEAR_CF();
    11241300        return;
    11251301
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette