blob: 655ee00ad09ffebc8f045f225c01b9182570b78c [file] [log] [blame]
Kevin O'Connor36c93a52009-09-12 19:35:04 -04001// Support for booting from cdroms (the "El Torito" spec).
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -05002//
Kevin O'Connorc892b132009-08-11 21:59:37 -04003// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -05004// Copyright (C) 2002 MandrakeSoft S.A.
5//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05006// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -05007
8#include "disk.h" // cdrom_13
9#include "util.h" // memset
Kevin O'Connor9521e262008-07-04 13:04:29 -040010#include "bregs.h" // struct bregs
11#include "biosvar.h" // GET_EBDA
Kevin O'Connorc892b132009-08-11 21:59:37 -040012#include "ata.h" // ATA_CMD_REQUEST_SENSE
Kevin O'Connor7d700252010-02-15 11:56:07 -050013#include "blockcmd.h" // CDB_CMD_REQUEST_SENSE
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -050014
15
16/****************************************************************
Kevin O'Connor51cfbe72009-08-18 22:38:49 -040017 * CD emulation
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -050018 ****************************************************************/
19
Kevin O'Connord5d02b62010-06-06 16:18:03 -040020struct drive_s *cdemu_drive_gf VAR16VISIBLE;
21u8 *cdemu_buf_fl VAR16VISIBLE;
22
Kevin O'Connor36c93a52009-09-12 19:35:04 -040023static int
24cdemu_read(struct disk_op_s *op)
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -050025{
Kevin O'Connor4a16ef62008-12-31 00:09:28 -050026 u16 ebda_seg = get_ebda_seg();
Kevin O'Connor8f469b92010-02-28 01:28:11 -050027 struct drive_s *drive_g;
28 drive_g = GLOBALFLAT2GLOBAL(GET_EBDA2(ebda_seg, cdemu.emulated_drive_gf));
Kevin O'Connor36c93a52009-09-12 19:35:04 -040029 struct disk_op_s dop;
Kevin O'Connor77d227b2009-10-22 21:48:39 -040030 dop.drive_g = drive_g;
Kevin O'Connor36c93a52009-09-12 19:35:04 -040031 dop.command = op->command;
32 dop.lba = GET_EBDA2(ebda_seg, cdemu.ilba) + op->lba / 4;
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -050033
Kevin O'Connor36c93a52009-09-12 19:35:04 -040034 int count = op->count;
35 op->count = 0;
Kevin O'Connord5d02b62010-06-06 16:18:03 -040036 u8 *cdbuf_fl = GET_GLOBAL(cdemu_buf_fl);
Kevin O'Connoraa2590c2008-03-22 23:13:24 -040037
Kevin O'Connor36c93a52009-09-12 19:35:04 -040038 if (op->lba & 3) {
39 // Partial read of first block.
40 dop.count = 1;
Kevin O'Connord5d02b62010-06-06 16:18:03 -040041 dop.buf_fl = cdbuf_fl;
Kevin O'Connor36c93a52009-09-12 19:35:04 -040042 int ret = process_op(&dop);
43 if (ret)
44 return ret;
45 u8 thiscount = 4 - (op->lba & 3);
46 if (thiscount > count)
47 thiscount = count;
48 count -= thiscount;
Kevin O'Connord5d02b62010-06-06 16:18:03 -040049 memcpy_fl(op->buf_fl, cdbuf_fl + (op->lba & 3) * 512, thiscount * 512);
Kevin O'Connor36c93a52009-09-12 19:35:04 -040050 op->buf_fl += thiscount * 512;
51 op->count += thiscount;
52 dop.lba++;
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -050053 }
Kevin O'Connor36c93a52009-09-12 19:35:04 -040054
55 if (count > 3) {
56 // Read n number of regular blocks.
57 dop.count = count / 4;
58 dop.buf_fl = op->buf_fl;
59 int ret = process_op(&dop);
60 op->count += dop.count * 4;
61 if (ret)
62 return ret;
63 u8 thiscount = count & ~3;
64 count &= 3;
65 op->buf_fl += thiscount * 512;
66 dop.lba += thiscount / 4;
67 }
68
69 if (count) {
70 // Partial read on last block.
71 dop.count = 1;
Kevin O'Connord5d02b62010-06-06 16:18:03 -040072 dop.buf_fl = cdbuf_fl;
Kevin O'Connor36c93a52009-09-12 19:35:04 -040073 int ret = process_op(&dop);
74 if (ret)
75 return ret;
76 u8 thiscount = count;
Kevin O'Connord5d02b62010-06-06 16:18:03 -040077 memcpy_fl(op->buf_fl, cdbuf_fl, thiscount * 512);
Kevin O'Connor36c93a52009-09-12 19:35:04 -040078 op->count += thiscount;
79 }
80
81 return DISK_RET_SUCCESS;
82}
83
84int
85process_cdemu_op(struct disk_op_s *op)
86{
87 if (!CONFIG_CDROM_EMU)
88 return 0;
89
90 switch (op->command) {
91 case CMD_READ:
92 return cdemu_read(op);
93 case CMD_WRITE:
94 case CMD_FORMAT:
95 return DISK_RET_EWRITEPROTECT;
96 case CMD_VERIFY:
97 case CMD_RESET:
98 case CMD_SEEK:
99 case CMD_ISREADY:
100 return DISK_RET_SUCCESS;
101 default:
102 op->count = 0;
103 return DISK_RET_EPARAM;
104 }
105}
106
Kevin O'Connor36c93a52009-09-12 19:35:04 -0400107void
Kevin O'Connor1ca05b02010-01-03 17:43:37 -0500108cdemu_setup(void)
Kevin O'Connor36c93a52009-09-12 19:35:04 -0400109{
110 if (!CONFIG_CDROM_EMU)
111 return;
Kevin O'Connord5d02b62010-06-06 16:18:03 -0400112 cdemu_drive_gf = NULL;
113 cdemu_buf_fl = NULL;
114 if (!Drives.cdcount)
115 return;
Kevin O'Connor36c93a52009-09-12 19:35:04 -0400116
Kevin O'Connord7e998f2010-02-15 22:48:28 -0500117 struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g));
Kevin O'Connord5d02b62010-06-06 16:18:03 -0400118 u8 *buf = malloc_low(CDROM_SECTOR_SIZE);
119 if (!drive_g || !buf) {
Kevin O'Connord7e998f2010-02-15 22:48:28 -0500120 warn_noalloc();
Kevin O'Connord5d02b62010-06-06 16:18:03 -0400121 free(drive_g);
122 free(buf);
Kevin O'Connor36c93a52009-09-12 19:35:04 -0400123 return;
124 }
Kevin O'Connor8f469b92010-02-28 01:28:11 -0500125 cdemu_drive_gf = drive_g;
Kevin O'Connord5d02b62010-06-06 16:18:03 -0400126 cdemu_buf_fl = buf;
127 memset(drive_g, 0, sizeof(*drive_g));
Kevin O'Connor77d227b2009-10-22 21:48:39 -0400128 drive_g->type = DTYPE_CDEMU;
129 drive_g->blksize = DISK_SECTOR_SIZE;
130 drive_g->sectors = (u64)-1;
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -0500131}
132
133struct eltorito_s {
134 u8 size;
135 u8 media;
136 u8 emulated_drive;
137 u8 controller_index;
138 u32 ilba;
139 u16 device_spec;
140 u16 buffer_segment;
141 u16 load_segment;
142 u16 sector_count;
143 u8 cylinders;
144 u8 sectors;
145 u8 heads;
146};
147
148#define SET_INT13ET(regs,var,val) \
149 SET_FARVAR((regs)->ds, ((struct eltorito_s*)((regs)->si+0))->var, (val))
150
151// ElTorito - Terminate disk emu
152void
153cdemu_134b(struct bregs *regs)
154{
155 // FIXME ElTorito Hardcoded
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500156 u16 ebda_seg = get_ebda_seg();
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -0500157 SET_INT13ET(regs, size, 0x13);
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500158 SET_INT13ET(regs, media, GET_EBDA2(ebda_seg, cdemu.media));
Kevin O'Connor669e6442009-08-11 22:36:30 -0400159 SET_INT13ET(regs, emulated_drive
160 , GET_EBDA2(ebda_seg, cdemu.emulated_extdrive));
Kevin O'Connor8f469b92010-02-28 01:28:11 -0500161 struct drive_s *drive_gf = GET_EBDA2(ebda_seg, cdemu.emulated_drive_gf);
162 u8 cntl_id = 0;
163 if (drive_gf)
164 cntl_id = GET_GLOBALFLAT(drive_gf->cntl_id);
Kevin O'Connor669e6442009-08-11 22:36:30 -0400165 SET_INT13ET(regs, controller_index, cntl_id / 2);
166 SET_INT13ET(regs, device_spec, cntl_id % 2);
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500167 SET_INT13ET(regs, ilba, GET_EBDA2(ebda_seg, cdemu.ilba));
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500168 SET_INT13ET(regs, buffer_segment, GET_EBDA2(ebda_seg, cdemu.buffer_segment));
169 SET_INT13ET(regs, load_segment, GET_EBDA2(ebda_seg, cdemu.load_segment));
170 SET_INT13ET(regs, sector_count, GET_EBDA2(ebda_seg, cdemu.sector_count));
Kevin O'Connorb68ac712009-08-09 17:25:19 -0400171 SET_INT13ET(regs, cylinders, GET_EBDA2(ebda_seg, cdemu.lchs.cylinders));
172 SET_INT13ET(regs, sectors, GET_EBDA2(ebda_seg, cdemu.lchs.spt));
173 SET_INT13ET(regs, heads, GET_EBDA2(ebda_seg, cdemu.lchs.heads));
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -0500174
175 // If we have to terminate emulation
176 if (regs->al == 0x00) {
177 // FIXME ElTorito Various. Should be handled accordingly to spec
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500178 SET_EBDA2(ebda_seg, cdemu.active, 0x00); // bye bye
Kevin O'Connor7d700252010-02-15 11:56:07 -0500179
180 // XXX - update floppy/hd count.
Kevin O'Connor31d8c8a2008-03-04 19:56:41 -0500181 }
182
183 disk_ret(regs, DISK_RET_SUCCESS);
184}
Kevin O'Connor180a9592008-03-04 22:50:53 -0500185
186
187/****************************************************************
188 * CD booting
189 ****************************************************************/
190
Kevin O'Connora05223c2008-06-28 12:15:57 -0400191static int
Kevin O'Connor7d700252010-02-15 11:56:07 -0500192atapi_is_ready(struct disk_op_s *op)
Kevin O'Connor180a9592008-03-04 22:50:53 -0500193{
Kevin O'Connor7d700252010-02-15 11:56:07 -0500194 dprintf(6, "atapi_is_ready (drive=%p)\n", op->drive_g);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500195
Kevin O'Connora0c68792009-02-12 20:47:59 -0500196 /* Retry READ CAPACITY for 5 seconds unless MEDIUM NOT PRESENT is
197 * reported by the device. If the device reports "IN PROGRESS",
Kevin O'Connor180a9592008-03-04 22:50:53 -0500198 * 30 seconds is added. */
Kevin O'Connor76977b22010-02-17 01:01:32 -0500199 struct cdbres_read_capacity info;
Kevin O'Connora0c68792009-02-12 20:47:59 -0500200 int in_progress = 0;
201 u64 end = calc_future_tsc(5000);
202 for (;;) {
Kevin O'Connor144817b2010-05-23 10:46:49 -0400203 if (check_tsc(end)) {
Kevin O'Connora05223c2008-06-28 12:15:57 -0400204 dprintf(1, "read capacity failed\n");
Kevin O'Connor180a9592008-03-04 22:50:53 -0500205 return -1;
206 }
Kevin O'Connora0c68792009-02-12 20:47:59 -0500207
Kevin O'Connor76977b22010-02-17 01:01:32 -0500208 int ret = cdb_read_capacity(op, &info);
Kevin O'Connora0c68792009-02-12 20:47:59 -0500209 if (!ret)
210 // Success
Kevin O'Connor180a9592008-03-04 22:50:53 -0500211 break;
212
Kevin O'Connor76977b22010-02-17 01:01:32 -0500213 struct cdbres_request_sense sense;
214 ret = cdb_get_sense(op, &sense);
Kevin O'Connora0c68792009-02-12 20:47:59 -0500215 if (ret)
216 // Error - retry.
Kevin O'Connor180a9592008-03-04 22:50:53 -0500217 continue;
218
Kevin O'Connora0c68792009-02-12 20:47:59 -0500219 // Sense succeeded.
Kevin O'Connor76977b22010-02-17 01:01:32 -0500220 if (sense.asc == 0x3a) { /* MEDIUM NOT PRESENT */
Kevin O'Connora05223c2008-06-28 12:15:57 -0400221 dprintf(1, "Device reports MEDIUM NOT PRESENT\n");
Kevin O'Connor180a9592008-03-04 22:50:53 -0500222 return -1;
223 }
224
Kevin O'Connor76977b22010-02-17 01:01:32 -0500225 if (sense.asc == 0x04 && sense.ascq == 0x01 && !in_progress) {
Kevin O'Connor180a9592008-03-04 22:50:53 -0500226 /* IN PROGRESS OF BECOMING READY */
227 printf("Waiting for device to detect medium... ");
228 /* Allow 30 seconds more */
Kevin O'Connora0c68792009-02-12 20:47:59 -0500229 end = calc_future_tsc(30000);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500230 in_progress = 1;
231 }
232 }
233
Kevin O'Connor76977b22010-02-17 01:01:32 -0500234 u32 blksize = ntohl(info.blksize), sectors = ntohl(info.sectors);
Kevin O'Connor7d700252010-02-15 11:56:07 -0500235 if (blksize != GET_GLOBAL(op->drive_g->blksize)) {
Kevin O'Connora0c68792009-02-12 20:47:59 -0500236 printf("Unsupported sector size %u\n", blksize);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500237 return -1;
238 }
Kevin O'Connor180a9592008-03-04 22:50:53 -0500239
Kevin O'Connora05223c2008-06-28 12:15:57 -0400240 dprintf(6, "sectors=%u\n", sectors);
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500241 printf("%dMB medium detected\n", sectors>>(20-11));
Kevin O'Connor180a9592008-03-04 22:50:53 -0500242 return 0;
243}
244
Kevin O'Connora05223c2008-06-28 12:15:57 -0400245int
Kevin O'Connor7da1dcd2009-02-16 10:51:24 -0500246cdrom_boot(int cdid)
Kevin O'Connor180a9592008-03-04 22:50:53 -0500247{
Kevin O'Connor7d700252010-02-15 11:56:07 -0500248 struct disk_op_s dop;
249 memset(&dop, 0, sizeof(dop));
250 dop.drive_g = getDrive(EXTTYPE_CD, cdid);
251 if (!dop.drive_g)
Kevin O'Connor7da1dcd2009-02-16 10:51:24 -0500252 return 1;
Kevin O'Connor180a9592008-03-04 22:50:53 -0500253
Kevin O'Connor7d700252010-02-15 11:56:07 -0500254 int ret = atapi_is_ready(&dop);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500255 if (ret)
Kevin O'Connor65e63422008-07-19 14:12:32 -0400256 dprintf(1, "atapi_is_ready returned %d\n", ret);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500257
258 // Read the Boot Record Volume Descriptor
259 u8 buffer[2048];
Kevin O'Connor4524bf72008-12-31 00:31:03 -0500260 dop.lba = 0x11;
261 dop.count = 1;
Kevin O'Connor35ae7262009-01-19 15:44:44 -0500262 dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer);
Kevin O'Connor76977b22010-02-17 01:01:32 -0500263 ret = cdb_read(&dop);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500264 if (ret)
265 return 3;
266
267 // Validity checks
268 if (buffer[0])
269 return 4;
Kevin O'Connor38d1a342009-04-18 16:59:47 -0400270 if (strcmp((char*)&buffer[1], "CD001\001EL TORITO SPECIFICATION") != 0)
Kevin O'Connor180a9592008-03-04 22:50:53 -0500271 return 5;
272
273 // ok, now we calculate the Boot catalog address
274 u32 lba = *(u32*)&buffer[0x47];
275
276 // And we read the Boot Catalog
Kevin O'Connor4524bf72008-12-31 00:31:03 -0500277 dop.lba = lba;
Kevin O'Connor76977b22010-02-17 01:01:32 -0500278 dop.count = 1;
279 ret = cdb_read(&dop);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500280 if (ret)
281 return 7;
282
283 // Validation entry
284 if (buffer[0x00] != 0x01)
285 return 8; // Header
286 if (buffer[0x01] != 0x00)
287 return 9; // Platform
288 if (buffer[0x1E] != 0x55)
289 return 10; // key 1
290 if (buffer[0x1F] != 0xAA)
291 return 10; // key 2
292
293 // Initial/Default Entry
294 if (buffer[0x20] != 0x88)
295 return 11; // Bootable
296
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500297 u16 ebda_seg = get_ebda_seg();
Kevin O'Connordfa16502008-03-22 20:13:08 -0400298 u8 media = buffer[0x21];
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500299 SET_EBDA2(ebda_seg, cdemu.media, media);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500300
Kevin O'Connor8f469b92010-02-28 01:28:11 -0500301 SET_EBDA2(ebda_seg, cdemu.emulated_drive_gf, dop.drive_g);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500302
303 u16 boot_segment = *(u16*)&buffer[0x22];
304 if (!boot_segment)
305 boot_segment = 0x07C0;
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500306 SET_EBDA2(ebda_seg, cdemu.load_segment, boot_segment);
307 SET_EBDA2(ebda_seg, cdemu.buffer_segment, 0x0000);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500308
309 u16 nbsectors = *(u16*)&buffer[0x26];
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500310 SET_EBDA2(ebda_seg, cdemu.sector_count, nbsectors);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500311
312 lba = *(u32*)&buffer[0x28];
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500313 SET_EBDA2(ebda_seg, cdemu.ilba, lba);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500314
315 // And we read the image in memory
Kevin O'Connora4d70aa2009-08-09 11:32:00 -0400316 dop.lba = lba;
317 dop.count = DIV_ROUND_UP(nbsectors, 4);
Kevin O'Connor35ae7262009-01-19 15:44:44 -0500318 dop.buf_fl = MAKE_FLATPTR(boot_segment, 0);
Kevin O'Connor76977b22010-02-17 01:01:32 -0500319 ret = cdb_read(&dop);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500320 if (ret)
321 return 12;
322
Kevin O'Connordfa16502008-03-22 20:13:08 -0400323 if (media == 0) {
324 // No emulation requested - return success.
Kevin O'Connor51cfbe72009-08-18 22:38:49 -0400325 SET_EBDA2(ebda_seg, cdemu.emulated_extdrive, EXTSTART_CD + cdid);
Kevin O'Connordfa16502008-03-22 20:13:08 -0400326 return 0;
327 }
328
329 // Emulation of a floppy/harddisk requested
Kevin O'Connor8f469b92010-02-28 01:28:11 -0500330 if (! CONFIG_CDROM_EMU || !cdemu_drive_gf)
Kevin O'Connordfa16502008-03-22 20:13:08 -0400331 return 13;
332
333 // Set emulated drive id and increase bios installed hardware
334 // number of devices
335 if (media < 4) {
336 // Floppy emulation
Kevin O'Connor669e6442009-08-11 22:36:30 -0400337 SET_EBDA2(ebda_seg, cdemu.emulated_extdrive, 0x00);
Kevin O'Connor7d700252010-02-15 11:56:07 -0500338 // XXX - get and set actual floppy count.
Kevin O'Connordfa16502008-03-22 20:13:08 -0400339 SETBITS_BDA(equipment_list_flags, 0x41);
Kevin O'Connor95827c42009-02-07 00:04:57 -0500340
341 switch (media) {
342 case 0x01: // 1.2M floppy
Kevin O'Connorb68ac712009-08-09 17:25:19 -0400343 SET_EBDA2(ebda_seg, cdemu.lchs.spt, 15);
344 SET_EBDA2(ebda_seg, cdemu.lchs.cylinders, 80);
345 SET_EBDA2(ebda_seg, cdemu.lchs.heads, 2);
Kevin O'Connor95827c42009-02-07 00:04:57 -0500346 break;
347 case 0x02: // 1.44M floppy
Kevin O'Connorb68ac712009-08-09 17:25:19 -0400348 SET_EBDA2(ebda_seg, cdemu.lchs.spt, 18);
349 SET_EBDA2(ebda_seg, cdemu.lchs.cylinders, 80);
350 SET_EBDA2(ebda_seg, cdemu.lchs.heads, 2);
Kevin O'Connor95827c42009-02-07 00:04:57 -0500351 break;
352 case 0x03: // 2.88M floppy
Kevin O'Connorb68ac712009-08-09 17:25:19 -0400353 SET_EBDA2(ebda_seg, cdemu.lchs.spt, 36);
354 SET_EBDA2(ebda_seg, cdemu.lchs.cylinders, 80);
355 SET_EBDA2(ebda_seg, cdemu.lchs.heads, 2);
Kevin O'Connor95827c42009-02-07 00:04:57 -0500356 break;
357 }
Kevin O'Connordfa16502008-03-22 20:13:08 -0400358 } else {
359 // Harddrive emulation
Kevin O'Connor669e6442009-08-11 22:36:30 -0400360 SET_EBDA2(ebda_seg, cdemu.emulated_extdrive, 0x80);
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500361 SET_BDA(hdcount, GET_BDA(hdcount) + 1);
Kevin O'Connordfa16502008-03-22 20:13:08 -0400362
Kevin O'Connor95827c42009-02-07 00:04:57 -0500363 // Peak at partition table to get chs.
364 struct mbr_s *mbr = (void*)0;
365 u8 sptcyl = GET_FARVAR(boot_segment, mbr->partitions[0].last.sptcyl);
366 u8 cyllow = GET_FARVAR(boot_segment, mbr->partitions[0].last.cyllow);
367 u8 heads = GET_FARVAR(boot_segment, mbr->partitions[0].last.heads);
368
Kevin O'Connorb68ac712009-08-09 17:25:19 -0400369 SET_EBDA2(ebda_seg, cdemu.lchs.spt, sptcyl & 0x3f);
370 SET_EBDA2(ebda_seg, cdemu.lchs.cylinders
371 , ((sptcyl<<2)&0x300) + cyllow + 1);
372 SET_EBDA2(ebda_seg, cdemu.lchs.heads, heads + 1);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500373 }
374
Kevin O'Connordfa16502008-03-22 20:13:08 -0400375 // everything is ok, so from now on, the emulation is active
Kevin O'Connor4a16ef62008-12-31 00:09:28 -0500376 SET_EBDA2(ebda_seg, cdemu.active, 0x01);
Kevin O'Connora05223c2008-06-28 12:15:57 -0400377 dprintf(6, "cdemu media=%d\n", media);
Kevin O'Connor180a9592008-03-04 22:50:53 -0500378
379 return 0;
380}