---------------------------------------------------------------------- Patch name: patch.4ata-channels Author: christophe Bothamy Date: 14 september 2002 Detailed description: I merged Bryce's patch and mine. Here are the descriptions of both : ---------------------------------------------------------------------- This patch adds 4 ata channels support for Bochs. Features : - number of active channels defined at boot-time config - new options in bochsrc - up to 8 devices support (disks or cdroms) - up to 4 cdrom devices can be changed at runtime config You'll want to use BIOS-bochs-new-ata to be able to access new devices from the bios. I have not split "harddrv.cc" in simpler files yet. ---------------------------------------------------------------------- This patch applies on top of Christophe Bothamy's 4ata-channels patch. I'm keeping a separate patch in case Christophe wants to make revisions to his patch without my changes getting in the way. I have just been working on the configuration interface part, in both the text interface and wxWindows. - set default I/O address for all ata channels, even the ones which are disabled by default. It's easier to configure from scratch if we have reasonable defaults already. (I know many options default to zero instead of reasonable defaults, but I don't like that either.) - eliminate huge initialization lists atachannel_init_list[][] and atadevice_init_list[][] by creating the bx_list_c and calling the add() method from inside a loop. - fix bugs in the bochsrc output code (extra or missing comma problems) - Also I'm using a trick: since the dependent_list and the menus contain almost the same items, I build just one list at first. Then since I need to add a few more items to the dependent list (but I don't want them to show on the menu) I call bx_list_c::clone() to make a copy to use as the dependent list. Example: BXP_ATA0 menu: BXP_ATA0_PRESENT, BXP_ATA0_IOADDR1, BXP_ATA0_IOADDR2, BXP_ATA0_IRQ dependent list for BXP_ATA0_PRESENT: BXP_ATA0_PRESENT, BXP_ATA0_IOADDR1, BXP_ATA0_IOADDR2, BXP_ATA0_IRQ, BXP_ATA0_MASTER_PRESENT, BXP_ATA0_SLAVE_PRESENT - the ata devices have both a "present" boolean parameter and a "type" enum parameter. I removed the "none" value in the type enum, because it was the same as having present=false. This made the enable/disable logic somewhat easier. - Now the ATA channel present parameters have a dependent_list which includes both the ATA channel parameters and also the ATA device parameters that are on that channel. This way, when you disable the ATA channel, the devices on the channel will be disabled too. I am using the dependent_list instead of the callback function that calls set_enable because it allows wxWindows to do the enable/disables without any special code to handle each case. - a few changes relating to bx_param_num_c::update_dependents(): - don't allow a parameter to disable itself. This allows the "present" param to be included in its own dependency list without danger of disabling itself forever. - before, if a param with dependents had a value of zero, it would disable its dependent parameters. Now it will also disable its dependents if the param itself is disabled. - when a parameter with dependents is enabled/disabled, it now calls update_dependents() as well. Before this only happened when the value was changed. - in wxdialog.cc, I've added equivalent logic in EnableChanged and EnumChanged so that the wxWindows dialogs follow the same dependency rules. It doesn't work in quite the same way because the text interface changes the params immediately while the wxWindows interface only changes the params when Ok is pressed, but it is very similar. - in wxWindows, replace the Edit Hard Disk and Edit Cdrom menu items with ATA Controller items. - in ParamDialog, I now add the wxStaticText label for each parameter to the ParamStruct. If the param is enabled/disabled, the label will be changed as well. Esp. since gtk wxCheckboxes do not change visibly when disabled, having the label change to grey is good. - in the selection of boot disk, I didn't check for all possibilities of hard disks and cdroms. If you want to boot from a hard disk, you should make it ata0-master, and if you want to boot from a cdrom, you should make it ata0-slave. This is just a wxwindows limitation, because Christophe says the BIOS would be able to boot a hard disk on ata3-slave if that was the first one, but I think we can live with it for now. - add clone() method of bx_list_c, which makes a copy. I could not use the dependent_list trick to handle the "type" field of the ATA devices. When type=disk, it's supposed to enable cylinders, heads, and spt, but when type=cdrom, it's supposed to disable C/H/S and enable the inserted/ejected param instead. There's currently no way to do this with dependent_list, so I left this behavior in the bx_param_handler callback function. The problem with using callback functions to handle the enabling of other parameters (and the reason that I've been moving away from them for this purpose) is that in a GUI dialog box, you don't want to change any parameter value until the user presses "Ok". If callback functions control the enabling of other parameters, I cannot know which parts of the dialog to enable/disable without modifying the parameter with set(). Possible solutions: 1) have the dialog box code remember the old value of every param, to be able to implement Cancel. 2) in each param structure, remember the new value and the previous value. Then if the user presses cancel, I can revert each param back to its previous value. 3) for special cases such as enabling C/H/S when type=disk, duplicate the enable/disable code in each implementation of the user interface. #3 is what I've done in ParamDialog::EnumChanged. Patch was created with: cvs diff -u Apply patch to what version: cvs checked out on 14 september 2002 Instructions: To patch, go to main bochs directory. Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- Index: misc/bximage.c =================================================================== RCS file: /cvsroot/bochs/bochs/misc/bximage.c,v retrieving revision 1.10 diff -u -r1.10 bximage.c --- misc/bximage.c 5 Sep 2002 16:50:03 -0000 1.10 +++ misc/bximage.c 22 Sep 2002 20:46:02 -0000 @@ -261,7 +261,7 @@ printf (" total size=%.2f megabytes\n", (float)sectors*512.0/1024.0/1024.0); if (ask_string ("\nWhat should I name the image?\n[c.img] ", "c.img", filename) < 0) fatal (EOF_ERR); - sprintf (bochsrc_line, "diskc: file=\"%s\", cyl=%d, heads=%d, spt=%d", filename, cyl, heads, spt); + sprintf (bochsrc_line, "ata0-master: type=disk, path=\"%s\", cylinders=%d, heads=%d, spt=%d", filename, cyl, heads, spt); } else { int fdsize, cyl=0, heads=0, spt=0; char *name = NULL; Index: bochs.h =================================================================== RCS file: /cvsroot/bochs/bochs/bochs.h,v retrieving revision 1.95 diff -u -r1.95 bochs.h --- bochs.h 21 Sep 2002 11:38:12 -0000 1.95 +++ bochs.h 22 Sep 2002 20:46:03 -0000 @@ -491,6 +491,7 @@ +/* Already in gui/siminterface.h ??? #define BX_FLOPPY_NONE 10 // floppy not present #define BX_FLOPPY_1_2 11 // 1.2M 5.25" #define BX_FLOPPY_1_44 12 // 1.44M 3.5" @@ -498,6 +499,7 @@ #define BX_FLOPPY_720K 14 // 720K 3.5" #define BX_FLOPPY_360K 15 // 360K 5.25" #define BX_FLOPPY_LAST 15 // last one +*/ #define BX_READ 0 @@ -549,6 +551,13 @@ #define BX_PATHNAME_LEN 512 typedef struct { + bx_param_bool_c *Opresent; + bx_param_num_c *Oioaddr1; + bx_param_num_c *Oioaddr2; + bx_param_num_c *Oirq; + } bx_ata_options; + +typedef struct { bx_param_string_c *Opath; bx_param_num_c *Oaddress; } bx_rom_options; @@ -630,10 +639,12 @@ typedef struct { bx_floppy_options floppya; bx_floppy_options floppyb; - bx_disk_options diskc; - bx_disk_options diskd; + bx_ata_options ata[BX_MAX_ATA_CHANNEL]; + bx_atadevice_options atadevice[BX_MAX_ATA_CHANNEL][2]; + // bx_disk_options diskc; + // bx_disk_options diskd; + // bx_cdrom_options cdromd; bx_serial_options com[BX_N_SERIAL_PORTS]; - bx_cdrom_options cdromd; bx_rom_options rom; bx_vgarom_options vgarom; bx_rom_options optrom[BX_N_OPTROM_IMAGES]; // Optional rom images Index: config.h.in =================================================================== RCS file: /cvsroot/bochs/bochs/config.h.in,v retrieving revision 1.72 diff -u -r1.72 config.h.in --- config.h.in 22 Sep 2002 16:11:11 -0000 1.72 +++ config.h.in 22 Sep 2002 20:46:04 -0000 @@ -270,6 +270,13 @@ // [[Provide example of partitioning]] #define BX_SPLIT_HD_SUPPORT 0 +// This option defines the number of supported ATA channels. +// There are up to two drives per ATA channel. +#define BX_MAX_ATA_CHANNEL 4 + +#if (BX_MAX_ATA_CHANNEL>4 || BX_MAX_ATA_CHANNEL<1) +# error "BX_MAX_ATA_CHANNEL should be between 1 and 4" +#endif // ================================================================= // BEGIN: OPTIONAL DEBUGGER SECTION Index: main.cc =================================================================== RCS file: /cvsroot/bochs/bochs/main.cc,v retrieving revision 1.143 diff -u -r1.143 main.cc --- main.cc 20 Sep 2002 18:14:25 -0000 1.143 +++ main.cc 22 Sep 2002 20:46:06 -0000 @@ -113,9 +113,18 @@ SIM->get_param (BXP_LOAD32BITOS_INITRD)->set_enabled (enable); } break; - case BXP_CDROM_STATUS: + case BXP_ATA0_MASTER_STATUS: + case BXP_ATA0_SLAVE_STATUS: + case BXP_ATA1_MASTER_STATUS: + case BXP_ATA1_SLAVE_STATUS: + case BXP_ATA2_MASTER_STATUS: + case BXP_ATA2_SLAVE_STATUS: + case BXP_ATA3_MASTER_STATUS: + case BXP_ATA3_SLAVE_STATUS: if ((set) && (SIM->get_init_done ())) { - bx_devices.hard_drive->set_cd_media_status(val == BX_INSERTED); + Bit8u device = id - BXP_ATA0_MASTER_STATUS; + Bit32u handle = bx_devices.hard_drive->get_device_handle (device/2, device%2); + bx_devices.hard_drive->set_cd_media_status(handle, val == BX_INSERTED); bx_gui.update_drive_status_buttons (); } break; @@ -144,6 +153,42 @@ case BXP_KBD_PASTE_DELAY: if (set) bx_keyboard.paste_delay_changed (); break; + case BXP_ATA0_MASTER_TYPE: + case BXP_ATA0_SLAVE_TYPE: + case BXP_ATA1_MASTER_TYPE: + case BXP_ATA1_SLAVE_TYPE: + case BXP_ATA2_MASTER_TYPE: + case BXP_ATA2_SLAVE_TYPE: + case BXP_ATA3_MASTER_TYPE: + case BXP_ATA3_SLAVE_TYPE: + if (set) { + int device = id - BXP_ATA0_MASTER_TYPE; + switch (val) { + case BX_ATA_DEVICE_DISK: + SIM->get_param_num ((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->set (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_CYLINDERS + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_HEADS + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_SPT + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_enabled (0); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_TRANSLATION + device))->set_enabled (1); + break; + case BX_ATA_DEVICE_CDROM: + SIM->get_param_num ((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->set (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_CYLINDERS + device))->set_enabled (0); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_HEADS + device))->set_enabled (0); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_SPT + device))->set_enabled (0); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled (1); + SIM->get_param ((bx_id)(BXP_ATA0_MASTER_TRANSLATION + device))->set_enabled (0); + break; + } + } + break; default: BX_PANIC (("bx_param_handler called with unknown id %d", id)); return -1; @@ -153,12 +198,14 @@ char *bx_param_string_handler (bx_param_string_c *param, int set, char *val, int maxlen) { + bx_id id = param->get_id (); + int empty = 0; if ((strlen(val) < 1) || !strcmp ("none", val)) { empty = 1; val = "none"; } - switch (param->get_id ()) { + switch (id) { case BXP_FLOPPYA_PATH: if (set==1) { if (SIM->get_init_done ()) { @@ -209,46 +256,44 @@ } } break; - case BXP_DISKC_PATH: - if (set==1) { - SIM->get_param_num(BXP_DISKC_PRESENT)->set (!empty); - SIM->get_param_num(BXP_DISKC_CYLINDERS)->set_enabled (!empty); - SIM->get_param_num(BXP_DISKC_HEADS)->set_enabled (!empty); - SIM->get_param_num(BXP_DISKC_SPT)->set_enabled (!empty); - } - break; - case BXP_DISKD_PATH: - if (set==1) { - SIM->get_param_num(BXP_DISKD_PRESENT)->set (!empty); - SIM->get_param_num(BXP_DISKD_CYLINDERS)->set_enabled (!empty); - SIM->get_param_num(BXP_DISKD_HEADS)->set_enabled (!empty); - SIM->get_param_num(BXP_DISKD_SPT)->set_enabled (!empty); - } - break; - case BXP_CDROM_PATH: + + case BXP_ATA0_MASTER_PATH: + case BXP_ATA0_SLAVE_PATH: + case BXP_ATA1_MASTER_PATH: + case BXP_ATA1_SLAVE_PATH: + case BXP_ATA2_MASTER_PATH: + case BXP_ATA2_SLAVE_PATH: + case BXP_ATA3_MASTER_PATH: + case BXP_ATA3_SLAVE_PATH: if (set==1) { + Bit8u device = id - BXP_ATA0_MASTER_PATH; + Bit32u handle = bx_devices.hard_drive->get_device_handle(device/2, device%2); + if (SIM->get_init_done ()) { if (empty) { - bx_devices.hard_drive->set_cd_media_status(0); + bx_devices.hard_drive->set_cd_media_status(handle, 0); bx_gui.update_drive_status_buttons (); } else { - if (!SIM->get_param_num(BXP_CDROM_PRESENT)->get ()) { + if (!SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->get ()) { BX_ERROR(("Cannot add a cdrom drive at runtime")); - bx_options.cdromd.Opath->set ("none"); + bx_options.atadevice[device/2][device%2].Opresent->set (0); + } + if (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get () != BX_ATA_DEVICE_CDROM) { + BX_ERROR(("Device is not a cdrom drive")); + bx_options.atadevice[device/2][device%2].Opresent->set (0); } } if ((bx_devices.hard_drive) && - (SIM->get_param_num(BXP_CDROM_STATUS)->get () == BX_INSERTED)) { + (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_STATUS + device))->get () == BX_INSERTED) && + (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get () == BX_ATA_DEVICE_CDROM)) { // tell the device model that we removed, then inserted the cd - bx_devices.hard_drive->set_cd_media_status(0); - bx_devices.hard_drive->set_cd_media_status(1); + bx_devices.hard_drive->set_cd_media_status(handle, 0); + bx_devices.hard_drive->set_cd_media_status(handle, 1); } - } else { - SIM->get_param_num(BXP_CDROM_PRESENT)->set (!empty); - SIM->get_param_num(BXP_CDROM_STATUS)->set_enabled (!empty); } } break; + case BXP_SCREENMODE: if (set==1) { BX_INFO (("Screen mode changed to %s", val)); @@ -260,7 +305,6 @@ return val; } - void bx_init_options () { int i; @@ -370,127 +414,229 @@ bx_options.floppyb.Otype->set_handler (bx_param_handler); bx_options.floppyb.Ostatus->set_handler (bx_param_handler); - // diskc options - bx_options.diskc.Opresent = new bx_param_bool_c (BXP_DISKC_PRESENT, - "diskc:present", - "Controls whether diskc is installed or not", - 0); - bx_options.diskc.Opath = new bx_param_filename_c (BXP_DISKC_PATH, - "", - "Pathname of the hard drive image", - "", BX_PATHNAME_LEN); - bx_options.diskc.Ocylinders = new bx_param_num_c (BXP_DISKC_CYLINDERS, - "diskc:cylinders", - "Number of cylinders", - 0, 65535, - 0); - bx_options.diskc.Oheads = new bx_param_num_c (BXP_DISKC_HEADS, - "diskc:heads", - "Number of heads", - 0, 65535, - 0); - bx_options.diskc.Ospt = new bx_param_num_c (BXP_DISKC_SPT, - "diskc:spt", - "Number of sectors per track", - 0, 65535, - 0); - bx_options.diskc.Opath->set_ask_format ("Enter new filename, or 'none' for no disk: [%s] "); - bx_options.diskc.Ocylinders->set_ask_format ("Enter number of cylinders: [%d] "); - bx_options.diskc.Oheads->set_ask_format ("Enter number of heads: [%d] "); - bx_options.diskc.Ospt->set_ask_format ("Enter number of sectors per track: [%d] "); - bx_options.diskc.Opath->set_format ("%s"); - bx_options.diskc.Ocylinders->set_format (", %d cylinders, "); - bx_options.diskc.Oheads->set_format ("%d heads, "); - bx_options.diskc.Ospt->set_format ("%d sectors/track"); - bx_param_c *diskc_init_list[] = { - bx_options.diskc.Opath, - bx_options.diskc.Ocylinders, - bx_options.diskc.Oheads, - bx_options.diskc.Ospt, - NULL + // disk options + + // FIXME use descr and name + char *s_atachannel[] = { + "ATA channel 0", + "ATA channel 1", + "ATA channel 2", + "ATA channel 3", + }; + char *s_atadevice[4][2] = { + { "Master ATA device on channel 0", + "Slave ATA device on channel 0" }, + { "Master ATA device on channel 1", + "Slave ATA device on channel 1" }, + { "Master ATA device on channel 2", + "Slave ATA device on channel 2" }, + { "Master ATA device on channel 3", + "Slave ATA device on channel 3" } + }; + Bit16u ata_default_ioaddr1[BX_MAX_ATA_CHANNEL] = { + 0x1f0, 0x170, 0x1e8, 0x168 }; - menu = new bx_list_c (BXP_DISKC, "Hard disk 0", "All options for hard disk 0", diskc_init_list); - menu->get_options ()->set (menu->BX_SERIES_ASK); - // if path is the word "none", then do not ask the other options and - // set present=0. - bx_options.diskc.Opath->set_handler (bx_param_string_handler); - bx_options.diskc.Opath->set ("none"); - - // diskd options - bx_options.diskd.Opresent = new bx_param_bool_c (BXP_DISKD_PRESENT, - "diskd:present", - "Controls whether diskd is installed or not", - 0); - bx_options.diskd.Opath = new bx_param_filename_c (BXP_DISKD_PATH, - "diskd:path", - "Pathname of the hard drive image", - "", BX_PATHNAME_LEN); - bx_options.diskd.Ocylinders = new bx_param_num_c (BXP_DISKD_CYLINDERS, - "diskd:cylinders", - "Number of cylinders", - 0, 65535, - 0); - bx_options.diskd.Oheads = new bx_param_num_c (BXP_DISKD_HEADS, - "diskd:heads", - "Number of heads", - 0, 65535, - 0); - bx_options.diskd.Ospt = new bx_param_num_c (BXP_DISKD_SPT, - "diskd:spt", - "Number of sectors per track", - 0, 65535, - 0); - bx_options.diskd.Opath->set_ask_format ("Enter new filename, or none for no disk: [%s] "); - bx_options.diskd.Ocylinders->set_ask_format ("Enter number of cylinders: [%d] "); - bx_options.diskd.Oheads->set_ask_format ("Enter number of heads: [%d] "); - bx_options.diskd.Ospt->set_ask_format ("Enter number of sectors per track: [%d] "); - bx_options.diskd.Opath->set_format ("%s"); - bx_options.diskd.Ocylinders->set_format (", %d cylinders, "); - bx_options.diskd.Oheads->set_format ("%d heads, "); - bx_options.diskd.Ospt->set_format ("%d sectors/track"); - bx_param_c *diskd_init_list[] = { - bx_options.diskd.Opath, - bx_options.diskd.Ocylinders, - bx_options.diskd.Oheads, - bx_options.diskd.Ospt, - NULL + Bit8u ata_default_irq[BX_MAX_ATA_CHANNEL] = { + 14, 15, 12, 11 }; - menu = new bx_list_c (BXP_DISKD, "Hard disk 1", "All options for hard disk 1", diskd_init_list); - menu->get_options ()->set (menu->BX_SERIES_ASK); - bx_options.diskd.Opath->set_handler (bx_param_string_handler); - bx_options.diskd.Opath->set ("none"); - // cdrom options - bx_options.cdromd.Opresent = new bx_param_bool_c (BXP_CDROM_PRESENT, - "CDROM is present", - "Controls whether cdromd is installed or not", - 0); - bx_options.cdromd.Opath = new bx_param_filename_c (BXP_CDROM_PATH, - "CDROM image filename", - "Pathname of the cdrom device or image", - "", BX_PATHNAME_LEN); - bx_options.cdromd.Opath->set_format ("%s"); -#if BX_UI_TEXT - bx_options.cdromd.Opath->set_ask_format ("Enter new filename, or 'none' for no CDROM: [%s] "); -#endif - bx_options.cdromd.Ostatus = new bx_param_enum_c (BXP_CDROM_STATUS, - "Is the CDROM inserted or ejected", - "Inserted or ejected", - floppy_status_names, - BX_INSERTED, - BX_EJECTED); - bx_options.cdromd.Ostatus->set_format (", %s"); - bx_options.cdromd.Ostatus->set_ask_format ("Is the CDROM inserted or ejected? [%s] "); - bx_param_c *cdromd_init_list[] = { - bx_options.cdromd.Opath, - bx_options.cdromd.Ostatus, - NULL - }; - menu = new bx_list_c (BXP_CDROMD, "CDROM", "Options for the CDROM", cdromd_init_list); - menu->get_options ()->set (menu->BX_SERIES_ASK); - bx_options.cdromd.Opath->set_handler (bx_param_string_handler); - bx_options.cdromd.Opath->set ("none"); - bx_options.cdromd.Ostatus->set_handler (bx_param_handler); + bx_list_c *ata[BX_MAX_ATA_CHANNEL]; + + for (Bit8u channel=0; channelget_options ()->set (ata[channel]->BX_SERIES_ASK); + + ata[channel]->add (bx_options.ata[channel].Opresent = new bx_param_bool_c ((bx_id)(BXP_ATA0_PRESENT+channel), + "ata:present", + "Controls whether ata channel is installed or not", + 0)); + + ata[channel]->add (bx_options.ata[channel].Oioaddr1 = new bx_param_num_c ((bx_id)(BXP_ATA0_IOADDR1+channel), + "ata:ioaddr1", + "IO adress of ata command block", + 0, 0xffff, + ata_default_ioaddr1[channel])); + + ata[channel]->add (bx_options.ata[channel].Oioaddr2 = new bx_param_num_c ((bx_id)(BXP_ATA0_IOADDR2+channel), + "ata:ioaddr2", + "IO adress of ata control block", + 0, 0xffff, + ata_default_ioaddr1[channel] + 0x200)); + + ata[channel]->add (bx_options.ata[channel].Oirq = new bx_param_num_c ((bx_id)(BXP_ATA0_IRQ+channel), + "ata:irq", + "IRQ of ata ", + 0, 15, + ata_default_irq[channel])); + + // all items in the ata[channel] menu depend on the present flag. + // The menu list is complete, but a few dependent_list items will + // be added later. Use clone() to make a copy of the dependent_list + // so that it can be changed without affecting the menu. + bx_options.ata[channel].Opresent->set_dependent_list ( + ata[channel]->clone()); + + for (Bit8u slave=0; slave<2; slave++) { + + menu = bx_options.atadevice[channel][slave].Omenu = new bx_list_c ((bx_id)(BXP_ATA0_MASTER+channel*2+slave), + s_atadevice[channel][slave], + s_atadevice[channel][slave], + 12 /* list max size */); + menu->get_options ()->set (menu->BX_SERIES_ASK); + + menu->add (bx_options.atadevice[channel][slave].Opresent = new bx_param_bool_c ((bx_id)(BXP_ATA0_MASTER_PRESENT+channel*2+slave), + "ata-device:present", + "Controls whether ata device is installed or not", + 0)); + + menu->add (bx_options.atadevice[channel][slave].Otype = new bx_param_enum_c ((bx_id)(BXP_ATA0_MASTER_TYPE+channel*2+slave), + "ata-device:type", + "Type of ATA device", + atadevice_type_names, + BX_ATA_DEVICE_DISK, + BX_ATA_DEVICE_DISK)); + + menu->add (bx_options.atadevice[channel][slave].Opath = new bx_param_filename_c ((bx_id)(BXP_ATA0_MASTER_PATH+channel*2+slave), + "ata-device:path", + "Pathname of the image", + "", BX_PATHNAME_LEN)); + + menu->add (bx_options.atadevice[channel][slave].Ocylinders = new bx_param_num_c ((bx_id)(BXP_ATA0_MASTER_CYLINDERS+channel*2+slave), + "ata-device:cylinders", + "Number of cylinders", + 0, 65535, + 0)); + menu->add (bx_options.atadevice[channel][slave].Oheads = new bx_param_num_c ((bx_id)(BXP_ATA0_MASTER_HEADS+channel*2+slave), + "ata-device:heads", + "Number of heads", + 0, 65535, + 0)); + menu->add (bx_options.atadevice[channel][slave].Ospt = new bx_param_num_c ((bx_id)(BXP_ATA0_MASTER_SPT+channel*2+slave), + "ata-device:spt", + "Number of sectors per track", + 0, 65535, + 0)); + + menu->add (bx_options.atadevice[channel][slave].Ostatus = new bx_param_enum_c ((bx_id)(BXP_ATA0_MASTER_STATUS+channel*2+slave), + "ata-device:status", + "Inserted or ejected", + atadevice_status_names, + BX_INSERTED, + BX_EJECTED)); + + menu->add (bx_options.atadevice[channel][slave].Omodel = new bx_param_string_c ((bx_id)(BXP_ATA0_MASTER_MODEL+channel*2+slave), + "ata-device:model", + "Model name", + "Generic 1234", 40)); + + menu->add (bx_options.atadevice[channel][slave].Obiosdetect = new bx_param_enum_c ((bx_id)(BXP_ATA0_MASTER_BIOSDETECT+channel*2+slave), + "ata-device:biosdetect", + "Type of bios detection", + atadevice_biosdetect_names, + BX_ATA_BIOSDETECT_AUTO, + BX_ATA_BIOSDETECT_NONE)); + + menu->add (bx_options.atadevice[channel][slave].Otranslation = new bx_param_enum_c ((bx_id)(BXP_ATA0_MASTER_TRANSLATION+channel*2+slave), + "How the ata-disk translation is done by the bios", + "Type of translation", + atadevice_translation_names, + BX_ATA_TRANSLATION_LBA, + BX_ATA_TRANSLATION_NONE)); + + bx_options.atadevice[channel][slave].Opresent->set_dependent_list ( + menu->clone ()); + // the menu and all items on it depend on the Opresent flag + bx_options.atadevice[channel][slave].Opresent->get_dependent_list()->add(menu); + // the present flag depends on the ATA channel's present flag + bx_options.ata[channel].Opresent->get_dependent_list()->add ( + bx_options.atadevice[channel][slave].Opresent); + } + } + + // Enable first ata interface by default, disable the others. + bx_options.ata[0].Opresent->set_initial_val(1); + + // now that the dependence relationships are established, call set() on + // the ata device present params to set all enables correctly. + for (i=0; iset (i==0); + + for (Bit8u channel=0; channelset_ask_format ( + BX_WITH_WX? "Enable?" + : "Channel is enabled: [%s] "); + bx_options.ata[channel].Oioaddr1->set_ask_format ( + BX_WITH_WX? "I/O Address 1:" + : "Enter new ioaddr1: [0x%x] "); + bx_options.ata[channel].Oioaddr2->set_ask_format ( + BX_WITH_WX? "I/O Address 2:" + : "Enter new ioaddr2: [0x%x] "); + bx_options.ata[channel].Oirq->set_ask_format ( + BX_WITH_WX? "IRQ:" + : "Enter new IRQ: [%d] "); +#if !BX_WITH_WX + bx_options.ata[channel].Opresent->set_format ("enabled: %s"); + bx_options.ata[channel].Oioaddr1->set_format (", ioaddr1: 0x%x"); + bx_options.ata[channel].Oioaddr2->set_format (", ioaddr2: 0x%x"); + bx_options.ata[channel].Oirq->set_format (", irq: %d"); +#endif + bx_options.ata[channel].Oioaddr1->set_base (16); + bx_options.ata[channel].Oioaddr2->set_base (16); + + for (Bit8u slave=0; slave<2; slave++) { + + bx_options.atadevice[channel][slave].Opresent->set_ask_format ( + BX_WITH_WX? "Enable?" + : "Device is enabled: [%s] "); + bx_options.atadevice[channel][slave].Otype->set_ask_format ( + BX_WITH_WX? "Type of ATA device:" + : "Enter type of ATA device, disk or cdrom: [%s] "); + bx_options.atadevice[channel][slave].Opath->set_ask_format ( + BX_WITH_WX? "Path or physical device name:" + : "Enter new filename: [%s] "); + bx_options.atadevice[channel][slave].Ocylinders->set_ask_format ( + BX_WITH_WX? "Cylinders:" + : "Enter number of cylinders: [%d] "); + bx_options.atadevice[channel][slave].Oheads->set_ask_format ( + BX_WITH_WX? "Heads:" + : "Enter number of heads: [%d] "); + bx_options.atadevice[channel][slave].Ospt->set_ask_format ( + BX_WITH_WX? "Sectors per track:" + : "Enter number of sectors per track: [%d] "); + bx_options.atadevice[channel][slave].Ostatus->set_ask_format ( + BX_WITH_WX? "Inserted?" + : "Is the device inserted or ejected? [%s] "); + bx_options.atadevice[channel][slave].Omodel->set_ask_format ( + BX_WITH_WX? "Model name:" + : "Enter new model name: [%s]"); + bx_options.atadevice[channel][slave].Otranslation->set_ask_format ( + BX_WITH_WX? "Translation type:" + : "Enter translation type: [%s]"); + bx_options.atadevice[channel][slave].Obiosdetect->set_ask_format ( + BX_WITH_WX? "BIOS Detection:" + : "Enter bios detection type: [%s]"); + +#if !BX_WITH_WX + bx_options.atadevice[channel][slave].Opresent->set_format ("enabled: %s"); + bx_options.atadevice[channel][slave].Otype->set_format (", %s"); + bx_options.atadevice[channel][slave].Opath->set_format (" on '%s'"); + bx_options.atadevice[channel][slave].Ocylinders->set_format (", %d cylinders"); + bx_options.atadevice[channel][slave].Oheads->set_format (", %d heads"); + bx_options.atadevice[channel][slave].Ospt->set_format (", %d sectors/track"); + bx_options.atadevice[channel][slave].Ostatus->set_format (", %s"); + bx_options.atadevice[channel][slave].Omodel->set_format (", model '%s'"); + bx_options.atadevice[channel][slave].Otranslation->set_format (", translation '%s'"); + bx_options.atadevice[channel][slave].Obiosdetect->set_format (", biosdetect '%s'"); +#endif + + bx_options.atadevice[channel][slave].Otype->set_handler (bx_param_handler); + + bx_options.atadevice[channel][slave].Ostatus->set_handler (bx_param_handler); + bx_options.atadevice[channel][slave].Opath->set_handler (bx_param_string_handler); + } + } bx_options.OnewHardDriveSupport = new bx_param_bool_c (BXP_NEWHARDDRIVESUPPORT, "New hard drive support", @@ -515,9 +661,27 @@ bx_param_c *disk_menu_init_list[] = { SIM->get_param (BXP_FLOPPYA), SIM->get_param (BXP_FLOPPYB), - SIM->get_param (BXP_DISKC), - SIM->get_param (BXP_DISKD), - SIM->get_param (BXP_CDROMD), + //SIM->get_param (BXP_DISKC), + //SIM->get_param (BXP_DISKD), + //SIM->get_param (BXP_CDROMD), + SIM->get_param (BXP_ATA0), + SIM->get_param (BXP_ATA0_MASTER), + SIM->get_param (BXP_ATA0_SLAVE), +#if BX_MAX_ATA_CHANNEL>1 + SIM->get_param (BXP_ATA1), + SIM->get_param (BXP_ATA1_MASTER), + SIM->get_param (BXP_ATA1_SLAVE), +#endif +#if BX_MAX_ATA_CHANNEL>2 + SIM->get_param (BXP_ATA2), + SIM->get_param (BXP_ATA2_MASTER), + SIM->get_param (BXP_ATA2_SLAVE), +#endif +#if BX_MAX_ATA_CHANNEL>3 + SIM->get_param (BXP_ATA3), + SIM->get_param (BXP_ATA3_MASTER), + SIM->get_param (BXP_ATA3_SLAVE), +#endif SIM->get_param (BXP_NEWHARDDRIVESUPPORT), SIM->get_param (BXP_BOOTDRIVE), SIM->get_param (BXP_FLOPPYSIGCHECK), @@ -990,19 +1154,26 @@ bx_options.floppyb.Odevtype->reset(); bx_options.floppyb.Otype->reset(); bx_options.floppyb.Ostatus->reset(); - bx_options.diskc.Opresent->reset(); - bx_options.diskc.Opath->reset(); - bx_options.diskc.Ocylinders->reset(); - bx_options.diskc.Oheads->reset(); - bx_options.diskc.Ospt->reset(); - bx_options.diskd.Opresent->reset(); - bx_options.diskd.Opath->reset(); - bx_options.diskd.Ocylinders->reset(); - bx_options.diskd.Oheads->reset(); - bx_options.diskd.Ospt->reset(); - bx_options.cdromd.Opresent->reset(); - bx_options.cdromd.Opath->reset(); - bx_options.cdromd.Ostatus->reset(); + + for (Bit8u channel=0; channelreset(); + bx_options.ata[channel].Oioaddr1->reset(); + bx_options.ata[channel].Oioaddr2->reset(); + bx_options.ata[channel].Oirq->reset(); + + for (Bit8u slave=0; slave<2; slave++) { + bx_options.atadevice[channel][slave].Opresent->reset(); + bx_options.atadevice[channel][slave].Otype->reset(); + bx_options.atadevice[channel][slave].Opath->reset(); + bx_options.atadevice[channel][slave].Ocylinders->reset(); + bx_options.atadevice[channel][slave].Oheads->reset(); + bx_options.atadevice[channel][slave].Ospt->reset(); + bx_options.atadevice[channel][slave].Ostatus->reset(); + bx_options.atadevice[channel][slave].Omodel->reset(); + bx_options.atadevice[channel][slave].Obiosdetect->reset(); + bx_options.atadevice[channel][slave].Otranslation->reset(); + } + } bx_options.OnewHardDriveSupport->reset(); // boot & memory @@ -1822,7 +1993,168 @@ } } + else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) == 4)) { + Bit8u channel = params[0][3]; + + if ((channel < '0') || (channel > '9')) { + BX_PANIC(("%s: ataX directive malformed.", context)); + } + channel-='0'; + if (channel >= BX_MAX_ATA_CHANNEL) { + BX_PANIC(("%s: ataX directive malformed.", context)); + } + + if ((num_params < 2) || (num_params > 5)) { + BX_PANIC(("%s: ataX directive malformed.", context)); + } + + if (strncmp(params[1], "enabled=", 8)) { + BX_PANIC(("%s: ataX directive malformed.", context)); + } + else { + bx_options.ata[channel].Opresent->set (atol(¶ms[1][8])); + } + + if (num_params > 2) { + if (strncmp(params[2], "ioaddr1=", 8)) { + BX_PANIC(("%s: ataX directive malformed.", context)); + } + else { + if ( (params[2][8] == '0') && (params[2][9] == 'x') ) + bx_options.ata[channel].Oioaddr1->set (strtoul (¶ms[2][8], NULL, 16)); + else + bx_options.ata[channel].Oioaddr1->set (strtoul (¶ms[2][8], NULL, 10)); + } + } + + if (num_params > 3) { + if (strncmp(params[3], "ioaddr2=", 8)) { + BX_PANIC(("%s: ataX directive malformed.", context)); + } + else { + if ( (params[3][8] == '0') && (params[3][9] == 'x') ) + bx_options.ata[channel].Oioaddr2->set (strtoul (¶ms[3][8], NULL, 16)); + else + bx_options.ata[channel].Oioaddr2->set (strtoul (¶ms[3][8], NULL, 10)); + } + } + + if (num_params > 4) { + if (strncmp(params[4], "irq=", 4)) { + BX_PANIC(("%s: ataX directive malformed.", context)); + } + else { + bx_options.ata[channel].Oirq->set (atol(¶ms[4][4])); + } + } + } + + // ataX-master, ataX-slave + else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) > 4)) { + Bit8u channel = params[0][3], slave = 0; + + if ((channel < '0') || (channel > '9')) { + BX_PANIC(("%s: ataX-master/slave directive malformed.", context)); + } + channel-='0'; + if (channel >= BX_MAX_ATA_CHANNEL) { + BX_PANIC(("%s: ataX-master/slave directive malformed.", context)); + } + + if ((strcmp(¶ms[0][4], "-slave")) && + (strcmp(¶ms[0][4], "-master"))) { + BX_PANIC(("%s: ataX-master/slave directive malformed.", context)); + } + + if (!strcmp(¶ms[0][4], "-slave")) { + slave = 1; + } + + if (bx_options.atadevice[channel][slave].Opresent->get()) { + BX_PANIC(("%s: %s device of ata channel %d already defined.", context, slave?"slave":"master",channel)); + } + + for (i=1; iset (BX_ATA_DEVICE_DISK); + } + else if (!strcmp(params[i], "type=cdrom")) { + bx_options.atadevice[channel][slave].Otype->set (BX_ATA_DEVICE_CDROM); + } + else if (!strncmp(params[i], "path=", 5)) { + bx_options.atadevice[channel][slave].Opath->set (¶ms[i][5]); + } + else if (!strncmp(params[i], "cylinders=", 10)) { + bx_options.atadevice[channel][slave].Ocylinders->set (atol(¶ms[i][10])); + } + else if (!strncmp(params[i], "heads=", 6)) { + bx_options.atadevice[channel][slave].Oheads->set (atol(¶ms[i][6])); + } + else if (!strncmp(params[i], "spt=", 4)) { + bx_options.atadevice[channel][slave].Ospt->set (atol(¶ms[i][4])); + } + else if (!strncmp(params[i], "model=", 6)) { + bx_options.atadevice[channel][slave].Omodel->set(¶ms[i][6]); + } + else if (!strcmp(params[i], "biosdetect=none")) { + bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_NONE); + } + else if (!strcmp(params[i], "biosdetect=cmos")) { + bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_CMOS); + } + else if (!strcmp(params[i], "biosdetect=auto")) { + bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_AUTO); + } + else if (!strcmp(params[i], "translation=none")) { + bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_NONE); + } + else if (!strcmp(params[i], "translation=lba")) { + bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_LBA); + } + else if (!strcmp(params[i], "translation=large")) { + bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_LARGE); + } + else if (!strcmp(params[i], "status=ejected")) { + bx_options.atadevice[channel][slave].Ostatus->set(BX_EJECTED); + } + else if (!strcmp(params[i], "status=inserted")) { + bx_options.atadevice[channel][slave].Ostatus->set(BX_INSERTED); + } + else { + BX_PANIC(("%s: ataX-master/slave directive malformed.", context)); + } + } + + // Enables the ata device + bx_options.atadevice[channel][slave].Opresent->set(1); + + // if enabled check if device ok + if (bx_options.atadevice[channel][slave].Opresent->get() == 1) { + if (bx_options.atadevice[channel][slave].Otype->get() == BX_ATA_DEVICE_DISK) { + if ((strlen(bx_options.atadevice[channel][slave].Opath->getptr()) ==0) || + (bx_options.atadevice[channel][slave].Ocylinders->get() == 0) || + (bx_options.atadevice[channel][slave].Oheads->get() ==0 ) || + (bx_options.atadevice[channel][slave].Ospt->get() == 0)) { + BX_PANIC(("%s: ataX-master/slave directive malformed.", context)); + } + } + else if (bx_options.atadevice[channel][slave].Otype->get() == BX_ATA_DEVICE_CDROM) { + if (strlen(bx_options.atadevice[channel][slave].Opath->getptr()) == 0) { + BX_PANIC(("%s: ataX-master/slave directive malformed.", context)); + } + } + else { + BX_PANIC(("%s: ataX-master/slave: type sould be specified ", context)); + } + } + + } + + // Legacy disk options emulation else if (!strcmp(params[0], "diskc")) { + if (bx_options.atadevice[0][0].Opresent->get()) { + BX_PANIC(("%s: master device of ata channel 0 already defined.", context)); + } if (num_params != 5) { BX_PANIC(("%s: diskc directive malformed.", context)); } @@ -1832,13 +2164,18 @@ strncmp(params[4], "spt=", 4)) { BX_PANIC(("%s: diskc directive malformed.", context)); } - bx_options.diskc.Opath->set (¶ms[1][5]); - bx_options.diskc.Ocylinders->set (atol(¶ms[2][4])); - bx_options.diskc.Oheads->set (atol(¶ms[3][6])); - bx_options.diskc.Ospt->set (atol(¶ms[4][4])); - bx_options.diskc.Opresent->set (1); + bx_options.ata[0].Opresent->set(1); + bx_options.atadevice[0][0].Otype->set (BX_ATA_DEVICE_DISK); + bx_options.atadevice[0][0].Opath->set (¶ms[1][5]); + bx_options.atadevice[0][0].Ocylinders->set (atol(¶ms[2][4])); + bx_options.atadevice[0][0].Oheads->set (atol(¶ms[3][6])); + bx_options.atadevice[0][0].Ospt->set (atol(¶ms[4][4])); + bx_options.atadevice[0][0].Opresent->set (1); } else if (!strcmp(params[0], "diskd")) { + if (bx_options.atadevice[0][1].Opresent->get()) { + BX_PANIC(("%s: slave device of ata channel 0 already defined.", context)); + } if (num_params != 5) { BX_PANIC(("%s: diskd directive malformed.", context)); } @@ -1848,11 +2185,47 @@ strncmp(params[4], "spt=", 4)) { BX_PANIC(("%s: diskd directive malformed.", context)); } - bx_options.diskd.Opath->set (¶ms[1][5]); - bx_options.diskd.Ocylinders->set (atol( ¶ms[2][4])); - bx_options.diskd.Oheads->set (atol( ¶ms[3][6] )); - bx_options.diskd.Ospt->set (atol( ¶ms[4][4] )); - bx_options.diskd.Opresent->set (1); + bx_options.ata[0].Opresent->set(1); + bx_options.atadevice[0][1].Otype->set (BX_ATA_DEVICE_DISK); + bx_options.atadevice[0][1].Opath->set (¶ms[1][5]); + bx_options.atadevice[0][1].Ocylinders->set (atol( ¶ms[2][4])); + bx_options.atadevice[0][1].Oheads->set (atol( ¶ms[3][6])); + bx_options.atadevice[0][1].Ospt->set (atol( ¶ms[4][4])); + bx_options.atadevice[0][1].Opresent->set (1); + } + else if (!strcmp(params[0], "cdromd")) { + if (bx_options.atadevice[0][1].Opresent->get()) { + BX_PANIC(("%s: slave device of ata channel 0 already defined.", context)); + } + if (num_params != 3) { + BX_PANIC(("%s: cdromd directive malformed.", context)); + } + if (strncmp(params[1], "dev=", 4) || strncmp(params[2], "status=", 7)) { + BX_PANIC(("%s: cdromd directive malformed.", context)); + } + bx_options.ata[0].Opresent->set(1); + bx_options.atadevice[0][1].Otype->set (BX_ATA_DEVICE_CDROM); + bx_options.atadevice[0][1].Opath->set (¶ms[1][4]); + if (!strcmp(params[2], "status=inserted")) + bx_options.atadevice[0][1].Ostatus->set (BX_INSERTED); + else if (!strcmp(params[2], "status=ejected")) + bx_options.atadevice[0][1].Ostatus->set (BX_EJECTED); + else { + BX_PANIC(("%s: cdromd directive malformed.", context)); + } + bx_options.atadevice[0][1].Opresent->set (1); + } + + else if (!strcmp(params[0], "boot")) { + if (!strcmp(params[1], "a")) { + bx_options.Obootdrive->set (BX_BOOT_FLOPPYA); + } else if (!strcmp(params[1], "c")) { + bx_options.Obootdrive->set (BX_BOOT_DISKC); + } else if (!strcmp(params[1], "cdrom")) { + bx_options.Obootdrive->set (BX_BOOT_CDROM); + } else { + BX_PANIC(("%s: boot directive with unknown boot device '%s'. use 'a', 'c' or 'cdrom'.", context, params[1])); + } } else if (!strcmp(params[0], "com1")) { @@ -1914,35 +2287,6 @@ } #endif - else if (!strcmp(params[0], "cdromd")) { - if (num_params != 3) { - BX_PANIC(("%s: cdromd directive malformed.", context)); - } - if (strncmp(params[1], "dev=", 4) || strncmp(params[2], "status=", 7)) { - BX_PANIC(("%s: cdromd directive malformed.", context)); - } - bx_options.cdromd.Opath->set (¶ms[1][4]); - if (!strcmp(params[2], "status=inserted")) - bx_options.cdromd.Ostatus->set (BX_INSERTED); - else if (!strcmp(params[2], "status=ejected")) - bx_options.cdromd.Ostatus->set (BX_EJECTED); - else { - BX_PANIC(("%s: cdromd directive malformed.", context)); - } - bx_options.cdromd.Opresent->set (1); - } - - else if (!strcmp(params[0], "boot")) { - if (!strcmp(params[1], "a")) { - bx_options.Obootdrive->set (BX_BOOT_FLOPPYA); - } else if (!strcmp(params[1], "c")) { - bx_options.Obootdrive->set (BX_BOOT_DISKC); - } else if (!strcmp(params[1], "cdrom")) { - bx_options.Obootdrive->set (BX_BOOT_CDROM); - } else { - BX_PANIC(("%s: boot directive with unknown boot device '%s'. use 'a', 'c' or 'cdrom'.", context, params[1])); - } - } else if (!strcmp(params[0], "floppy_bootsig_check")) { if (num_params != 2) { BX_PANIC(("%s: floppy_bootsig_check directive malformed.", context)); @@ -2503,15 +2847,11 @@ if(!strncmp(params[1], "keys=", 4)) { bx_options.Ouser_shortcut->set (strdup(¶ms[1][5])); } - } - - + } else { BX_PANIC(( "%s: directive '%s' not understood", context, params[0])); } - if (bx_options.diskd.Opresent->get () && bx_options.cdromd.Opresent->get ()) - BX_PANIC(("At present, using both diskd and cdromd at once is not supported.")); } static char *fdtypes[] = { @@ -2536,32 +2876,64 @@ } int -bx_write_disk_options (FILE *fp, int drive, bx_disk_options *opt) +bx_write_ata_options (FILE *fp, Bit8u channel, bx_ata_options *opt) { - if (!opt->Opresent->get ()) { - fprintf (fp, "# no disk%c\n", (char)'c'+drive); - return 0; - } - fprintf (fp, "disk%c: file=\"%s\", cyl=%d, heads=%d, spt=%d\n", - (char)'c'+drive, - opt->Opath->getptr (), - opt->Ocylinders->get (), - opt->Oheads->get (), - opt->Ospt->get ()); + fprintf (fp, "ata%d: enabled=%d", channel, opt->Opresent->get()); + + if (opt->Opresent->get()) { + fprintf (fp, ", ioaddr1=0x%x, ioaddr2=0x%x, irq=%d", opt->Oioaddr1->get(), + opt->Oioaddr2->get(), opt->Oirq->get()); + } + + fprintf (fp, "\n"); return 0; } int -bx_write_cdrom_options (FILE *fp, int drive, bx_cdrom_options *opt) +bx_write_atadevice_options (FILE *fp, Bit8u channel, Bit8u drive, bx_atadevice_options *opt) { - BX_ASSERT (drive == 0); - if (!opt->Opresent->get ()) { - fprintf (fp, "# no cdromd\n"); - return 0; + if (opt->Opresent->get()) { + fprintf (fp, "ata%d-%s: ", channel, drive==0?"master":"slave"); + + if (opt->Otype->get() == BX_ATA_DEVICE_DISK) { + fprintf (fp, "type=disk, path=\"%s\", cylinders=%d, heads=%d, spt=%d", + opt->Opath->getptr(), opt->Ocylinders->get(), opt->Oheads->get(), opt->Ospt->get()); + + switch(opt->Otranslation->get()) { + case BX_ATA_TRANSLATION_NONE: + fprintf (fp, ", translation=none"); + break; + case BX_ATA_TRANSLATION_LBA: + fprintf (fp, ", translation=lba"); + break; + case BX_ATA_TRANSLATION_LARGE: + fprintf (fp, ", translation=large"); + break; + } + } + else if (opt->Otype->get() == BX_ATA_DEVICE_CDROM) { + fprintf (fp, "type=cdrom, path=\"%s\", status=%s", + opt->Opath->getptr(), + opt->Ostatus->get ()==BX_EJECTED ? "ejected" : "inserted"); + } + + switch(opt->Obiosdetect->get()) { + case BX_ATA_BIOSDETECT_NONE: + fprintf (fp, ", biosdetect=none"); + break; + case BX_ATA_BIOSDETECT_CMOS: + fprintf (fp, ", biosdetect=cmos"); + break; + case BX_ATA_BIOSDETECT_AUTO: + fprintf (fp, ", biosdetect=auto"); + break; + } + if (strlen(opt->Omodel->getptr())>0) { + fprintf (fp, ", model=\"%s\"", opt->Omodel->getptr()); + } + + fprintf (fp, "\n"); } - fprintf (fp, "cdromd: dev=%s, status=%s\n", - opt->Opath->getptr (), - opt->Ostatus->get ()==BX_INSERTED ? "inserted" : "ejected"); return 0; } @@ -2682,9 +3054,11 @@ // the structs like bx_floppy_options::print or something. bx_write_floppy_options (fp, 0, &bx_options.floppya); bx_write_floppy_options (fp, 1, &bx_options.floppyb); - bx_write_disk_options (fp, 0, &bx_options.diskc); - bx_write_disk_options (fp, 1, &bx_options.diskd); - bx_write_cdrom_options (fp, 0, &bx_options.cdromd); + for (Bit8u channel=0; channelgetptr ()) > 0) fprintf (fp, "romimage: file=%s, address=0x%05x\n", bx_options.rom.Opath->getptr(), (unsigned int)bx_options.rom.Oaddress->get ()); else Index: .bochsrc =================================================================== RCS file: /cvsroot/bochs/bochs/.bochsrc,v retrieving revision 1.48 diff -u -r1.48 .bochsrc --- .bochsrc 20 Sep 2002 13:23:45 -0000 1.48 +++ .bochsrc 22 Sep 2002 20:46:06 -0000 @@ -84,6 +84,79 @@ floppyb: 1_44=b.img, status=inserted #======================================================================= +# ATA[0-3]: enabled=[0|1], ioaddr1=, ioaddr2=, irq= +# +# These options enables up to 4 ata channels. For each channel +# the two base io address and the irq must be specified. +# +# ata0 is enabled by default, with ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +# +# Examples: +# ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +# ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +# ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e8, irq=12 +# ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x368, irq=11 +#======================================================================= +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e8, irq=12 +ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x368, irq=11 + +#======================================================================= +# +# ATA[0-3]-MASTER: +# ATA[0-3]-SLAVE: +# +# This defines the type and characteristics of all attached ata devices: +# type= type of attached device [disk|cdrom] +# path= path of the image +# cylinders= only valid for disks +# heads= only valid for disks +# spt= only valid for disks +# status= only valid for cdroms [inserted|ejected] +# biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos] +# translation=type of transation of the bios, only for disks [none|lba|large] +# model= string returned by identify device command +# +# Point this at a 10M, 20M, or 30M hard disk image file, cdrom iso file, +# or physical cdrom device. +# To create # a hard disk image, try running bximage. +# It will help you choose the size and then suggest a line that +# works with it. +# +# In UNIX it may be possible to use a raw device as a Bochs hard disk, +# but WE DON'T RECOMMEND IT. In Windows there is no easy way. +# +# In windows, the drive letter + colon notation should be used for cdroms. +# Depending on versions of windows and drivers, you may only be able to +# access the "first" cdrom in the system. +# +# The path, cylinders, heads, and spt are mandatory for type=disk +# The path is mandatory for type=cdrom +# +# Default values are: +# biosdetect=auto, translation=lba, model="Generic 1234" +# +# The biosdetect and translation options have currently no effect on the bios +# +# Examples: +# ata0-master: type=disk, path=10M.sample, cylinders=306, heads=4, spt=17 +# ata0-slave: type=disk, path=20M.sample, cylinders=615, heads=4, spt=17 +# ata1-master: type=disk, path=30M.sample, cylinders=615, heads=6, spt=17 +# ata1-slave: type=disk, path=46M.sample, cylinders=940, heads=6, spt=17 +# ata2-master: type=disk, path=62M.sample, cylinders=940, heads=8, spt=17 +# ata2-slave: type=disk, path=112M.sample, cylinders=900, heads=15, spt=17 +# ata3-master: type=disk, path=483M.sample, cylinders=1024, heads=15, spt=63 +# ata3-slave: type=cdrom, path=iso.sample, status=inserted +#======================================================================= +ata0-master: type=disk, path="30M.sample", cylinders=615, heads=6, spt=17 +#ata0-slave: dev=D:, status=inserted # for win32 +#ata0-slave: dev=/dev/cdrom, status=inserted + +#======================================================================= +# +# The DISKC option is deprecated. Use ATA* options instead. +# # DISKC: file=, cyl=, heads=, spt= # Point this at a 10M, 20M, or 30M hard disk image file. To create # a hard disk image, try running bximage. It will help you choose the @@ -101,9 +174,12 @@ # diskc: file=112M.sample, cyl=900, heads=15, spt=17 # diskc: file=483M.sample, cyl=1024, heads=15, spt=63 #======================================================================= -diskc: file="30M.sample", cyl=615, heads=6, spt=17 +#diskc: file="30M.sample", cyl=615, heads=6, spt=17 #======================================================================= +# +# The DISKD option is deprecated. Use ATA* options instead. +# # DISKD: # See DISKC above for syntax # @@ -112,7 +188,10 @@ #diskd: file="diskd.img", cyl=615, heads=6, spt=17 #======================================================================= -# CDROM +# +# The CDROMD option is deprecated. Use ATA* options instead. +# +# CDROMD: # # cdromd: dev=/dev/cdrom, status=inserted # cdromd: dev=/dev/cdrom, status=ejected Index: gui/control.cc =================================================================== RCS file: /cvsroot/bochs/bochs/gui/control.cc,v retrieving revision 1.61 diff -u -r1.61 control.cc --- gui/control.cc 20 Sep 2002 18:14:27 -0000 1.61 +++ gui/control.cc 22 Sep 2002 20:46:07 -0000 @@ -302,19 +302,22 @@ "---------------------\n" "1. Floppy disk 0: %s\n" "2. Floppy disk 1: %s\n" -"3. CDROM: %s\n" -"4. (not implemented)\n" -"5. Log options for all devices\n" -"6. Log options for individual devices\n" -"7. VGA Update Interval: %d\n" -"8. Mouse: %s\n" -"9. Keyboard paste delay: %d\n" -"10. Userbutton shortcut: %s\n" -"11. Instruction tracing: off (doesn't exist yet)\n" -"12. Continue simulation\n" -"13. Quit now\n" +"3. 1st CDROM: %s\n" +"4. 2nd CDROM: %s\n" +"5. 3rd CDROM: %s\n" +"6. 4th CDROM: %s\n" +"7. (not implemented)\n" +"8. Log options for all devices\n" +"9. Log options for individual devices\n" +"10. VGA Update Interval: %d\n" +"11. Mouse: %s\n" +"12. Keyboard paste delay: %d\n" +"13. Userbutton shortcut: %s\n" +"14. Instruction tracing: off (doesn't exist yet)\n" +"15. Continue simulation\n" +"16. Quit now\n" "\n" -"Please choose one: [12] "; +"Please choose one: [15] "; char *menu_prompt_list[BX_CI_N_MENUS] = { NULL, @@ -338,9 +341,9 @@ void build_runtime_options_prompt (char *format, char *buf, int size) { bx_floppy_options floppyop; - bx_cdrom_options cdromop; + bx_atadevice_options cdromop; /* bx_param_num_c *ips = SIM->get_param_num (BXP_IPS); */ - char buffer[3][128]; + char buffer[6][128]; for (int i=0; i<2; i++) { SIM->get_floppy_options (i, &floppyop); if (floppyop.Odevtype->get () == BX_FLOPPY_NONE) @@ -352,14 +355,20 @@ if (!floppyop.Opath->getptr ()[0]) strcpy (buffer[i], "none"); } } - SIM->get_cdrom_options (0, &cdromop); - if (!cdromop.Opresent->get ()) - sprintf (buffer[2], "(not present)"); - else - sprintf (buffer[2], "%s, %s", - cdromop.Opath->getptr (), - (cdromop.Ostatus->get () == BX_INSERTED)? "inserted" : "ejected"); + + // 4 cdroms supported at run time + int device; + for (Bit8u cdrom=0; cdrom<4; cdrom++) { + if (!SIM->get_cdrom_options (cdrom, &cdromop, &device) || !cdromop.Opresent->get ()) + sprintf (buffer[2+cdrom], "(not present)"); + else + sprintf (buffer[2+cdrom], "(%s on ata%d) %s, %s", + device&1?"slave":"master", device/2, cdromop.Opath->getptr (), + (cdromop.Ostatus->get () == BX_INSERTED)? "inserted" : "ejected"); + } + snprintf (buf, size, format, buffer[0], buffer[1], buffer[2], + buffer[3], buffer[4], buffer[5], /* ips->get (), */ SIM->get_param_num (BXP_VGA_UPDATE_INTERVAL)->get (), SIM->get_param_num (BXP_MOUSE_ENABLED)->get () ? "enabled" : "disabled", @@ -452,9 +461,9 @@ case BX_CI_RUNTIME: char prompt[1024]; bx_floppy_options floppyop; - bx_cdrom_options cdromop; + bx_atadevice_options cdromop; build_runtime_options_prompt (runtime_menu_prompt, prompt, 1024); - if (ask_uint (prompt, 1, 13, 12, &choice, 10) < 0) return -1; + if (ask_uint (prompt, 1, 16, 15, &choice, 10) < 0) return -1; switch (choice) { case 1: SIM->get_floppy_options (0, &floppyop); @@ -465,22 +474,31 @@ if (floppyop.Odevtype->get () != BX_FLOPPY_NONE) do_menu (BXP_FLOPPYB); break; case 3: - SIM->get_cdrom_options (0, &cdromop); - if (cdromop.Opresent->get ()) do_menu (BXP_CDROMD); + case 4: + case 5: + case 6: + int device; + if (SIM->get_cdrom_options (choice - 3, &cdromop, &device) && cdromop.Opresent->get ()) { + // disable type selection + SIM->get_param((bx_id)(BXP_ATA0_MASTER_TYPE + device))->set_enabled(0); + SIM->get_param((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled(0); + SIM->get_param((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled(0); + do_menu ((bx_id)(BXP_ATA0_MASTER + device)); + } break; - case 4: // not implemented yet because I would have to mess with + case 7: // not implemented yet because I would have to mess with // resetting timers and pits and everything on the fly. // askparam (BXP_IPS); break; - case 5: bx_log_options (0); break; - case 6: bx_log_options (1); break; - case 7: askparam (BXP_VGA_UPDATE_INTERVAL); break; - case 8: askparam (BXP_MOUSE_ENABLED); break; - case 9: askparam (BXP_KBD_PASTE_DELAY); break; - case 10: askparam (BXP_USER_SHORTCUT); break; - case 11: NOT_IMPLEMENTED (choice); break; - case 12: fprintf (stderr, "Continuing simulation\n"); return 0; - case 13: + case 8: bx_log_options (0); break; + case 9: bx_log_options (1); break; + case 10: askparam (BXP_VGA_UPDATE_INTERVAL); break; + case 11: askparam (BXP_MOUSE_ENABLED); break; + case 12: askparam (BXP_KBD_PASTE_DELAY); break; + case 13: askparam (BXP_USER_SHORTCUT); break; + case 14: NOT_IMPLEMENTED (choice); break; + case 15: fprintf (stderr, "Continuing simulation\n"); return 0; + case 16: fprintf (stderr, "You chose quit on the configuration interface.\n"); SIM->quit_sim (1); return -1; Index: gui/gui.cc =================================================================== RCS file: /cvsroot/bochs/bochs/gui/gui.cc,v retrieving revision 1.48 diff -u -r1.48 gui.cc --- gui/gui.cc 21 Sep 2002 19:38:47 -0000 1.48 +++ gui/gui.cc 22 Sep 2002 20:46:07 -0000 @@ -108,9 +108,9 @@ BX_GRAVITY_LEFT, floppyB_handler); // CDROM - BX_GUI_THIS cdromD_status = - bx_devices.hard_drive->get_cd_media_status() - && bx_options.cdromd.Opresent->get (); + Bit32u handle = bx_devices.hard_drive->get_first_cd_handle(); + BX_GUI_THIS cdromD_status = bx_devices.hard_drive->get_cd_media_status(handle); + if (BX_GUI_THIS cdromD_status) BX_GUI_THIS cdromD_hbar_id = headerbar_bitmap(BX_GUI_THIS cdromD_bmap_id, BX_GRAVITY_LEFT, cdromD_handler); @@ -162,9 +162,8 @@ BX_GUI_THIS floppyB_status = bx_devices.floppy->get_media_status (1) && bx_options.floppyb.Ostatus->get (); - BX_GUI_THIS cdromD_status = - bx_devices.hard_drive->get_cd_media_status() - && bx_options.cdromd.Opresent->get (); + Bit32u handle = bx_devices.hard_drive->get_first_cd_handle(); + BX_GUI_THIS cdromD_status = bx_devices.hard_drive->get_cd_media_status(handle); if (BX_GUI_THIS floppyA_status) replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_bmap_id); else { @@ -243,22 +242,29 @@ void bx_gui_c::cdromD_handler(void) { + Bit32u handle = bx_devices.hard_drive->get_first_cd_handle(); #if BX_WITH_WX // instead of just toggling the status, call wxWindows to bring up // a dialog asking what disk image you want to switch to. - int ret = SIM->ask_param (BXP_CDROM_PATH); + // BBD: for now, find the first cdrom and call ask_param on that. + // Since we could have multiple cdroms now, maybe we should be adding + // one cdrom button for each? + bx_param_c *cdrom = SIM->get_first_cdrom (); + if (cdrom == NULL) + return; // no cdrom found + int ret = SIM->ask_param (cdrom->get_id ()); if (ret < 0) return; // cancelled // eject and then insert the disk. If the new path is invalid, // the status will return 0. - unsigned status = bx_devices.hard_drive->set_cd_media_status(0); + unsigned status = bx_devices.hard_drive->set_cd_media_status(handle, 0); printf ("eject disk, new_status is %d\n", status); - status = bx_devices.hard_drive->set_cd_media_status(1); + status = bx_devices.hard_drive->set_cd_media_status(handle, 1); printf ("insert disk, new_status is %d\n", status); fflush (stdout); BX_GUI_THIS cdromD_status = status; #else BX_GUI_THIS cdromD_status = - bx_devices.hard_drive->set_cd_media_status(!BX_GUI_THIS cdromD_status); + bx_devices.hard_drive->set_cd_media_status(handle, !BX_GUI_THIS cdromD_status); #endif BX_GUI_THIS update_drive_status_buttons (); } Index: gui/siminterface.h =================================================================== RCS file: /cvsroot/bochs/bochs/gui/siminterface.h,v retrieving revision 1.69 diff -u -r1.69 siminterface.h --- gui/siminterface.h 20 Sep 2002 17:56:22 -0000 1.69 +++ gui/siminterface.h 22 Sep 2002 20:46:08 -0000 @@ -128,12 +128,12 @@ BXP_ROM_ADDRESS, BXP_VGA_ROM_PATH, BXP_OPTROM1_PATH, - BXP_OPTROM1_ADDRESS, BXP_OPTROM2_PATH, - BXP_OPTROM2_ADDRESS, BXP_OPTROM3_PATH, - BXP_OPTROM3_ADDRESS, BXP_OPTROM4_PATH, + BXP_OPTROM1_ADDRESS, + BXP_OPTROM2_ADDRESS, + BXP_OPTROM3_ADDRESS, BXP_OPTROM4_ADDRESS, BXP_KBD_SERIAL_DELAY, BXP_KBD_PASTE_DELAY, @@ -149,18 +149,114 @@ BXP_FLOPPYB_TYPE, BXP_FLOPPYB_STATUS, BXP_FLOPPYB, - BXP_DISKC_PRESENT, - BXP_DISKC_PATH, - BXP_DISKC_CYLINDERS, - BXP_DISKC_HEADS, - BXP_DISKC_SPT, - BXP_DISKC, - BXP_DISKD_PRESENT, - BXP_DISKD_PATH, - BXP_DISKD_CYLINDERS, - BXP_DISKD_HEADS, - BXP_DISKD_SPT, - BXP_DISKD, + BXP_ATA0, + BXP_ATA1, + BXP_ATA2, + BXP_ATA3, + BXP_ATA0_PRESENT, + BXP_ATA1_PRESENT, + BXP_ATA2_PRESENT, + BXP_ATA3_PRESENT, + BXP_ATA0_IOADDR1, + BXP_ATA1_IOADDR1, + BXP_ATA2_IOADDR1, + BXP_ATA3_IOADDR1, + BXP_ATA0_IOADDR2, + BXP_ATA1_IOADDR2, + BXP_ATA2_IOADDR2, + BXP_ATA3_IOADDR2, + BXP_ATA0_IRQ, + BXP_ATA1_IRQ, + BXP_ATA2_IRQ, + BXP_ATA3_IRQ, + BXP_ATA0_MASTER, + BXP_ATA0_SLAVE, + BXP_ATA1_MASTER, + BXP_ATA1_SLAVE, + BXP_ATA2_MASTER, + BXP_ATA2_SLAVE, + BXP_ATA3_MASTER, + BXP_ATA3_SLAVE, + BXP_ATA0_MASTER_PRESENT, + BXP_ATA0_SLAVE_PRESENT, + BXP_ATA1_MASTER_PRESENT, + BXP_ATA1_SLAVE_PRESENT, + BXP_ATA2_MASTER_PRESENT, + BXP_ATA2_SLAVE_PRESENT, + BXP_ATA3_MASTER_PRESENT, + BXP_ATA3_SLAVE_PRESENT, + BXP_ATA0_MASTER_TYPE, + BXP_ATA0_SLAVE_TYPE, + BXP_ATA1_MASTER_TYPE, + BXP_ATA1_SLAVE_TYPE, + BXP_ATA2_MASTER_TYPE, + BXP_ATA2_SLAVE_TYPE, + BXP_ATA3_MASTER_TYPE, + BXP_ATA3_SLAVE_TYPE, + BXP_ATA0_MASTER_PATH, + BXP_ATA0_SLAVE_PATH, + BXP_ATA1_MASTER_PATH, + BXP_ATA1_SLAVE_PATH, + BXP_ATA2_MASTER_PATH, + BXP_ATA2_SLAVE_PATH, + BXP_ATA3_MASTER_PATH, + BXP_ATA3_SLAVE_PATH, + BXP_ATA0_MASTER_CYLINDERS, + BXP_ATA0_SLAVE_CYLINDERS, + BXP_ATA1_MASTER_CYLINDERS, + BXP_ATA1_SLAVE_CYLINDERS, + BXP_ATA2_MASTER_CYLINDERS, + BXP_ATA2_SLAVE_CYLINDERS, + BXP_ATA3_MASTER_CYLINDERS, + BXP_ATA3_SLAVE_CYLINDERS, + BXP_ATA0_MASTER_HEADS, + BXP_ATA0_SLAVE_HEADS, + BXP_ATA1_MASTER_HEADS, + BXP_ATA1_SLAVE_HEADS, + BXP_ATA2_MASTER_HEADS, + BXP_ATA2_SLAVE_HEADS, + BXP_ATA3_MASTER_HEADS, + BXP_ATA3_SLAVE_HEADS, + BXP_ATA0_MASTER_SPT, + BXP_ATA0_SLAVE_SPT, + BXP_ATA1_MASTER_SPT, + BXP_ATA1_SLAVE_SPT, + BXP_ATA2_MASTER_SPT, + BXP_ATA2_SLAVE_SPT, + BXP_ATA3_MASTER_SPT, + BXP_ATA3_SLAVE_SPT, + BXP_ATA0_MASTER_STATUS, + BXP_ATA0_SLAVE_STATUS, + BXP_ATA1_MASTER_STATUS, + BXP_ATA1_SLAVE_STATUS, + BXP_ATA2_MASTER_STATUS, + BXP_ATA2_SLAVE_STATUS, + BXP_ATA3_MASTER_STATUS, + BXP_ATA3_SLAVE_STATUS, + BXP_ATA0_MASTER_MODEL, + BXP_ATA0_SLAVE_MODEL, + BXP_ATA1_MASTER_MODEL, + BXP_ATA1_SLAVE_MODEL, + BXP_ATA2_MASTER_MODEL, + BXP_ATA2_SLAVE_MODEL, + BXP_ATA3_MASTER_MODEL, + BXP_ATA3_SLAVE_MODEL, + BXP_ATA0_MASTER_BIOSDETECT, + BXP_ATA0_SLAVE_BIOSDETECT, + BXP_ATA1_MASTER_BIOSDETECT, + BXP_ATA1_SLAVE_BIOSDETECT, + BXP_ATA2_MASTER_BIOSDETECT, + BXP_ATA2_SLAVE_BIOSDETECT, + BXP_ATA3_MASTER_BIOSDETECT, + BXP_ATA3_SLAVE_BIOSDETECT, + BXP_ATA0_MASTER_TRANSLATION, + BXP_ATA0_SLAVE_TRANSLATION, + BXP_ATA1_MASTER_TRANSLATION, + BXP_ATA1_SLAVE_TRANSLATION, + BXP_ATA2_MASTER_TRANSLATION, + BXP_ATA2_SLAVE_TRANSLATION, + BXP_ATA3_MASTER_TRANSLATION, + BXP_ATA3_SLAVE_TRANSLATION, #define BXP_PARAMS_PER_SERIAL_PORT 2 BXP_COM1_ENABLED, BXP_COM1_PATH, @@ -170,10 +266,6 @@ BXP_COM3_PATH, BXP_COM4_ENABLED, BXP_COM4_PATH, - BXP_CDROM_PRESENT, - BXP_CDROM_PATH, - BXP_CDROM_STATUS, - BXP_CDROMD, BXP_PRIVATE_COLORMAP, BXP_FULLSCREEN, BXP_SCREENMODE, @@ -670,11 +762,12 @@ char *get_name () { return name; } char *get_description () { return description; } int get_enabled () { return enabled; } - void set_enabled (int enabled) { this->enabled = enabled; } + virtual void set_enabled (int enabled) { this->enabled = enabled; } void reset () {} int getint () {return -1;} static const char* set_default_format (const char *f); static const char *get_default_format () { return default_text_format; } + virtual bx_list_c *get_dependent_list () { return NULL; } #if BX_UI_TEXT virtual void text_print (FILE *fp) {} virtual int text_ask (FILE *fpin, FILE *fpout) {return -1;} @@ -709,14 +802,16 @@ Bit32s min, Bit32s max, Bit32s initial_val); void reset (); void set_handler (param_event_handler handler); - bx_list_c *get_dependent_list () { return dependent_list; } + virtual bx_list_c *get_dependent_list () { return dependent_list; } void set_dependent_list (bx_list_c *l) { dependent_list = l; update_dependents (); } + virtual void set_enabled (int enabled); virtual Bit32s get (); virtual void set (Bit32s val); void set_base (int base) { this->base = base; } + void set_initial_val (Bit32s initial_val) { this->val.number = this->initial_val = initial_val;} int get_base () { return base; } Bit32s get_min () { return min; } Bit32s get_max () { return max; } @@ -897,13 +992,16 @@ bx_list_c (bx_id id, char *name, char *description, bx_param_c **init_list); bx_list_c (bx_id id, char *name, char *description, int maxsize); virtual ~bx_list_c(); + bx_list_c *clone (); void add (bx_param_c *param); bx_param_c *get (int index); int get_size () { return size; } bx_param_num_c *get_options () { return options; } + void set_options (bx_param_num_c *newopt) { options = newopt; } bx_param_num_c *get_choice () { return choice; } bx_param_string_c *get_title () { return title; } - void set_parent (bx_param_c *parent); + void set_parent (bx_param_c *newparent) { parent = newparent; } + bx_param_c *get_parent () { return parent; } #if BX_UI_TEXT virtual void text_print (FILE *); virtual int text_ask (FILE *fpin, FILE *fpout); @@ -922,6 +1020,19 @@ #define BX_FLOPPY_LAST 15 // last legal value of floppy type #define BX_FLOPPY_GUESS 20 // decide based on image size +#define BX_ATA_DEVICE_DISK 0 +#define BX_ATA_DEVICE_CDROM 1 +#define BX_ATA_DEVICE_LAST 1 + +#define BX_ATA_BIOSDETECT_NONE 0 +#define BX_ATA_BIOSDETECT_AUTO 1 +#define BX_ATA_BIOSDETECT_CMOS 2 + +#define BX_ATA_TRANSLATION_NONE 0 +#define BX_ATA_TRANSLATION_LBA 1 +#define BX_ATA_TRANSLATION_LARGE 2 +#define BX_ATA_TRANSLATION_LAST 2 + extern char *floppy_type_names[]; extern int floppy_type_n_sectors[]; extern int n_floppy_type_names; @@ -933,6 +1044,14 @@ extern int n_loader_os_names; extern char *keyboard_type_names[]; extern int n_keyboard_type_names; +extern char *atadevice_type_names[]; +extern int n_atadevice_type_names; +extern char *atadevice_status_names[]; +extern int n_atadevice_status_names; +extern char *atadevice_biosdetect_names[]; +extern int n_atadevice_biosdetect_names; +extern char *atadevice_translation_names[]; +extern int n_atadevice_translation_names; typedef struct { bx_param_enum_c *Odevtype; @@ -942,25 +1061,24 @@ } bx_floppy_options; typedef struct { + bx_list_c *Omenu; bx_param_bool_c *Opresent; + bx_param_enum_c *Otype; bx_param_string_c *Opath; bx_param_num_c *Ocylinders; bx_param_num_c *Oheads; bx_param_num_c *Ospt; - } bx_disk_options; + bx_param_enum_c *Ostatus; + bx_param_string_c *Omodel; + bx_param_enum_c *Obiosdetect; + bx_param_enum_c *Otranslation; + } bx_atadevice_options; typedef struct { bx_param_bool_c *Oenabled; bx_param_string_c *Odev; } bx_serial_options; -struct bx_cdrom_options -{ - bx_param_bool_c *Opresent; - bx_param_string_c *Opath; - bx_param_enum_c *Ostatus; -}; - //////////////////////////////////////////////////////////////////// // base class simulator interface, contains just virtual functions. @@ -982,6 +1100,7 @@ virtual bx_param_num_c *get_param_num (bx_id id) {return NULL;} virtual bx_param_string_c *get_param_string (bx_id id) {return NULL;} virtual bx_param_bool_c *get_param_bool (bx_id id) {return NULL;} + virtual bx_param_enum_c *get_param_enum (bx_id id) {return NULL;} virtual int get_n_log_modules () {return -1;} virtual char *get_prefix (int mod) {return 0;} virtual int get_log_action (int mod, int level) {return -1;} @@ -1008,7 +1127,7 @@ virtual int get_log_prefix (char *prefix, int len) {return -1;} virtual int set_log_prefix (char *prefix) {return -1;} virtual int get_floppy_options (int drive, bx_floppy_options *out) {return -1;} - virtual int get_cdrom_options (int drive, bx_cdrom_options *out) {return -1;} + virtual int get_cdrom_options (int drive, bx_atadevice_options *out, int *where = NULL) {return -1;} virtual char *get_floppy_type_name (int type) {return NULL;} // The CI calls set_notify_callback to register its event handler function. @@ -1043,6 +1162,8 @@ // changed. The CI will reread the parameters and change its display if it's // appropriate. Maybe later: mention which params have changed to save time. virtual void refresh_ci () {} + // return first cdrom in ATA interface + bx_param_c *get_first_cdrom () {return NULL;} #if BX_DEBUGGER // for debugger: same behavior as pressing control-C virtual void debug_break () {} Index: gui/siminterface.cc =================================================================== RCS file: /cvsroot/bochs/bochs/gui/siminterface.cc,v retrieving revision 1.64 diff -u -r1.64 siminterface.cc --- gui/siminterface.cc 20 Sep 2002 17:56:21 -0000 1.64 +++ gui/siminterface.cc 22 Sep 2002 20:46:09 -0000 @@ -50,6 +50,7 @@ virtual bx_param_num_c *get_param_num (bx_id id); virtual bx_param_string_c *get_param_string (bx_id id); virtual bx_param_bool_c *get_param_bool (bx_id id); + virtual bx_param_enum_c *get_param_enum (bx_id id); virtual int get_n_log_modules (); virtual char *get_prefix (int mod); virtual int get_log_action (int mod, int level); @@ -72,7 +73,7 @@ virtual int get_log_prefix (char *prefix, int len); virtual int set_log_prefix (char *prefix); virtual int get_floppy_options (int drive, bx_floppy_options *out); - virtual int get_cdrom_options (int drive, bx_cdrom_options *out); + virtual int get_cdrom_options (int drive, bx_atadevice_options *out, int *device = NULL); virtual char *get_floppy_type_name (int type); virtual void set_notify_callback (sim_interface_callback_t func, void *arg); virtual BxEvent* sim_to_ci_event (BxEvent *event); @@ -84,6 +85,7 @@ virtual void periodic (); virtual int create_disk_image (const char *filename, int sectors, Boolean overwrite); virtual void refresh_ci (); + bx_param_c *get_first_cdrom (); #if BX_DEBUGGER virtual void debug_break (); virtual void debug_interpret_cmd (char *cmd); @@ -143,6 +145,19 @@ return NULL; } +bx_param_enum_c * +bx_real_sim_c::get_param_enum (bx_id id) { + bx_param_c *generic = get_param(id); + if (generic==NULL) { + BX_PANIC (("get_param_enum(%u) could not find a parameter", id)); + return NULL; + } + if (generic->get_type () == BXT_PARAM_ENUM) + return (bx_param_enum_c *)generic; + BX_PANIC (("get_param_enum %u could not find a enum parameter with that id", id)); + return NULL; +} + void bx_init_siminterface () { siminterface_log = new logfunctions (); @@ -340,10 +355,20 @@ } int -bx_real_sim_c::get_cdrom_options (int drive, bx_cdrom_options *out) +bx_real_sim_c::get_cdrom_options (int level, bx_atadevice_options *out, int *where = NULL) { - BX_ASSERT (drive == 0); - *out = bx_options.cdromd; + for (Bit8u channel=0; channelget() == BX_ATA_DEVICE_CDROM) { + if (level==0) { + *out = bx_options.atadevice[channel][device]; + if (where != NULL) *where=(channel*2)+device; + return 1; + } + else level--; + } + } + } return 0; } @@ -358,6 +383,14 @@ int n_loader_os_names = 3; char *keyboard_type_names[] = { "xt", "at", "mf", NULL }; int n_keyboard_type_names = 3; +char *atadevice_type_names[] = { "hard disk", "cdrom", NULL }; +int n_atadevice_type_names = 2; +char *atadevice_status_names[] = { "ejected", "inserted", NULL }; +int n_atadevice_status_names = 2; +char *atadevice_biosdetect_names[] = { "none", "auto", "cmos", NULL }; +int n_atadevice_biosdetect_names = 3; +char *atadevice_translation_names[] = { "none", "lba", "large", NULL }; +int n_atadevice_translation_names = 3; char * bx_real_sim_c::get_floppy_type_name (int type) @@ -533,6 +566,23 @@ // the event will be freed by the recipient } +bx_param_c * +bx_real_sim_c::get_first_cdrom () +{ + for (int channel=0; channelget ()) + continue; + for (int slave=0; slave<2; slave++) { + Bit32u present = bx_options.atadevice[channel][slave].Opresent->get (); + Bit32u type = bx_options.atadevice[channel][slave].Otype->get (); + if (present && type == BX_ATA_DEVICE_CDROM) { + return bx_options.atadevice[channel][slave].Omenu; + } + } + } + return NULL; +} + #if BX_DEBUGGER // this can be safely called from either thread. @@ -688,12 +738,22 @@ void bx_param_num_c::update_dependents () { if (dependent_list) { - int en = val.number? 1 : 0; - for (int i=0; iget_size (); i++) - dependent_list->get (i)->set_enabled (en); + int en = val.number && enabled; + for (int i=0; iget_size (); i++) { + bx_param_c *param = dependent_list->get (i); + if (param != this) + param->set_enabled (en); + } } } +void +bx_param_num_c::set_enabled (int en) +{ + bx_param_c::set_enabled (en); + update_dependents (); +} + bx_shadow_num_c::bx_shadow_num_c (bx_id id, char *name, char *description, @@ -1042,6 +1102,17 @@ this->parent = NULL; } +bx_list_c * +bx_list_c::clone () +{ + bx_list_c *newlist = new bx_list_c (BXP_NULL, name, description, maxsize); + for (int i=0; iadd (get(i)); + newlist->set_options (get_options ()); + newlist->set_parent (get_parent ()); + return newlist; +} + void bx_list_c::add (bx_param_c *param) { @@ -1058,8 +1129,3 @@ return list[index]; } -void -bx_list_c::set_parent (bx_param_c *parent) -{ - this->parent = parent; -} Index: gui/wxdialog.cc =================================================================== RCS file: /cvsroot/bochs/bochs/gui/wxdialog.cc,v retrieving revision 1.42 diff -u -r1.42 wxdialog.cc --- gui/wxdialog.cc 20 Sep 2002 21:25:09 -0000 1.42 +++ gui/wxdialog.cc 22 Sep 2002 20:46:11 -0000 @@ -1709,6 +1709,7 @@ BEGIN_EVENT_TABLE(ParamDialog, wxDialog) EVT_BUTTON(-1, ParamDialog::OnEvent) EVT_CHECKBOX(-1, ParamDialog::OnEvent) + EVT_CHOICE(-1, ParamDialog::OnEvent) EVT_TEXT(-1, ParamDialog::OnEvent) END_EVENT_TABLE() @@ -1817,14 +1818,14 @@ pstr->id = genId (); pstr->param = param_generic; int type = param_generic->get_type (); -#define ADD_LABEL(x) sizer->Add (new wxStaticText (this, -1, wxString (x)), 0, wxALIGN_RIGHT|wxALL, 3) + char *prompt = pstr->param->get_ask_format (); + if (!prompt) prompt = pstr->param->get_name (); + wxASSERT (prompt != NULL); +#define ADD_LABEL(x) sizer->Add (pstr->label = new wxStaticText (this, -1, wxString (x)), 0, wxALIGN_RIGHT|wxALL, 3) switch (type) { case BXT_PARAM_BOOL: { bx_param_bool_c *param = (bx_param_bool_c*) param_generic; - if (!plain) { - char *prompt = param->get_name (); - ADD_LABEL (prompt); - } + if (!plain) ADD_LABEL (prompt); wxCheckBox *ckbx = new wxCheckBox (this, pstr->id, ""); ckbx->SetValue (param->get ()); sizer->Add (ckbx); @@ -1836,10 +1837,7 @@ } case BXT_PARAM_NUM: { bx_param_num_c *param = (bx_param_num_c*) param_generic; - if (!plain) { - char *prompt = param->get_name (); - ADD_LABEL (prompt); - } + if (!plain) ADD_LABEL (prompt); wxTextCtrl *textctrl = new wxTextCtrl (this, pstr->id, ""); const char *format = param->get_format (); if (!format) @@ -1854,10 +1852,7 @@ } case BXT_PARAM_ENUM: { bx_param_enum_c *param = (bx_param_enum_c*) param_generic; - if (!plain) { - char *prompt = param->get_name (); - ADD_LABEL (prompt); - } + if (!plain) ADD_LABEL (prompt); wxChoice *choice = new wxChoice (this, pstr->id); sizer->Add (choice); if (!plain) sizer->Add (1, 1); // spacer @@ -1874,10 +1869,7 @@ } case BXT_PARAM_STRING: { bx_param_string_c *param = (bx_param_string_c*) param_generic; - if (!plain) { - char *prompt = param->get_name (); - ADD_LABEL (prompt); - } + if (!plain) ADD_LABEL (prompt); bool isFilename = param->get_options ()->get () & param->BX_IS_FILENAME; wxTextCtrl *txtctrl = new wxTextCtrl (this, pstr->id, "", wxDefaultPosition, isFilename? longTextSize : wxDefaultSize); txtctrl->SetValue (param->getptr ()); @@ -1901,20 +1893,24 @@ } case BXT_LIST: { bx_list_c *list = (bx_list_c*) param_generic; - wxStaticBox *box = new wxStaticBox (this, -1, list->get_name ()); + wxStaticBox *box = new wxStaticBox (this, -1, prompt); wxStaticBoxSizer *boxsz = new wxStaticBoxSizer (box, wxVERTICAL); wxFlexGridSizer *gridSz = new wxFlexGridSizer (3); - boxsz->Add (gridSz, 1, wxGROW|wxALL, 20); + boxsz->Add (gridSz, 1, wxGROW|wxALL, 10); // put all items in the list inside the boxsz sizer. for (int i=0; iget_size (); i++) { bx_param_c *child = list->get (i); AddParam (child, gridSz); } // add the boxsz to mainSizer - mainSizer->Add (boxsz, 0, wxALL, 10); + mainSizer->Add (boxsz, 0, wxALL|wxGROW, 10); // clear gridSizer variable so that any future parameters force // creation of a new one. gridSizer = NULL; + // add to hashes + pstr->u.staticbox = box; + idHash->Put (pstr->id, pstr); + paramHash->Put (pstr->param->get_id (), pstr); break; } default: @@ -1974,26 +1970,108 @@ ParamStruct *pstr = (ParamStruct*) node->GetData (); if (pstr->param->get_type () == BXT_PARAM_BOOL) EnableChanged (pstr); + // special cases that can't be handled in the usual way } } void ParamDialog::EnableChanged (ParamStruct *pstrOfCheckbox) { + wxLogDebug ("EnableChanged on checkbox %s", pstrOfCheckbox->param->get_name ()); bx_param_bool_c *enableParam = (bx_param_bool_c*) pstrOfCheckbox->param; wxASSERT (enableParam->get_type () == BXT_PARAM_BOOL); // or we wouldn't be here - // if nothing depends on this "enableParam", then we're done - bx_list_c *list = enableParam->get_dependent_list (); - if (list == NULL) return; - // Now we know the object has dependents. Step through the list of - // dependents, use the paramHash table to find their ParamStruct, - // and enable/disable them as needed. bool en = pstrOfCheckbox->u.checkbox->GetValue (); + EnableChangedRecursive (enableParam->get_dependent_list (), en, pstrOfCheckbox); +} + +void ParamDialog::EnableChangedRecursive ( + bx_list_c *list, + bool en, + ParamStruct *pstrOfCheckbox) +{ + if (list==NULL) return; for (int i=0; iget_size (); i++) { bx_param_c *param = list->get(i); ParamStruct *pstr = (ParamStruct*) paramHash->Get (param->get_id ()); if (pstr) { + if (param == pstrOfCheckbox->param) { + wxLogDebug ("not setting enable on checkbox '%s' that triggered the enable change", pstrOfCheckbox->param->get_name ()); + continue; + } wxLogDebug ("setting enable for param '%s' to %d", pstr->param->get_name (), en?1:0); - pstr->u.window->Enable (en); + if (en != pstr->u.window->IsEnabled ()) { + EnableParam (pstr->param->get_id (), en); + //pstr->u.window->Enable (en); + //if (pstr->browseButton) pstr->browseButton->Enable (en); + //if (pstr->label) pstr->label->Enable (en); + bx_list_c *deps = pstr->param->get_dependent_list (); + if (deps) { + wxLogDebug ("recursing on dependent list of %s", list->get_name ()); + wxASSERT (pstr->param->get_type () == BXT_PARAM_BOOL); + bool dep_en = pstr->u.window->IsEnabled () && pstr->u.checkbox->GetValue (); + EnableChangedRecursive (deps, dep_en, pstr); + } + } + } + } + // if any enums changed, give them a chance to update + for (int i=0; iget_size (); i++) { + bx_param_c *param = list->get(i); + ParamStruct *pstr = (ParamStruct*) paramHash->Get (param->get_id ()); + if (pstr) { + if (pstr->param->get_type () == BXT_PARAM_ENUM) + EnumChanged (pstr); + } + } +} + +void ParamDialog::EnableParam (int param_id, bool enabled) +{ + ParamStruct *pstr = (ParamStruct*) paramHash->Get (param_id); + if (!pstr) return; + if (pstr->label) pstr->label->Enable (enabled); + if (pstr->browseButton) pstr->browseButton->Enable (enabled); + if (pstr->u.window) pstr->u.window->Enable (enabled); +} + +void ParamDialog::EnumChanged (ParamStruct *pstr) +{ + wxLogDebug ("EnumChanged"); + int id = pstr->param->get_id (); + switch (id) { + case BXP_ATA0_MASTER_TYPE: + case BXP_ATA0_SLAVE_TYPE: + case BXP_ATA1_MASTER_TYPE: + case BXP_ATA1_SLAVE_TYPE: + case BXP_ATA2_MASTER_TYPE: + case BXP_ATA2_SLAVE_TYPE: + case BXP_ATA3_MASTER_TYPE: + case BXP_ATA3_SLAVE_TYPE: { + int delta = id - BXP_ATA0_MASTER_TYPE; + // find out if "present" checkbox is checked + bx_id present_id = (bx_id) (BXP_ATA0_MASTER_PRESENT+delta); + ParamStruct *present = (ParamStruct*) paramHash->Get (present_id); + wxASSERT (present && present->param->get_type () == BXT_PARAM_BOOL); + if (!present->u.checkbox->GetValue ()) + break; // device not enabled, leave it alone + if (!present->u.checkbox->IsEnabled ()) + break; // enable button for the device is not enabled + wxASSERT (pstr->param->get_type () == BXT_PARAM_ENUM); + int type = pstr->u.choice->GetSelection (); + if (type == BX_ATA_DEVICE_DISK) { + // enable cylinders, heads, spt + wxLogDebug ("enabling disk parameters"); + EnableParam (BXP_ATA0_MASTER_CYLINDERS+delta, 1); + EnableParam (BXP_ATA0_MASTER_HEADS+delta, 1); + EnableParam (BXP_ATA0_MASTER_SPT+delta, 1); + EnableParam (BXP_ATA0_MASTER_STATUS+delta, 0); + } else { + // enable inserted + wxLogDebug ("enabling cdrom parameters"); + EnableParam (BXP_ATA0_MASTER_CYLINDERS+delta, 0); + EnableParam (BXP_ATA0_MASTER_HEADS+delta, 0); + EnableParam (BXP_ATA0_MASTER_SPT+delta, 0); + EnableParam (BXP_ATA0_MASTER_STATUS+delta, 1); + } } } } @@ -2041,7 +2119,7 @@ void ParamDialog::OnEvent(wxCommandEvent& event) { int id = event.GetId (); - //wxLogMessage ("event was from id=%d", id); + wxLogMessage ("event was from id=%d", id); if (isGeneratedId (id)) { ParamStruct *pstr = (ParamStruct*) idHash->Get (id); if (pstr == NULL) { @@ -2050,10 +2128,13 @@ } if (id == pstr->id) { IFDBG_DLG (wxLogDebug ("event came from window %p (id=%d) controlled by parameter '%s'", pstr->u.window, id, pstr->param->get_name ())); - if (pstr->param->get_type () == BXT_PARAM_BOOL) { - // we know that a wxCheckBox changed state. We don't yet know - // if that checkbox was enabling anything. - EnableChanged (pstr); + switch (pstr->param->get_type ()) { + case BXT_PARAM_BOOL: + EnableChanged (pstr); + break; + case BXT_PARAM_ENUM: + EnumChanged (pstr); + break; } return; } Index: gui/wxdialog.h =================================================================== RCS file: /cvsroot/bochs/bochs/gui/wxdialog.h,v retrieving revision 1.39 diff -u -r1.39 wxdialog.h --- gui/wxdialog.h 22 Sep 2002 04:52:55 -0000 1.39 +++ gui/wxdialog.h 22 Sep 2002 20:46:12 -0000 @@ -728,11 +728,13 @@ struct ParamStruct : public wxObject { bx_param_c *param; int id; + wxStaticText *label; union _u_tag { wxWindow *window; wxChoice *choice; wxTextCtrl *text; wxCheckBox *checkbox; + wxStaticBox *staticbox; } u; int browseButtonId; // only for filename params wxButton *browseButton; // only for filename params @@ -760,6 +762,9 @@ // map parameter ID (BXP_*) onto ParamStruct. wxHashTable *paramHash; virtual void EnableChanged (); + void EnableParam (int param_id, bool enabled); + void EnumChanged (ParamStruct *pstr); + void EnableChangedRecursive (bx_list_c *list, bool en, ParamStruct *pstrOfCheckbox); void EnableChanged (ParamStruct *pstr); bool CopyGuiToParam (); public: Index: gui/wxmain.h =================================================================== RCS file: /cvsroot/bochs/bochs/gui/wxmain.h,v retrieving revision 1.29 diff -u -r1.29 wxmain.h --- gui/wxmain.h 20 Sep 2002 21:25:09 -0000 1.29 +++ gui/wxmain.h 22 Sep 2002 20:46:12 -0000 @@ -28,9 +28,11 @@ ID_Config_Save, ID_Edit_FD_0, ID_Edit_FD_1, - ID_Edit_HD_0, - ID_Edit_HD_1, - ID_Edit_Cdrom, + ID_Edit_ATA0, + ID_Edit_ATA1, + ID_Edit_ATA2, + ID_Edit_ATA3, + ID_Edit_Cdrom, // for toolbar. FIXME: toolbar can't handle >1 cdrom ID_Edit_Boot, ID_Edit_Memory, ID_Edit_Sound, @@ -197,8 +199,7 @@ #endif static bool editFloppyValidate (FloppyConfigDialog *dialog); void editFloppyConfig (int drive); - void editHDConfig (int drive); - void editCdromConfig (); + void editATAConfig (int channel); void OnToolbarClick(wxCommandEvent& event); int HandleAskParam (BxEvent *event); int HandleAskParamString (bx_param_string_c *param); Index: gui/wxmain.cc =================================================================== RCS file: /cvsroot/bochs/bochs/gui/wxmain.cc,v retrieving revision 1.55 diff -u -r1.55 wxmain.cc --- gui/wxmain.cc 22 Sep 2002 04:36:09 -0000 1.55 +++ gui/wxmain.cc 22 Sep 2002 20:46:15 -0000 @@ -168,9 +168,10 @@ EVT_MENU(ID_Simulate_PauseResume, MyFrame::OnPauseResumeSim) EVT_MENU(ID_Simulate_Stop, MyFrame::OnKillSim) EVT_MENU(ID_Sim2CI_Event, MyFrame::OnSim2CIEvent) - EVT_MENU(ID_Edit_HD_0, MyFrame::OnOtherEvent) - EVT_MENU(ID_Edit_HD_1, MyFrame::OnOtherEvent) - EVT_MENU(ID_Edit_Cdrom, MyFrame::OnOtherEvent) + EVT_MENU(ID_Edit_ATA0, MyFrame::OnOtherEvent) + EVT_MENU(ID_Edit_ATA1, MyFrame::OnOtherEvent) + EVT_MENU(ID_Edit_ATA2, MyFrame::OnOtherEvent) + EVT_MENU(ID_Edit_ATA3, MyFrame::OnOtherEvent) EVT_MENU(ID_Edit_Boot, MyFrame::OnEditBoot) EVT_MENU(ID_Edit_Memory, MyFrame::OnEditMemory) EVT_MENU(ID_Edit_Sound, MyFrame::OnEditSound) @@ -279,9 +280,10 @@ menuEdit = new wxMenu; menuEdit->Append( ID_Edit_FD_0, "Floppy Disk &0..." ); menuEdit->Append( ID_Edit_FD_1, "Floppy Disk &1..." ); - menuEdit->Append( ID_Edit_HD_0, "Hard Disk 0..." ); - menuEdit->Append( ID_Edit_HD_1, "Hard Disk 1..." ); - menuEdit->Append( ID_Edit_Cdrom, "Cdrom..." ); + menuEdit->Append( ID_Edit_ATA0, "ATA Controller 0..." ); + menuEdit->Append( ID_Edit_ATA1, "ATA Controller 1..." ); + menuEdit->Append( ID_Edit_ATA2, "ATA Controller 2..." ); + menuEdit->Append( ID_Edit_ATA3, "ATA Controller 3..." ); menuEdit->Append( ID_Edit_Boot, "&Boot..." ); menuEdit->Append( ID_Edit_Memory, "&Memory..." ); menuEdit->Append( ID_Edit_Sound, "&Sound..." ); @@ -402,24 +404,22 @@ int bootDevices = 0; wxString devices[MAX_BOOT_DEVICES]; int dev_id[MAX_BOOT_DEVICES]; - bx_param_bool_c *floppy = (bx_param_bool_c *) - SIM->get_param (BXP_FLOPPYA_DEVTYPE); - bx_param_bool_c *hd = (bx_param_bool_c *) - SIM->get_param (BXP_DISKC_PRESENT); - bx_param_bool_c *cdrom = (bx_param_bool_c *) - SIM->get_param (BXP_CDROM_PRESENT); - wxASSERT (floppy->get_type () == BXT_PARAM_ENUM - && hd->get_type () == BXT_PARAM_BOOL - && cdrom->get_type () == BXT_PARAM_BOOL); + bx_param_enum_c *floppy = SIM->get_param_enum (BXP_FLOPPYA_DEVTYPE); + bx_param_bool_c *ata0_mpres = SIM->get_param_bool (BXP_ATA0_MASTER_PRESENT); + bx_param_enum_c *ata0_mtype = SIM->get_param_enum (BXP_ATA0_MASTER_TYPE); + bx_param_bool_c *ata0_spres = SIM->get_param_bool (BXP_ATA0_SLAVE_PRESENT); + bx_param_enum_c *ata0_stype = SIM->get_param_enum (BXP_ATA0_SLAVE_TYPE); if (floppy->get () != BX_FLOPPY_NONE) { devices[bootDevices] = wxT("First floppy drive"); dev_id[bootDevices++] = BX_BOOT_FLOPPYA; } - if (hd->get ()) { +#warning wxwindows interface will only allow booting from hard disk if it is on ATA0 master + if (ata0_mpres->get() && ata0_mtype->get() == BX_ATA_DEVICE_DISK) { devices[bootDevices] = wxT("First hard drive"); dev_id[bootDevices++] = BX_BOOT_DISKC; } - if (cdrom->get ()) { +#warning wxwindows interface will only allow booting from cdrom if it is on ATA0 slave + if (ata0_spres->get() && ata0_stype->get() == BX_ATA_DEVICE_CDROM) { devices[bootDevices] = wxT("CD-ROM drive"); dev_id[bootDevices++] = BX_BOOT_CDROM; } @@ -834,8 +834,11 @@ bool canConfigure = (change == Stop); menuConfiguration->Enable (ID_Config_New, canConfigure); menuConfiguration->Enable (ID_Config_Read, canConfigure); - menuEdit->Enable (ID_Edit_HD_0, canConfigure); - menuEdit->Enable (ID_Edit_HD_1, canConfigure); +#warning For now, leave ATA devices so that you configure them during runtime. Otherwise you cannot change the CD image at runtime. + //menuEdit->Enable (ID_Edit_ATA0, canConfigure); + //menuEdit->Enable (ID_Edit_ATA1, canConfigure); + //menuEdit->Enable (ID_Edit_ATA2, canConfigure); + //menuEdit->Enable (ID_Edit_ATA3, canConfigure); menuEdit->Enable( ID_Edit_Boot, canConfigure); menuEdit->Enable( ID_Edit_Memory, canConfigure); menuEdit->Enable( ID_Edit_Sound, canConfigure); @@ -853,8 +856,12 @@ menuEdit->Enable (ID_Edit_FD_0, canConfigure || param->get_enabled ()); param = SIM->get_param(BXP_FLOPPYB); menuEdit->Enable (ID_Edit_FD_1, canConfigure || param->get_enabled ()); - param = SIM->get_param(BXP_CDROMD); - menuEdit->Enable (ID_Edit_Cdrom, canConfigure || param->get_enabled ()); + /* + // this menu item removed, since you can configure the cdrom from the + // ATA controller menu items instead. + param = SIM->get_first_cdrom (); + menuEdit->Enable (ID_Edit_Cdrom, canConfigure || (param&¶m->get_enabled ())); + */ } void MyFrame::OnStartSim(wxCommandEvent& event) @@ -1152,9 +1159,12 @@ int id = event.GetId (); wxLogMessage ("event id=%d", id); switch (id) { - case ID_Edit_HD_0: editHDConfig (0); break; - case ID_Edit_HD_1: editHDConfig (1); break; - case ID_Edit_Cdrom: editCdromConfig (); break; + case ID_Edit_ATA0: + case ID_Edit_ATA1: + case ID_Edit_ATA2: + case ID_Edit_ATA3: + editATAConfig (id - ID_Edit_ATA0); + break; } } @@ -1217,106 +1227,14 @@ } } -void MyFrame::editHDConfig (int drive) -{ - HDConfigDialog dlg (this, -1); - dlg.SetDriveName (drive==0? BX_HARD_DISK0_NAME : BX_HARD_DISK1_NAME); - bx_list_c *list = (bx_list_c*) SIM->get_param ((drive==0)? BXP_DISKC : BXP_DISKD); - if (!list) { wxLogError ("HD object param is null"); return; } - bx_param_filename_c *fname = (bx_param_filename_c*) list->get(0); - bx_param_num_c *cyl = (bx_param_num_c *) list->get(1); - bx_param_num_c *heads = (bx_param_num_c *) list->get(2); - bx_param_num_c *spt = (bx_param_num_c *) list->get(3); - bx_param_bool_c *present = (bx_param_bool_c *) - SIM->get_param (drive==0? BXP_DISKC_PRESENT : BXP_DISKD_PRESENT); - wxASSERT (fname->get_type () == BXT_PARAM_STRING - && cyl->get_type () == BXT_PARAM_NUM - && heads->get_type () == BXT_PARAM_NUM - && spt->get_type() == BXT_PARAM_NUM - && present->get_type() == BXT_PARAM_BOOL); - dlg.SetFilename (fname->getptr ()); - dlg.SetGeomRange (0, cyl->get_min(), cyl->get_max ()); - dlg.SetGeomRange (1, heads->get_min(), heads->get_max ()); - dlg.SetGeomRange (2, spt->get_min(), spt->get_max ()); - dlg.SetGeom (0, cyl->get ()); - dlg.SetGeom (1, heads->get ()); - dlg.SetGeom (2, spt->get ()); - dlg.SetEnable (present->get ()); - int n = dlg.ShowModal (); - wxLogMessage ("HD config returned %d", n); - if (n==wxID_OK) { - char filename[1024]; - wxString fn (dlg.GetFilename ()); - strncpy (filename, fn.c_str (), sizeof (filename)); - wxLogMessage ("filename is '%s'", filename); - fname->set (filename); - cyl->set (dlg.GetGeom (0)); - heads->set (dlg.GetGeom (1)); - spt->set (dlg.GetGeom (2)); - present->set (dlg.GetEnable ()); - wxLogMessage ("present=%d cyl=%d heads=%d spt=%d", present->get (), cyl->get(), heads->get(), spt->get()); - if (drive==1 && present->get ()) { - // check that diskD and cdrom are not enabled at the same time - bx_param_bool_c *cdromd = (bx_param_bool_c*) - SIM->get_param(BXP_CDROM_PRESENT); - if (cdromd->get ()) { - wxString msg; - msg.Printf ("You cannot have both %s and %s enabled. Disabling %s.", - BX_HARD_DISK1_NAME, BX_CDROM_NAME, BX_CDROM_NAME); - wxMessageBox( msg, "Device conflict", wxOK | wxICON_ERROR ); - cdromd->set (0); - } - } - } -} - -void MyFrame::editCdromConfig () +void MyFrame::editATAConfig (int channel) { - CdromConfigDialog dlg (this, -1); - dlg.SetDriveName (BX_CDROM_NAME); - bx_param_filename_c *fname = - (bx_param_filename_c*) SIM->get_param(BXP_CDROM_PATH); - bx_param_bool_c *present = - (bx_param_bool_c*) SIM->get_param(BXP_CDROM_PRESENT); - bx_param_enum_c *status = - (bx_param_enum_c*) SIM->get_param(BXP_CDROM_STATUS); - wxASSERT (fname->get_type () == BXT_PARAM_STRING - && present->get_type () == BXT_PARAM_BOOL - && status->get_type () == BXT_PARAM_ENUM); -#if defined(__linux__) - dlg.AddRadio ("Physical CD-ROM drive /dev/cdrom", "/dev/cdrom"); -#elif defined (WIN32) - dlg.AddRadio ("Physical CD-ROM drive D:", "D:"); -#else - // add your favorite operating system here -#endif - dlg.SetEnable (present->get () ? TRUE : FALSE); - dlg.SetFilename (fname->getptr ()); - dlg.SetEjected (status->get () == BX_EJECTED); - int n = dlg.ShowModal (); - wxLogMessage ("cdrom config returned %d", n); - if (n==wxID_OK) { - char filename[1024]; - wxString fn (dlg.GetFilename ()); - strncpy (filename, fn.c_str (), sizeof(filename)); - fname->set (filename); - present->set (dlg.GetEnable ()); - status->set (dlg.GetEjected () ? BX_EJECTED : BX_INSERTED); - wxLogMessage ("filename is '%s'", filename); - wxLogMessage ("enabled=%d ejected=%d", present->get(), status->get()); - // cdrom and hard disk D cannot both be enabled. - if (present->get ()) { - bx_param_bool_c *diskd = (bx_param_bool_c*) - SIM->get_param(BXP_DISKD_PRESENT); - if (diskd->get ()) { - wxString msg; - msg.Printf ("You cannot have both %s and %s enabled. Disabling %s.", - BX_CDROM_NAME, BX_HARD_DISK1_NAME, BX_HARD_DISK1_NAME); - wxMessageBox( msg, "Device conflict", wxOK | wxICON_ERROR ); - diskd->set (0); - } - } - } + ParamDialog dlg (this, -1); + dlg.SetTitle ("Configure ATA0"); + dlg.AddParam (SIM->get_param ((bx_id)(BXP_ATA0+channel))); + dlg.AddParam (SIM->get_param ((bx_id)(BXP_ATA0_MASTER+channel*2))); + dlg.AddParam (SIM->get_param ((bx_id)(BXP_ATA0_SLAVE+channel*2))); + dlg.ShowModal (); } void MyFrame::OnToolbarClick(wxCommandEvent& event) Index: iodev/harddrv.cc =================================================================== RCS file: /cvsroot/bochs/bochs/iodev/harddrv.cc,v retrieving revision 1.72 diff -u -r1.72 harddrv.cc --- iodev/harddrv.cc 16 Sep 2002 16:58:36 -0000 1.72 +++ iodev/harddrv.cc 22 Sep 2002 20:46:16 -0000 @@ -56,76 +56,99 @@ #endif -static unsigned char model_no[41] = - "Generic 1234 "; - static unsigned max_multiple_sectors = 0; // was 0x3f static unsigned curr_multiple_sectors = 0; // was 0x3f // some packet handling macros #define EXTRACT_FIELD(arr,byte,start,num_bits) (((arr)[(byte)] >> (start)) & ((1 << (num_bits)) - 1)) -#define get_packet_field(b,s,n) (EXTRACT_FIELD((BX_SELECTED_CONTROLLER.buffer),(b),(s),(n))) -#define get_packet_byte(b) (BX_SELECTED_CONTROLLER.buffer[(b)]) -#define get_packet_word(b) (((uint16)BX_SELECTED_CONTROLLER.buffer[(b)] << 8) | BX_SELECTED_CONTROLLER.buffer[(b)+1]) - - -#define BX_CONTROLLER(a) (BX_HD_THIS s[(a)]).controller -#define BX_SELECTED_CONTROLLER (BX_CONTROLLER(BX_HD_THIS drive_select)) - -#define WRITE_FEATURES(a) do { uint8 _a = a; BX_CONTROLLER(0).features = _a; BX_CONTROLLER(1).features = _a; } while(0) -#define WRITE_SECTOR_COUNT(a) do { uint8 _a = a; BX_CONTROLLER(0).sector_count = _a; BX_CONTROLLER(1).sector_count = _a; } while(0) -#define WRITE_SECTOR_NUMBER(a) do { uint8 _a = a; BX_CONTROLLER(0).sector_no = _a; BX_CONTROLLER(1).sector_no = _a; } while(0) -#define WRITE_CYLINDER_LOW(a) do { uint8 _a = a; BX_CONTROLLER(0).cylinder_no = (BX_CONTROLLER(0).cylinder_no & 0xff00) | _a; BX_CONTROLLER(1).cylinder_no = (BX_CONTROLLER(1).cylinder_no & 0xff00) | _a; } while(0) -#define WRITE_CYLINDER_HIGH(a) do { uint16 _a = a; BX_CONTROLLER(0).cylinder_no = (_a << 8) | (BX_CONTROLLER(0).cylinder_no & 0xff); BX_CONTROLLER(1).cylinder_no = (_a << 8) | (BX_CONTROLLER(1).cylinder_no & 0xff); } while(0) -#define WRITE_HEAD_NO(a) do { uint8 _a = a; BX_CONTROLLER(0).head_no = _a; BX_CONTROLLER(1).head_no = _a; } while(0) -#define WRITE_LBA_MODE(a) do { uint8 _a = a; BX_CONTROLLER(0).lba_mode = _a; BX_CONTROLLER(1).lba_mode = _a; } while(0) +#define get_packet_field(c,b,s,n) (EXTRACT_FIELD((BX_SELECTED_CONTROLLER((c)).buffer),(b),(s),(n))) +#define get_packet_byte(c,b) (BX_SELECTED_CONTROLLER((c)).buffer[(b)]) +#define get_packet_word(c,b) (((uint16)BX_SELECTED_CONTROLLER((c)).buffer[(b)] << 8) | BX_SELECTED_CONTROLLER((c)).buffer[(b)+1]) + + +#define BX_CONTROLLER(c,a) (BX_HD_THIS channels[(c)].drives[(a)]).controller +#define BX_DRIVE(c,a) (BX_HD_THIS channels[(c)].drives[(a)]) + +#define BX_DRIVE_IS_PRESENT(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type != IDE_NONE) +#define BX_DRIVE_IS_HD(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type == IDE_DISK) +#define BX_DRIVE_IS_CD(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type == IDE_CDROM) + +#define BX_MASTER_IS_PRESENT(c) BX_DRIVE_IS_PRESENT((c),0) +#define BX_SLAVE_IS_PRESENT(c) BX_DRIVE_IS_PRESENT((c),1) + +#define BX_SELECTED_CONTROLLER(c) (BX_CONTROLLER((c),BX_HD_THIS channels[(c)].drive_select)) +#define BX_SELECTED_DRIVE(c) (BX_DRIVE((c),BX_HD_THIS channels[(c)].drive_select)) +#define BX_MASTER_SELECTED(c) (!BX_HD_THIS channels[(c)].drive_select) +#define BX_SLAVE_SELECTED(c) (BX_HD_THIS channels[(c)].drive_select) + +#define BX_SELECTED_IS_PRESENT(c) (BX_DRIVE_IS_PRESENT((c),BX_SLAVE_SELECTED((c)))) +#define BX_SELECTED_IS_HD(c) (BX_DRIVE_IS_HD((c),BX_SLAVE_SELECTED((c)))) +#define BX_SELECTED_IS_CD(c) (BX_DRIVE_IS_CD((c),BX_SLAVE_SELECTED((c)))) + +#define BX_SELECTED_MODEL(c) (BX_HD_THIS channels[(c)].drives[BX_HD_THIS channels[(c)].drive_select].model_no) +#define BX_SELECTED_TYPE_STRING(channel) ((BX_SELECTED_IS_CD(channel)) ? "CD-ROM" : "DISK") + +#define WRITE_FEATURES(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).features = _a; BX_CONTROLLER((c),1).features = _a; } while(0) +#define WRITE_SECTOR_COUNT(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).sector_count = _a; BX_CONTROLLER((c),1).sector_count = _a; } while(0) +#define WRITE_SECTOR_NUMBER(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).sector_no = _a; BX_CONTROLLER((c),1).sector_no = _a; } while(0) +#define WRITE_CYLINDER_LOW(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).cylinder_no = (BX_CONTROLLER((c),0).cylinder_no & 0xff00) | _a; BX_CONTROLLER((c),1).cylinder_no = (BX_CONTROLLER((c),1).cylinder_no & 0xff00) | _a; } while(0) +#define WRITE_CYLINDER_HIGH(c,a) do { uint16 _a = a; BX_CONTROLLER((c),0).cylinder_no = (_a << 8) | (BX_CONTROLLER((c),0).cylinder_no & 0xff); BX_CONTROLLER((c),1).cylinder_no = (_a << 8) | (BX_CONTROLLER((c),1).cylinder_no & 0xff); } while(0) +#define WRITE_HEAD_NO(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).head_no = _a; BX_CONTROLLER((c),1).head_no = _a; } while(0) +#define WRITE_LBA_MODE(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).lba_mode = _a; BX_CONTROLLER((c),1).lba_mode = _a; } while(0) //static unsigned im_here = 0; bx_hard_drive_c::bx_hard_drive_c(void) { - s[0].hard_drive = NULL; - s[1].hard_drive = NULL; +#if DLL_HD_SUPPORT +# error code must be fixed to use DLL_HD_SUPPORT and 4 ata channels +#endif + + for (Bit8u channel=0; channelget() == 1) { + BX_HD_THIS channels[channel].ioaddr1 = bx_options.ata[channel].Oioaddr1->get(); + BX_HD_THIS channels[channel].ioaddr2 = bx_options.ata[channel].Oioaddr2->get(); + BX_HD_THIS channels[channel].irq = bx_options.ata[channel].Oirq->get(); + + // Coherency check + if ( (BX_HD_THIS channels[channel].ioaddr1 == 0) || + (BX_HD_THIS channels[channel].ioaddr2 == 0) || + (BX_HD_THIS channels[channel].irq == 0) ) { + BX_PANIC(("incoherency for ata channel %d: io1=0x%x, io2=%x, irq=%d", + channel, + BX_HD_THIS channels[channel].ioaddr1, + BX_HD_THIS channels[channel].ioaddr2, + BX_HD_THIS channels[channel].irq)); + } + } + else { + BX_HD_THIS channels[channel].ioaddr1 = 0; + BX_HD_THIS channels[channel].ioaddr2 = 0; + BX_HD_THIS channels[channel].irq = 0; + } + } + + for (channel=0; channelregister_irq(14, "Hard Drive 0"); - for (unsigned addr=0x01F0; addr<=0x01F7; addr++) { - BX_HD_THIS devices->register_io_read_handler(this, read_handler, - addr, "Hard Drive 0"); - BX_HD_THIS devices->register_io_write_handler(this, write_handler, - addr, "Hard Drive 0"); - } -#if 0 - // this would be necessary to make the second HD master on the - // second controller, using 0x170-0x177 and irq15. But it currently - // works as second disk on the first IDE controller, so this code - // is not needed. - BX_HD_THIS devices->register_irq(15, "Hard Drive 1"); - for (unsigned addr=0x0170; addr<=0x0177; addr++) { - BX_HD_THIS devices->register_io_read_handler(this, read_handler, - addr, "Hard Drive 1"); - BX_HD_THIS devices->register_io_write_handler(this, write_handler, - addr, "Hard Drive 1"); + if (BX_HD_THIS channels[channel].irq != 0) + BX_HD_THIS devices->register_irq(BX_HD_THIS channels[channel].irq, strdup(string)); + + if (BX_HD_THIS channels[channel].ioaddr1 != 0) { + for (unsigned addr=0x0; addr<=0x7; addr++) { + BX_HD_THIS devices->register_io_read_handler(this, read_handler, + BX_HD_THIS channels[channel].ioaddr1+addr, strdup(string)); + BX_HD_THIS devices->register_io_write_handler(this, write_handler, + BX_HD_THIS channels[channel].ioaddr1+addr, strdup(string)); + } + } + + // We don't want to register addresses 0x3f6 and 0x3f7 as they are handled by the floppy controller + if ((BX_HD_THIS channels[channel].ioaddr2 != 0) && (BX_HD_THIS channels[channel].ioaddr2 != 0x3f0)) { + for (unsigned addr=0x6; addr<=0x7; addr++) { + BX_HD_THIS devices->register_io_read_handler(this, read_handler, + BX_HD_THIS channels[channel].ioaddr2+addr, strdup(string)); + BX_HD_THIS devices->register_io_write_handler(this, write_handler, + BX_HD_THIS channels[channel].ioaddr2+addr, strdup(string)); + } + } + + BX_HD_THIS channels[channel].drive_select = 0; } -#endif - BX_HD_THIS drive_select = 0; - - BX_HD_THIS s[0].hard_drive->cylinders = bx_options.diskc.Ocylinders->get (); - BX_HD_THIS s[0].hard_drive->heads = bx_options.diskc.Oheads->get (); - BX_HD_THIS s[0].hard_drive->sectors = bx_options.diskc.Ospt->get (); - BX_HD_THIS s[0].device_type = IDE_DISK; - BX_HD_THIS s[1].hard_drive->cylinders = bx_options.diskd.Ocylinders->get (); - BX_HD_THIS s[1].hard_drive->heads = bx_options.diskd.Oheads->get (); - BX_HD_THIS s[1].hard_drive->sectors = bx_options.diskd.Ospt->get (); - BX_HD_THIS s[1].device_type = IDE_DISK; - - if (bx_options.cdromd.Opresent->get ()) { - bx_options.diskd.Opresent->set (1); - BX_DEBUG(( "Experimental CDROM on target 1" )); - BX_HD_THIS s[1].device_type = IDE_CDROM; - BX_HD_THIS s[1].cdrom.locked = 0; - BX_HD_THIS s[1].sense.sense_key = SENSE_NONE; - BX_HD_THIS s[1].sense.asc = 0; - BX_HD_THIS s[1].sense.ascq = 0; - // Check bit fields - BX_CONTROLLER(1).sector_count = 0; - BX_CONTROLLER(1).interrupt_reason.c_d = 1; - if (BX_CONTROLLER(1).sector_count != 0x01) - BX_PANIC(("interrupt reason bit field error")); + channel = 0; + for (channel=0; channelget()) { + continue; + } - BX_CONTROLLER(1).sector_count = 0; - BX_CONTROLLER(1).interrupt_reason.i_o = 1; - if (BX_CONTROLLER(1).sector_count != 0x02) - BX_PANIC(("interrupt reason bit field error")); + // Make model string + strncpy((char*)BX_HD_THIS channels[channel].drives[device].model_no, + bx_options.atadevice[channel][device].Omodel->getptr(), 40); + while (strlen((char *)BX_HD_THIS channels[channel].drives[device].model_no) < 40) { + strcat ((char*)BX_HD_THIS channels[channel].drives[device].model_no, " "); + } - BX_CONTROLLER(1).sector_count = 0; - BX_CONTROLLER(1).interrupt_reason.rel = 1; - if (BX_CONTROLLER(1).sector_count != 0x04) + if (bx_options.atadevice[channel][device].Otype->get() == BX_ATA_DEVICE_DISK) { + BX_DEBUG(( "Hard-Disk on target %d/%d",channel,device)); + BX_HD_THIS channels[channel].drives[device].device_type = IDE_DISK; + BX_HD_THIS channels[channel].drives[device].hard_drive->cylinders = bx_options.atadevice[channel][device].Ocylinders->get (); + BX_HD_THIS channels[channel].drives[device].hard_drive->heads = bx_options.atadevice[channel][device].Oheads->get (); + BX_HD_THIS channels[channel].drives[device].hard_drive->sectors = bx_options.atadevice[channel][device].Ospt->get (); + + /* open hard drive image file */ + if ((BX_HD_THIS channels[channel].drives[device].hard_drive->open(bx_options.atadevice[channel][device].Opath->getptr ())) < 0) { + BX_PANIC(("could not open hard drive image file '%s'", bx_options.atadevice[channel][device].Opath->getptr ())); + } + BX_INFO(("HD on ata%d-%d: '%s'",channel, device, bx_options.atadevice[channel][device].Opath->getptr ())); + } + else if (bx_options.atadevice[channel][device].Otype->get() == BX_ATA_DEVICE_CDROM) { + BX_DEBUG(( "CDROM on target %d/%d",channel,device)); + BX_HD_THIS channels[channel].drives[device].device_type = IDE_CDROM; + BX_HD_THIS channels[channel].drives[device].cdrom.locked = 0; + BX_HD_THIS channels[channel].drives[device].sense.sense_key = SENSE_NONE; + BX_HD_THIS channels[channel].drives[device].sense.asc = 0; + BX_HD_THIS channels[channel].drives[device].sense.ascq = 0; + + // Check bit fields + BX_CONTROLLER(channel,device).sector_count = 0; + BX_CONTROLLER(channel,device).interrupt_reason.c_d = 1; + if (BX_CONTROLLER(channel,device).sector_count != 0x01) + BX_PANIC(("interrupt reason bit field error")); + + BX_CONTROLLER(channel,device).sector_count = 0; + BX_CONTROLLER(channel,device).interrupt_reason.i_o = 1; + if (BX_CONTROLLER(channel,device).sector_count != 0x02) + BX_PANIC(("interrupt reason bit field error")); + + BX_CONTROLLER(channel,device).sector_count = 0; + BX_CONTROLLER(channel,device).interrupt_reason.rel = 1; + if (BX_CONTROLLER(channel,device).sector_count != 0x04) BX_PANIC(("interrupt reason bit field error")); - BX_CONTROLLER(1).sector_count = 0; - BX_CONTROLLER(1).interrupt_reason.tag = 3; - if (BX_CONTROLLER(1).sector_count != 0x18) + BX_CONTROLLER(channel,device).sector_count = 0; + BX_CONTROLLER(channel,device).interrupt_reason.tag = 3; + if (BX_CONTROLLER(channel,device).sector_count != 0x18) BX_PANIC(("interrupt reason bit field error")); - BX_CONTROLLER(1).sector_count = 0; + BX_CONTROLLER(channel,device).sector_count = 0; // allocate low level driver #ifdef LOWLEVEL_CDROM - BX_HD_THIS s[1].cdrom.cd = new LOWLEVEL_CDROM(bx_options.cdromd.Opath->getptr ()); -#endif + BX_HD_THIS channels[channel].drives[device].cdrom.cd = new LOWLEVEL_CDROM(bx_options.atadevice[channel][device].Opath->getptr ()); + BX_INFO(("CD on ata%d-%d: '%s'",channel, device, bx_options.atadevice[channel][device].Opath->getptr ())); -#ifdef LOWLEVEL_CDROM - if (bx_options.cdromd.Ostatus->get () == BX_INSERTED) { - if (BX_HD_THIS s[1].cdrom.cd->insert_cdrom()) { + if (bx_options.atadevice[channel][device].Ostatus->get () == BX_INSERTED) { + if (BX_HD_THIS channels[channel].drives[device].cdrom.cd->insert_cdrom()) { BX_INFO(( "Media present in CD-ROM drive")); - BX_HD_THIS s[1].cdrom.ready = 1; - BX_HD_THIS s[1].cdrom.capacity = BX_HD_THIS s[1].cdrom.cd->capacity(); + BX_HD_THIS channels[channel].drives[device].cdrom.ready = 1; + BX_HD_THIS channels[channel].drives[device].cdrom.capacity = BX_HD_THIS channels[channel].drives[device].cdrom.cd->capacity(); } else { BX_INFO(( "Could not locate CD-ROM, continuing with media not present")); - BX_HD_THIS s[1].cdrom.ready = 0; - bx_options.cdromd.Ostatus->set(BX_EJECTED); + BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; + bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED); } } else { #endif BX_INFO(( "Media not present in CD-ROM drive" )); - BX_HD_THIS s[1].cdrom.ready = 0; + BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; #ifdef LOWLEVEL_CDROM } #endif - } + } - /* open hard drive image file */ - if (bx_options.diskc.Opresent->get ()) { - if ((BX_HD_THIS s[0].hard_drive->open(bx_options.diskc.Opath->getptr ())) < 0) { - BX_PANIC(("could not open hard drive image file '%s'", - bx_options.diskc.Opath->getptr ())); - } - BX_INFO(("hd0: '%s'",bx_options.diskc.Opath->getptr ())); - } - if (bx_options.diskd.Opresent->get () && !bx_options.cdromd.Opresent->get ()) { - if ((BX_HD_THIS s[1].hard_drive->open(bx_options.diskd.Opath->getptr ())) < 0) { - BX_PANIC(("could not open hard drive image file '%s'", - bx_options.diskd.Opath->getptr ())); - } - BX_INFO(("hd1: '%s'",bx_options.diskd.Opath->getptr())); + BX_CONTROLLER(channel,device).status.busy = 0; + BX_CONTROLLER(channel,device).status.drive_ready = 1; + BX_CONTROLLER(channel,device).status.write_fault = 0; + BX_CONTROLLER(channel,device).status.seek_complete = 1; + BX_CONTROLLER(channel,device).status.drq = 0; + BX_CONTROLLER(channel,device).status.corrected_data = 0; + BX_CONTROLLER(channel,device).status.index_pulse = 0; + BX_CONTROLLER(channel,device).status.index_pulse_count = 0; + BX_CONTROLLER(channel,device).status.err = 0; + + BX_CONTROLLER(channel,device).error_register = 0x01; // diagnostic code: no error + BX_CONTROLLER(channel,device).head_no = 0; + BX_CONTROLLER(channel,device).sector_count = 1; + BX_CONTROLLER(channel,device).sector_no = 1; + BX_CONTROLLER(channel,device).cylinder_no = 0; + BX_CONTROLLER(channel,device).current_command = 0x00; + BX_CONTROLLER(channel,device).buffer_index = 0; + + BX_CONTROLLER(channel,device).control.reset = 0; + BX_CONTROLLER(channel,device).control.disable_irq = 0; + + BX_CONTROLLER(channel,device).reset_in_progress = 0; + + BX_CONTROLLER(channel,device).sectors_per_block = 0x80; + BX_CONTROLLER(channel,device).lba_mode = 0; + + BX_CONTROLLER(channel,device).features = 0; + } } // generate CMOS values for hard drive if not using a CMOS image if (!bx_options.cmos.OcmosImage->get ()) { cmos->s.reg[0x12] = 0x00; // start out with: no drive 0, no drive 1 - if (bx_options.diskc.Opresent->get ()) { + if (BX_DRIVE_IS_HD(0,0)) { // Flag drive type as Fh, use extended CMOS location as real type cmos->s.reg[0x12] = (cmos->s.reg[0x12] & 0x0f) | 0xf0; cmos->s.reg[0x19] = 47; // user definable type // AMI BIOS: 1st hard disk #cyl low byte - cmos->s.reg[0x1b] = (bx_options.diskc.Ocylinders->get () & 0x00ff); + cmos->s.reg[0x1b] = (bx_options.atadevice[0][0].Ocylinders->get () & 0x00ff); // AMI BIOS: 1st hard disk #cyl high byte - cmos->s.reg[0x1c] = (bx_options.diskc.Ocylinders->get () & 0xff00) >> 8; + cmos->s.reg[0x1c] = (bx_options.atadevice[0][0].Ocylinders->get () & 0xff00) >> 8; // AMI BIOS: 1st hard disk #heads - cmos->s.reg[0x1d] = (bx_options.diskc.Oheads->get ()); + cmos->s.reg[0x1d] = (bx_options.atadevice[0][0].Oheads->get ()); // AMI BIOS: 1st hard disk write precompensation cylinder, low byte cmos->s.reg[0x1e] = 0xff; // -1 // AMI BIOS: 1st hard disk write precompensation cylinder, high byte cmos->s.reg[0x1f] = 0xff; // -1 // AMI BIOS: 1st hard disk control byte - cmos->s.reg[0x20] = 0xc0 | ((bx_options.diskc.Oheads->get () > 8) << 3); + cmos->s.reg[0x20] = 0xc0 | ((bx_options.atadevice[0][0].Oheads->get () > 8) << 3); // AMI BIOS: 1st hard disk landing zone, low byte cmos->s.reg[0x21] = cmos->s.reg[0x1b]; // AMI BIOS: 1st hard disk landing zone, high byte cmos->s.reg[0x22] = cmos->s.reg[0x1c]; // AMI BIOS: 1st hard disk sectors/track - cmos->s.reg[0x23] = bx_options.diskc.Ospt->get (); + cmos->s.reg[0x23] = bx_options.atadevice[0][0].Ospt->get (); } //set up cmos for second hard drive - if (bx_options.diskd.Opresent->get () && !bx_options.cdromd.Opresent->get ()) { + if (BX_DRIVE_IS_HD(0,1)) { BX_DEBUG(("1: I will put 0xf into the second hard disk field")); // fill in lower 4 bits of 0x12 for second HD cmos->s.reg[0x12] = (cmos->s.reg[0x12] & 0xf0) | 0x0f; cmos->s.reg[0x1a] = 47; // user definable type // AMI BIOS: 2nd hard disk #cyl low byte - cmos->s.reg[0x24] = (bx_options.diskd.Ocylinders->get () & 0x00ff); + cmos->s.reg[0x24] = (bx_options.atadevice[0][1].Ocylinders->get () & 0x00ff); // AMI BIOS: 2nd hard disk #cyl high byte - cmos->s.reg[0x25] = (bx_options.diskd.Ocylinders->get () & 0xff00) >> 8; + cmos->s.reg[0x25] = (bx_options.atadevice[0][1].Ocylinders->get () & 0xff00) >> 8; // AMI BIOS: 2nd hard disk #heads - cmos->s.reg[0x26] = (bx_options.diskd.Oheads->get ()); + cmos->s.reg[0x26] = (bx_options.atadevice[0][1].Oheads->get ()); // AMI BIOS: 2nd hard disk write precompensation cylinder, low byte cmos->s.reg[0x27] = 0xff; // -1 // AMI BIOS: 2nd hard disk write precompensation cylinder, high byte cmos->s.reg[0x28] = 0xff; // -1 // AMI BIOS: 2nd hard disk, 0x80 if heads>8 - cmos->s.reg[0x29] = (bx_options.diskd.Oheads->get () > 8) ? 0x80 : 0x00; + cmos->s.reg[0x29] = (bx_options.atadevice[0][1].Oheads->get () > 8) ? 0x80 : 0x00; // AMI BIOS: 2nd hard disk landing zone, low byte cmos->s.reg[0x2a] = cmos->s.reg[0x24]; // AMI BIOS: 2nd hard disk landing zone, high byte cmos->s.reg[0x2b] = cmos->s.reg[0x25]; // AMI BIOS: 2nd hard disk sectors/track - cmos->s.reg[0x2c] = bx_options.diskd.Ospt->get (); + cmos->s.reg[0x2c] = bx_options.atadevice[0][1].Ospt->get (); } @@ -330,38 +417,6 @@ BX_INFO(("Floppy boot signature check is %sabled", bx_options.OfloppySigCheck->get() ? "dis" : "en")); } - //switch (stat_buf.st_size) { - // } - - for (int id = 0; id < 2; id++) { - BX_CONTROLLER(id).status.busy = 0; - BX_CONTROLLER(id).status.drive_ready = 1; - BX_CONTROLLER(id).status.write_fault = 0; - BX_CONTROLLER(id).status.seek_complete = 1; - BX_CONTROLLER(id).status.drq = 0; - BX_CONTROLLER(id).status.corrected_data = 0; - BX_CONTROLLER(id).status.index_pulse = 0; - BX_CONTROLLER(id).status.index_pulse_count = 0; - BX_CONTROLLER(id).status.err = 0; - - BX_CONTROLLER(id).error_register = 0x01; // diagnostic code: no error - BX_CONTROLLER(id).head_no = 0; - BX_CONTROLLER(id).sector_count = 1; - BX_CONTROLLER(id).sector_no = 1; - BX_CONTROLLER(id).cylinder_no = 0; - BX_CONTROLLER(id).current_command = 0x00; - BX_CONTROLLER(id).buffer_index = 0; - - BX_CONTROLLER(id).control.reset = 0; - BX_CONTROLLER(id).control.disable_irq = 0; - - BX_CONTROLLER(id).reset_in_progress = 0; - - BX_CONTROLLER(id).sectors_per_block = 0x80; - BX_CONTROLLER(id).lba_mode = 0; - - BX_CONTROLLER(id).features = 0; - } } void @@ -406,27 +461,47 @@ Bit16u value16; Bit32u value32; - if (io_len>1 && address!=0x1f0) { + Bit8u channel = BX_MAX_ATA_CHANNEL; + Bit32u port; + + for (channel=0; channel= BX_HD_THIS channels[channel].ioaddr1) + && (address <= BX_HD_THIS channels[channel].ioaddr1 + 7) ) { + port = address - BX_HD_THIS channels[channel].ioaddr1; + break; + } + else if ((address >= BX_HD_THIS channels[channel].ioaddr2) + && (address <= BX_HD_THIS channels[channel].ioaddr2 + 7) ) { + port = address - BX_HD_THIS channels[channel].ioaddr2 + 0x10; + break; + } + } + + if (channel == BX_MAX_ATA_CHANNEL) { + BX_PANIC(("Unable to find ATA channel, ioport=0x%04x", address)); + } + + if (io_len>1 && port!=0x00) { BX_PANIC(("non-byte IO read to %04x", (unsigned) address)); } - switch (address) { - case 0x1f0: // hard disk data (16bit) - if (BX_SELECTED_CONTROLLER.status.drq == 0) { + switch (port) { + case 0x00: // hard disk data (16bit) 0x1f0 + if (BX_SELECTED_CONTROLLER(channel).status.drq == 0) { BX_ERROR(("IO read(1f0h) with drq == 0: last command was %02xh", - (unsigned) BX_SELECTED_CONTROLLER.current_command)); + (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); return(0); } BX_DEBUG(("IO read(1f0h): current command is %02xh", - (unsigned) BX_SELECTED_CONTROLLER.current_command)); - switch (BX_SELECTED_CONTROLLER.current_command) { + (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); + switch (BX_SELECTED_CONTROLLER(channel).current_command) { case 0x20: // READ SECTORS, with retries case 0x21: // READ SECTORS, without retries if (io_len == 1) { BX_PANIC(("byte IO read from %04x", (unsigned) address)); } - if (BX_SELECTED_CONTROLLER.buffer_index >= 512) + if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) BX_PANIC(("IO read(1f0): buffer_index >= 512")); #if BX_SupportRepeatSpeedups @@ -455,70 +530,69 @@ value32 = 0L; switch(io_len){ case 4: - value32 |= (BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index+3] << 24); - value32 |= (BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index+2] << 16); + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+3] << 24); + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+2] << 16); case 2: - value32 |= (BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index+1] << 8); - value32 |= BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index]; + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] << 8); + value32 |= BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index]; } - - BX_SELECTED_CONTROLLER.buffer_index += io_len; } + BX_SELECTED_CONTROLLER(channel).buffer_index += io_len; // if buffer completely read - if (BX_SELECTED_CONTROLLER.buffer_index >= 512) { + if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) { // update sector count, sector number, cylinder, // drive, head, status // if there are more sectors, read next one in... // - BX_SELECTED_CONTROLLER.buffer_index = 0; + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - increment_address(); + increment_address(channel); - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; if (bx_options.OnewHardDriveSupport->get ()) - BX_SELECTED_CONTROLLER.status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; else - BX_SELECTED_CONTROLLER.status.seek_complete = 0; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; - if (BX_SELECTED_CONTROLLER.sector_count==0) { - BX_SELECTED_CONTROLLER.status.drq = 0; + if (BX_SELECTED_CONTROLLER(channel).sector_count==0) { + BX_SELECTED_CONTROLLER(channel).status.drq = 0; } else { /* read next one into controller buffer */ Bit32u logical_sector; int ret; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; #if TEST_READ_BEYOND_END==1 - BX_SELECTED_CONTROLLER.cylinder_no += 100000; + BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000; #endif - if (!calculate_logical_address(&logical_sector)) { + if (!calculate_logical_address(channel, &logical_sector)) { BX_ERROR(("multi-sector read reached invalid sector %u, aborting", logical_sector)); - command_aborted (BX_SELECTED_CONTROLLER.current_command); + command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); GOTO_RETURN_VALUE ; } - ret = BX_SELECTED_HD.hard_drive->lseek(logical_sector * 512, SEEK_SET); + ret = BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET); if (ret < 0) { BX_ERROR(("could not lseek() hard drive image file")); - command_aborted (BX_SELECTED_CONTROLLER.current_command); + command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); GOTO_RETURN_VALUE ; } - ret = BX_SELECTED_HD.hard_drive->read((bx_ptr_t) BX_SELECTED_CONTROLLER.buffer, 512); + ret = BX_SELECTED_DRIVE(channel).hard_drive->read((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512); if (ret < 512) { BX_ERROR(("logical sector was %u", (unsigned) logical_sector)); BX_ERROR(("could not read() hard drive image file at byte %d", logical_sector*512)); - command_aborted (BX_SELECTED_CONTROLLER.current_command); + command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); GOTO_RETURN_VALUE ; } - BX_SELECTED_CONTROLLER.buffer_index = 0; - raise_interrupt(); + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; + raise_interrupt(channel); } } GOTO_RETURN_VALUE ; @@ -529,61 +603,61 @@ if (bx_options.OnewHardDriveSupport->get ()) { unsigned index; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.write_fault = 0; - BX_SELECTED_CONTROLLER.status.seek_complete = 1; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; - index = BX_SELECTED_CONTROLLER.buffer_index; - value32 = BX_SELECTED_CONTROLLER.buffer[index]; + index = BX_SELECTED_CONTROLLER(channel).buffer_index; + value32 = BX_SELECTED_CONTROLLER(channel).buffer[index]; index++; if (io_len >= 2) { - value32 |= (BX_SELECTED_CONTROLLER.buffer[index] << 8); + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index] << 8); index++; } if (io_len == 4) { - value32 |= (BX_SELECTED_CONTROLLER.buffer[index] << 16); - value32 |= (BX_SELECTED_CONTROLLER.buffer[index+1] << 24); + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index] << 16); + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+1] << 24); index += 2; } - BX_SELECTED_CONTROLLER.buffer_index = index; + BX_SELECTED_CONTROLLER(channel).buffer_index = index; - if (BX_SELECTED_CONTROLLER.buffer_index >= 512) { - BX_SELECTED_CONTROLLER.status.drq = 0; - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) + if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) { + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) BX_INFO(("Read all drive ID Bytes ...")); } GOTO_RETURN_VALUE; } else BX_PANIC(("IO read(1f0h): current command is %02xh", - (unsigned) BX_SELECTED_CONTROLLER.current_command)); + (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); case 0xa0: { - unsigned index = BX_SELECTED_CONTROLLER.buffer_index; + unsigned index = BX_SELECTED_CONTROLLER(channel).buffer_index; unsigned increment = 0; // Load block if necessary if (index >= 2048) { if (index > 2048) BX_PANIC(("index > 2048 : 0x%x",index)); - switch (BX_SELECTED_HD.atapi.command) { + switch (BX_SELECTED_DRIVE(channel).atapi.command) { case 0x28: // read (10) case 0xa8: // read (12) #ifdef LOWLEVEL_CDROM - BX_SELECTED_HD.cdrom.cd->read_block(BX_SELECTED_CONTROLLER.buffer, - BX_SELECTED_HD.cdrom.next_lba); - BX_SELECTED_HD.cdrom.next_lba++; - BX_SELECTED_HD.cdrom.remaining_blocks--; + BX_SELECTED_DRIVE(channel).cdrom.cd->read_block(BX_SELECTED_CONTROLLER(channel).buffer, + BX_SELECTED_DRIVE(channel).cdrom.next_lba); + BX_SELECTED_DRIVE(channel).cdrom.next_lba++; + BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks--; - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) - if (!BX_SELECTED_HD.cdrom.remaining_blocks) + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) + if (!BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks) BX_INFO(("Last READ block loaded {CDROM}")); else BX_INFO(("READ block loaded (%d remaining) {CDROM}", - BX_SELECTED_HD.cdrom.remaining_blocks)); + BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks)); // one block transfered, start at beginning index = 0; @@ -597,55 +671,55 @@ } } - value32 = BX_SELECTED_CONTROLLER.buffer[index+increment]; + value32 = BX_SELECTED_CONTROLLER(channel).buffer[index+increment]; increment++; if (io_len >= 2) { - value32 |= (BX_SELECTED_CONTROLLER.buffer[index+increment] << 8); + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment] << 8); increment++; } if (io_len == 4) { - value32 |= (BX_SELECTED_CONTROLLER.buffer[index+increment] << 16); - value32 |= (BX_SELECTED_CONTROLLER.buffer[index+increment+1] << 24); + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment] << 16); + value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment+1] << 24); increment += 2; } - BX_SELECTED_CONTROLLER.buffer_index = index + increment; - BX_SELECTED_CONTROLLER.drq_index += increment; + BX_SELECTED_CONTROLLER(channel).buffer_index = index + increment; + BX_SELECTED_CONTROLLER(channel).drq_index += increment; - if (BX_SELECTED_CONTROLLER.drq_index >= (unsigned)BX_SELECTED_HD.atapi.drq_bytes) { - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.drq_index = 0; + if (BX_SELECTED_CONTROLLER(channel).drq_index >= (unsigned)BX_SELECTED_DRIVE(channel).atapi.drq_bytes) { + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).drq_index = 0; - BX_SELECTED_HD.atapi.total_bytes_remaining -= BX_SELECTED_HD.atapi.drq_bytes; + BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining -= BX_SELECTED_DRIVE(channel).atapi.drq_bytes; - if (BX_SELECTED_HD.atapi.total_bytes_remaining > 0) { + if (BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining > 0) { // one or more blocks remaining (works only for single block commands) - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) BX_INFO(("PACKET drq bytes read")); - BX_SELECTED_CONTROLLER.interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.interrupt_reason.c_d = 0; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 0; // set new byte count if last block - if (BX_SELECTED_HD.atapi.total_bytes_remaining < BX_SELECTED_CONTROLLER.byte_count) { - BX_SELECTED_CONTROLLER.byte_count = BX_SELECTED_HD.atapi.total_bytes_remaining; + if (BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining < BX_SELECTED_CONTROLLER(channel).byte_count) { + BX_SELECTED_CONTROLLER(channel).byte_count = BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining; } - BX_SELECTED_HD.atapi.drq_bytes = BX_SELECTED_CONTROLLER.byte_count; + BX_SELECTED_DRIVE(channel).atapi.drq_bytes = BX_SELECTED_CONTROLLER(channel).byte_count; - raise_interrupt(); + raise_interrupt(channel); } else { // all bytes read - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) BX_INFO(("PACKET all bytes read")); - BX_SELECTED_CONTROLLER.interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER.interrupt_reason.c_d = 1; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.interrupt_reason.rel = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; - raise_interrupt(); + raise_interrupt(channel); } } GOTO_RETURN_VALUE; @@ -655,111 +729,111 @@ // List all the read operations that are defined in the ATA/ATAPI spec // that we don't support. Commands that are listed here will cause a // BX_ERROR, which is non-fatal, and the command will be aborted. - case 0x08: BX_ERROR(("read cmd 0x08 (DEVICE RESET) not supported")); command_aborted(0x08); break; - case 0x10: BX_ERROR(("read cmd 0x10 (RECALIBRATE) not supported")); command_aborted(0x10); break; - case 0x22: BX_ERROR(("read cmd 0x22 (READ LONG) not supported")); command_aborted(0x22); break; - case 0x23: BX_ERROR(("read cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(0x23); break; - case 0x24: BX_ERROR(("read cmd 0x24 (READ SECTORS EXT) not supported")); command_aborted(0x24); break; - case 0x25: BX_ERROR(("read cmd 0x25 (READ DMA EXT) not supported")); command_aborted(0x25); break; - case 0x26: BX_ERROR(("read cmd 0x26 (READ DMA QUEUED EXT) not supported")); command_aborted(0x26); break; - case 0x27: BX_ERROR(("read cmd 0x27 (READ NATIVE MAX ADDRESS EXT) not supported")); command_aborted(0x27); break; - case 0x29: BX_ERROR(("read cmd 0x29 (READ MULTIPLE EXT) not supported")); command_aborted(0x29); break; - case 0x2A: BX_ERROR(("read cmd 0x2A (READ STREAM DMA) not supported")); command_aborted(0x2A); break; - case 0x2B: BX_ERROR(("read cmd 0x2B (READ STREAM PIO) not supported")); command_aborted(0x2B); break; - case 0x2F: BX_ERROR(("read cmd 0x2F (READ LOG EXT) not supported")); command_aborted(0x2F); break; - case 0x30: BX_ERROR(("read cmd 0x30 (WRITE SECTORS) not supported")); command_aborted(0x30); break; - case 0x31: BX_ERROR(("read cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(0x31); break; - case 0x32: BX_ERROR(("read cmd 0x32 (WRITE LONG) not supported")); command_aborted(0x32); break; - case 0x33: BX_ERROR(("read cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(0x33); break; - case 0x34: BX_ERROR(("read cmd 0x34 (WRITE SECTORS EXT) not supported")); command_aborted(0x34); break; - case 0x35: BX_ERROR(("read cmd 0x35 (WRITE DMA EXT) not supported")); command_aborted(0x35); break; - case 0x36: BX_ERROR(("read cmd 0x36 (WRITE DMA QUEUED EXT) not supported")); command_aborted(0x36); break; - case 0x37: BX_ERROR(("read cmd 0x37 (SET MAX ADDRESS EXT) not supported")); command_aborted(0x37); break; - case 0x38: BX_ERROR(("read cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported")); command_aborted(0x38); break; - case 0x39: BX_ERROR(("read cmd 0x39 (WRITE MULTIPLE EXT) not supported")); command_aborted(0x39); break; - case 0x3A: BX_ERROR(("read cmd 0x3A (WRITE STREAM DMA) not supported")); command_aborted(0x3A); break; - case 0x3B: BX_ERROR(("read cmd 0x3B (WRITE STREAM PIO) not supported")); command_aborted(0x3B); break; - case 0x3F: BX_ERROR(("read cmd 0x3F (WRITE LOG EXT) not supported")); command_aborted(0x3F); break; - case 0x40: BX_ERROR(("read cmd 0x40 (READ VERIFY SECTORS) not supported")); command_aborted(0x40); break; - case 0x41: BX_ERROR(("read cmd 0x41 (READ VERIFY SECTORS NO RETRY) not supported")); command_aborted(0x41); break; - case 0x42: BX_ERROR(("read cmd 0x42 (READ VERIFY SECTORS EXT) not supported")); command_aborted(0x42); break; - case 0x50: BX_ERROR(("read cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(0x50); break; - case 0x51: BX_ERROR(("read cmd 0x51 (CONFIGURE STREAM) not supported")); command_aborted(0x51); break; - case 0x70: BX_ERROR(("read cmd 0x70 (SEEK) not supported")); command_aborted(0x70); break; - case 0x87: BX_ERROR(("read cmd 0x87 (CFA TRANSLATE SECTOR) not supported")); command_aborted(0x87); break; - case 0x90: BX_ERROR(("read cmd 0x90 (EXECUTE DEVICE DIAGNOSTIC) not supported")); command_aborted(0x90); break; - case 0x91: BX_ERROR(("read cmd 0x91 (INITIALIZE DEVICE PARAMETERS) not supported")); command_aborted(0x91); break; - case 0x92: BX_ERROR(("read cmd 0x92 (DOWNLOAD MICROCODE) not supported")); command_aborted(0x92); break; - case 0x94: BX_ERROR(("read cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(0x94); break; - case 0x95: BX_ERROR(("read cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(0x95); break; - case 0x96: BX_ERROR(("read cmd 0x96 (STANDBY) not supported")); command_aborted(0x96); break; - case 0x97: BX_ERROR(("read cmd 0x97 (IDLE) not supported")); command_aborted(0x97); break; - case 0x98: BX_ERROR(("read cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(0x98); break; - case 0x99: BX_ERROR(("read cmd 0x99 (SLEEP) not supported")); command_aborted(0x99); break; - case 0xA2: BX_ERROR(("read cmd 0xA2 (SERVICE) not supported")); command_aborted(0xA2); break; - case 0xB0: BX_ERROR(("read cmd 0xB0 (SMART DISABLE OPERATIONS) not supported")); command_aborted(0xB0); break; - case 0xB1: BX_ERROR(("read cmd 0xB1 (DEVICE CONFIGURATION FREEZE LOCK) not supported")); command_aborted(0xB1); break; - case 0xC0: BX_ERROR(("read cmd 0xC0 (CFA ERASE SECTORS) not supported")); command_aborted(0xC0); break; - case 0xC4: BX_ERROR(("read cmd 0xC4 (READ MULTIPLE) not supported")); command_aborted(0xC4); break; - case 0xC5: BX_ERROR(("read cmd 0xC5 (WRITE MULTIPLE) not supported")); command_aborted(0xC5); break; - case 0xC6: BX_ERROR(("read cmd 0xC6 (SET MULTIPLE MODE) not supported")); command_aborted(0xC6); break; - case 0xC7: BX_ERROR(("read cmd 0xC7 (READ DMA QUEUED) not supported")); command_aborted(0xC7); break; - case 0xC8: BX_ERROR(("read cmd 0xC8 (READ DMA) not supported")); command_aborted(0xC8); break; - case 0xC9: BX_ERROR(("read cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(0xC9); break; - case 0xCA: BX_ERROR(("read cmd 0xCA (WRITE DMA) not supported")); command_aborted(0xCA); break; - case 0xCC: BX_ERROR(("read cmd 0xCC (WRITE DMA QUEUED) not supported")); command_aborted(0xCC); break; - case 0xCD: BX_ERROR(("read cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported")); command_aborted(0xCD); break; - case 0xD1: BX_ERROR(("read cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported")); command_aborted(0xD1); break; - case 0xDA: BX_ERROR(("read cmd 0xDA (GET MEDIA STATUS) not supported")); command_aborted(0xDA); break; - case 0xDE: BX_ERROR(("read cmd 0xDE (MEDIA LOCK) not supported")); command_aborted(0xDE); break; - case 0xDF: BX_ERROR(("read cmd 0xDF (MEDIA UNLOCK) not supported")); command_aborted(0xDF); break; - case 0xE0: BX_ERROR(("read cmd 0xE0 (STANDBY IMMEDIATE) not supported")); command_aborted(0xE0); break; - case 0xE1: BX_ERROR(("read cmd 0xE1 (IDLE IMMEDIATE) not supported")); command_aborted(0xE1); break; - case 0xE2: BX_ERROR(("read cmd 0xE2 (STANDBY) not supported")); command_aborted(0xE2); break; - case 0xE3: BX_ERROR(("read cmd 0xE3 (IDLE) not supported")); command_aborted(0xE3); break; - case 0xE4: BX_ERROR(("read cmd 0xE4 (READ BUFFER) not supported")); command_aborted(0xE4); break; - case 0xE5: BX_ERROR(("read cmd 0xE5 (CHECK POWER MODE) not supported")); command_aborted(0xE5); break; - case 0xE6: BX_ERROR(("read cmd 0xE6 (SLEEP) not supported")); command_aborted(0xE6); break; - case 0xE7: BX_ERROR(("read cmd 0xE7 (FLUSH CACHE) not supported")); command_aborted(0xE7); break; - case 0xE8: BX_ERROR(("read cmd 0xE8 (WRITE BUFFER) not supported")); command_aborted(0xE8); break; - case 0xEA: BX_ERROR(("read cmd 0xEA (FLUSH CACHE EXT) not supported")); command_aborted(0xEA); break; - case 0xED: BX_ERROR(("read cmd 0xED (MEDIA EJECT) not supported")); command_aborted(0xED); break; - case 0xEF: BX_ERROR(("read cmd 0xEF (SET FEATURES) not supported")); command_aborted(0xEF); break; - case 0xF1: BX_ERROR(("read cmd 0xF1 (SECURITY SET PASSWORD) not supported")); command_aborted(0xF1); break; - case 0xF2: BX_ERROR(("read cmd 0xF2 (SECURITY UNLOCK) not supported")); command_aborted(0xF2); break; - case 0xF3: BX_ERROR(("read cmd 0xF3 (SECURITY ERASE PREPARE) not supported")); command_aborted(0xF3); break; - case 0xF4: BX_ERROR(("read cmd 0xF4 (SECURITY ERASE UNIT) not supported")); command_aborted(0xF4); break; - case 0xF5: BX_ERROR(("read cmd 0xF5 (SECURITY FREEZE LOCK) not supported")); command_aborted(0xF5); break; - case 0xF6: BX_ERROR(("read cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported")); command_aborted(0xF6); break; - case 0xF8: BX_ERROR(("read cmd 0xF8 (READ NATIVE MAX ADDRESS) not supported")); command_aborted(0xF8); break; - case 0xF9: BX_ERROR(("read cmd 0xF9 (SET MAX ADDRESS) not supported")); command_aborted(0xF9); break; + case 0x08: BX_ERROR(("read cmd 0x08 (DEVICE RESET) not supported")); command_aborted(channel, 0x08); break; + case 0x10: BX_ERROR(("read cmd 0x10 (RECALIBRATE) not supported")); command_aborted(channel, 0x10); break; + case 0x22: BX_ERROR(("read cmd 0x22 (READ LONG) not supported")); command_aborted(channel, 0x22); break; + case 0x23: BX_ERROR(("read cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(channel, 0x23); break; + case 0x24: BX_ERROR(("read cmd 0x24 (READ SECTORS EXT) not supported")); command_aborted(channel, 0x24); break; + case 0x25: BX_ERROR(("read cmd 0x25 (READ DMA EXT) not supported")); command_aborted(channel, 0x25); break; + case 0x26: BX_ERROR(("read cmd 0x26 (READ DMA QUEUED EXT) not supported")); command_aborted(channel, 0x26); break; + case 0x27: BX_ERROR(("read cmd 0x27 (READ NATIVE MAX ADDRESS EXT) not supported")); command_aborted(channel, 0x27); break; + case 0x29: BX_ERROR(("read cmd 0x29 (READ MULTIPLE EXT) not supported")); command_aborted(channel, 0x29); break; + case 0x2A: BX_ERROR(("read cmd 0x2A (READ STREAM DMA) not supported")); command_aborted(channel, 0x2A); break; + case 0x2B: BX_ERROR(("read cmd 0x2B (READ STREAM PIO) not supported")); command_aborted(channel, 0x2B); break; + case 0x2F: BX_ERROR(("read cmd 0x2F (READ LOG EXT) not supported")); command_aborted(channel, 0x2F); break; + case 0x30: BX_ERROR(("read cmd 0x30 (WRITE SECTORS) not supported")); command_aborted(channel, 0x30); break; + case 0x31: BX_ERROR(("read cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(channel, 0x31); break; + case 0x32: BX_ERROR(("read cmd 0x32 (WRITE LONG) not supported")); command_aborted(channel, 0x32); break; + case 0x33: BX_ERROR(("read cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(channel, 0x33); break; + case 0x34: BX_ERROR(("read cmd 0x34 (WRITE SECTORS EXT) not supported")); command_aborted(channel, 0x34); break; + case 0x35: BX_ERROR(("read cmd 0x35 (WRITE DMA EXT) not supported")); command_aborted(channel, 0x35); break; + case 0x36: BX_ERROR(("read cmd 0x36 (WRITE DMA QUEUED EXT) not supported")); command_aborted(channel, 0x36); break; + case 0x37: BX_ERROR(("read cmd 0x37 (SET MAX ADDRESS EXT) not supported")); command_aborted(channel, 0x37); break; + case 0x38: BX_ERROR(("read cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported")); command_aborted(channel, 0x38); break; + case 0x39: BX_ERROR(("read cmd 0x39 (WRITE MULTIPLE EXT) not supported")); command_aborted(channel, 0x39); break; + case 0x3A: BX_ERROR(("read cmd 0x3A (WRITE STREAM DMA) not supported")); command_aborted(channel, 0x3A); break; + case 0x3B: BX_ERROR(("read cmd 0x3B (WRITE STREAM PIO) not supported")); command_aborted(channel, 0x3B); break; + case 0x3F: BX_ERROR(("read cmd 0x3F (WRITE LOG EXT) not supported")); command_aborted(channel, 0x3F); break; + case 0x40: BX_ERROR(("read cmd 0x40 (READ VERIFY SECTORS) not supported")); command_aborted(channel, 0x40); break; + case 0x41: BX_ERROR(("read cmd 0x41 (READ VERIFY SECTORS NO RETRY) not supported")); command_aborted(channel, 0x41); break; + case 0x42: BX_ERROR(("read cmd 0x42 (READ VERIFY SECTORS EXT) not supported")); command_aborted(channel, 0x42); break; + case 0x50: BX_ERROR(("read cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(channel, 0x50); break; + case 0x51: BX_ERROR(("read cmd 0x51 (CONFIGURE STREAM) not supported")); command_aborted(channel, 0x51); break; + case 0x70: BX_ERROR(("read cmd 0x70 (SEEK) not supported")); command_aborted(channel, 0x70); break; + case 0x87: BX_ERROR(("read cmd 0x87 (CFA TRANSLATE SECTOR) not supported")); command_aborted(channel, 0x87); break; + case 0x90: BX_ERROR(("read cmd 0x90 (EXECUTE DEVICE DIAGNOSTIC) not supported")); command_aborted(channel, 0x90); break; + case 0x91: BX_ERROR(("read cmd 0x91 (INITIALIZE DEVICE PARAMETERS) not supported")); command_aborted(channel, 0x91); break; + case 0x92: BX_ERROR(("read cmd 0x92 (DOWNLOAD MICROCODE) not supported")); command_aborted(channel, 0x92); break; + case 0x94: BX_ERROR(("read cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0x94); break; + case 0x95: BX_ERROR(("read cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0x95); break; + case 0x96: BX_ERROR(("read cmd 0x96 (STANDBY) not supported")); command_aborted(channel, 0x96); break; + case 0x97: BX_ERROR(("read cmd 0x97 (IDLE) not supported")); command_aborted(channel, 0x97); break; + case 0x98: BX_ERROR(("read cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(channel, 0x98); break; + case 0x99: BX_ERROR(("read cmd 0x99 (SLEEP) not supported")); command_aborted(channel, 0x99); break; + case 0xA2: BX_ERROR(("read cmd 0xA2 (SERVICE) not supported")); command_aborted(channel, 0xA2); break; + case 0xB0: BX_ERROR(("read cmd 0xB0 (SMART DISABLE OPERATIONS) not supported")); command_aborted(channel, 0xB0); break; + case 0xB1: BX_ERROR(("read cmd 0xB1 (DEVICE CONFIGURATION FREEZE LOCK) not supported")); command_aborted(channel, 0xB1); break; + case 0xC0: BX_ERROR(("read cmd 0xC0 (CFA ERASE SECTORS) not supported")); command_aborted(channel, 0xC0); break; + case 0xC4: BX_ERROR(("read cmd 0xC4 (READ MULTIPLE) not supported")); command_aborted(channel, 0xC4); break; + case 0xC5: BX_ERROR(("read cmd 0xC5 (WRITE MULTIPLE) not supported")); command_aborted(channel, 0xC5); break; + case 0xC6: BX_ERROR(("read cmd 0xC6 (SET MULTIPLE MODE) not supported")); command_aborted(channel, 0xC6); break; + case 0xC7: BX_ERROR(("read cmd 0xC7 (READ DMA QUEUED) not supported")); command_aborted(channel, 0xC7); break; + case 0xC8: BX_ERROR(("read cmd 0xC8 (READ DMA) not supported")); command_aborted(channel, 0xC8); break; + case 0xC9: BX_ERROR(("read cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(channel, 0xC9); break; + case 0xCA: BX_ERROR(("read cmd 0xCA (WRITE DMA) not supported")); command_aborted(channel, 0xCA); break; + case 0xCC: BX_ERROR(("read cmd 0xCC (WRITE DMA QUEUED) not supported")); command_aborted(channel, 0xCC); break; + case 0xCD: BX_ERROR(("read cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported")); command_aborted(channel, 0xCD); break; + case 0xD1: BX_ERROR(("read cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported")); command_aborted(channel, 0xD1); break; + case 0xDA: BX_ERROR(("read cmd 0xDA (GET MEDIA STATUS) not supported")); command_aborted(channel, 0xDA); break; + case 0xDE: BX_ERROR(("read cmd 0xDE (MEDIA LOCK) not supported")); command_aborted(channel, 0xDE); break; + case 0xDF: BX_ERROR(("read cmd 0xDF (MEDIA UNLOCK) not supported")); command_aborted(channel, 0xDF); break; + case 0xE0: BX_ERROR(("read cmd 0xE0 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0xE0); break; + case 0xE1: BX_ERROR(("read cmd 0xE1 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0xE1); break; + case 0xE2: BX_ERROR(("read cmd 0xE2 (STANDBY) not supported")); command_aborted(channel, 0xE2); break; + case 0xE3: BX_ERROR(("read cmd 0xE3 (IDLE) not supported")); command_aborted(channel, 0xE3); break; + case 0xE4: BX_ERROR(("read cmd 0xE4 (READ BUFFER) not supported")); command_aborted(channel, 0xE4); break; + case 0xE5: BX_ERROR(("read cmd 0xE5 (CHECK POWER MODE) not supported")); command_aborted(channel, 0xE5); break; + case 0xE6: BX_ERROR(("read cmd 0xE6 (SLEEP) not supported")); command_aborted(channel, 0xE6); break; + case 0xE7: BX_ERROR(("read cmd 0xE7 (FLUSH CACHE) not supported")); command_aborted(channel, 0xE7); break; + case 0xE8: BX_ERROR(("read cmd 0xE8 (WRITE BUFFER) not supported")); command_aborted(channel, 0xE8); break; + case 0xEA: BX_ERROR(("read cmd 0xEA (FLUSH CACHE EXT) not supported")); command_aborted(channel, 0xEA); break; + case 0xED: BX_ERROR(("read cmd 0xED (MEDIA EJECT) not supported")); command_aborted(channel, 0xED); break; + case 0xEF: BX_ERROR(("read cmd 0xEF (SET FEATURES) not supported")); command_aborted(channel, 0xEF); break; + case 0xF1: BX_ERROR(("read cmd 0xF1 (SECURITY SET PASSWORD) not supported")); command_aborted(channel, 0xF1); break; + case 0xF2: BX_ERROR(("read cmd 0xF2 (SECURITY UNLOCK) not supported")); command_aborted(channel, 0xF2); break; + case 0xF3: BX_ERROR(("read cmd 0xF3 (SECURITY ERASE PREPARE) not supported")); command_aborted(channel, 0xF3); break; + case 0xF4: BX_ERROR(("read cmd 0xF4 (SECURITY ERASE UNIT) not supported")); command_aborted(channel, 0xF4); break; + case 0xF5: BX_ERROR(("read cmd 0xF5 (SECURITY FREEZE LOCK) not supported")); command_aborted(channel, 0xF5); break; + case 0xF6: BX_ERROR(("read cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported")); command_aborted(channel, 0xF6); break; + case 0xF8: BX_ERROR(("read cmd 0xF8 (READ NATIVE MAX ADDRESS) not supported")); command_aborted(channel, 0xF8); break; + case 0xF9: BX_ERROR(("read cmd 0xF9 (SET MAX ADDRESS) not supported")); command_aborted(channel, 0xF9); break; default: BX_PANIC(("IO read(1f0h): current command is %02xh", - (unsigned) BX_SELECTED_CONTROLLER.current_command)); + (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); } break; - case 0x1f1: // hard disk error register - BX_SELECTED_CONTROLLER.status.err = 0; - value8 = BX_SELECTED_CONTROLLER.error_register; + case 0x01: // hard disk error register 0x1f1 + BX_SELECTED_CONTROLLER(channel).status.err = 0; + value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).error_register; goto return_value8; break; - case 0x1f2: // hard disk sector count / interrupt reason - value8 = BX_SELECTED_CONTROLLER.sector_count; + case 0x02: // hard disk sector count / interrupt reason 0x1f2 + value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).sector_count; goto return_value8; break; - case 0x1f3: // sector number - value8 = BX_SELECTED_CONTROLLER.sector_no; + case 0x03: // sector number 0x1f3 + value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).sector_no; goto return_value8; - case 0x1f4: // cylinder low - value8 = (BX_SELECTED_CONTROLLER.cylinder_no & 0x00ff); + case 0x04: // cylinder low 0x1f4 + value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : (BX_SELECTED_CONTROLLER(channel).cylinder_no & 0x00ff); goto return_value8; - case 0x1f5: // cylinder high - value8 = BX_SELECTED_CONTROLLER.cylinder_no >> 8; + case 0x05: // cylinder high 0x1f5 + value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).cylinder_no >> 8; goto return_value8; - case 0x1f6: // hard disk drive and head register + case 0x06: // hard disk drive and head register 0x1f6 // b7 Extended data field for ECC // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128 // Since 512 was always used, bit 6 was taken to mean LBA mode: @@ -768,42 +842,41 @@ // b4: DRV // b3..0 HD3..HD0 value8 = (1 << 7) | - ((BX_SELECTED_CONTROLLER.lba_mode>0) << 6) | + ((BX_SELECTED_CONTROLLER(channel).lba_mode>0) << 6) | (1 << 5) | // 01b = 512 sector size - (BX_HD_THIS drive_select << 4) | - (BX_SELECTED_CONTROLLER.head_no << 0); + (BX_HD_THIS channels[channel].drive_select << 4) | + (BX_SELECTED_CONTROLLER(channel).head_no << 0); goto return_value8; break; -//BX_CONTROLLER(0).lba_mode +//BX_CONTROLLER(channel,0).lba_mode - case 0x1f7: // Hard Disk Status - case 0x3f6: // Hard Disk Alternate Status - if ((!BX_HD_THIS drive_select && !bx_options.diskc.Opresent->get ()) || - (BX_HD_THIS drive_select && !bx_options.diskd.Opresent->get ())) { + case 0x07: // Hard Disk Status 0x1f7 + case 0x16: // Hard Disk Alternate Status 0x3f6 + if (!BX_SELECTED_IS_PRESENT(channel)) { // (mch) Just return zero for these registers value8 = 0; } else { value8 = ( - (BX_SELECTED_CONTROLLER.status.busy << 7) | - (BX_SELECTED_CONTROLLER.status.drive_ready << 6) | - (BX_SELECTED_CONTROLLER.status.write_fault << 5) | - (BX_SELECTED_CONTROLLER.status.seek_complete << 4) | - (BX_SELECTED_CONTROLLER.status.drq << 3) | - (BX_SELECTED_CONTROLLER.status.corrected_data << 2) | - (BX_SELECTED_CONTROLLER.status.index_pulse << 1) | - (BX_SELECTED_CONTROLLER.status.err) ); - BX_SELECTED_CONTROLLER.status.index_pulse_count++; - BX_SELECTED_CONTROLLER.status.index_pulse = 0; - if (BX_SELECTED_CONTROLLER.status.index_pulse_count >= INDEX_PULSE_CYCLE) { - BX_SELECTED_CONTROLLER.status.index_pulse = 1; - BX_SELECTED_CONTROLLER.status.index_pulse_count = 0; + (BX_SELECTED_CONTROLLER(channel).status.busy << 7) | + (BX_SELECTED_CONTROLLER(channel).status.drive_ready << 6) | + (BX_SELECTED_CONTROLLER(channel).status.write_fault << 5) | + (BX_SELECTED_CONTROLLER(channel).status.seek_complete << 4) | + (BX_SELECTED_CONTROLLER(channel).status.drq << 3) | + (BX_SELECTED_CONTROLLER(channel).status.corrected_data << 2) | + (BX_SELECTED_CONTROLLER(channel).status.index_pulse << 1) | + (BX_SELECTED_CONTROLLER(channel).status.err) ); + BX_SELECTED_CONTROLLER(channel).status.index_pulse_count++; + BX_SELECTED_CONTROLLER(channel).status.index_pulse = 0; + if (BX_SELECTED_CONTROLLER(channel).status.index_pulse_count >= INDEX_PULSE_CYCLE) { + BX_SELECTED_CONTROLLER(channel).status.index_pulse = 1; + BX_SELECTED_CONTROLLER(channel).status.index_pulse_count = 0; } } - if (address == 0x1f7) BX_HD_THIS devices->pic->lower_irq(14); + if (port == 0x07) BX_HD_THIS devices->pic->lower_irq(BX_HD_THIS channels[channel].irq); goto return_value8; break; - case 0x3f7: // Hard Disk Address Register + case 0x17: // Hard Disk Address Register 0x3f7 // Obsolete and unsupported register. Not driven by hard // disk controller. Report all 1's. If floppy controller // is handling this address, it will call this function @@ -813,19 +886,6 @@ goto return_value8; break; -#if 0 - // you'll need these to support second IDE controller, not needed yet. - case 0x170: - case 0x171: - case 0x172: - case 0x173: - case 0x174: - case 0x175: - case 0x176: - case 0x177: - BX_INFO(("[disk] ignoring read from 0x%04x", address)); - break; -#endif default: BX_PANIC(("hard drive: io read to address %x unsupported", (unsigned) address)); @@ -836,17 +896,17 @@ return_value32: BX_DEBUG(("32-bit read from %04x = %08x {%s}", - (unsigned) address, value32, DEVICE_TYPE_STRING)); + (unsigned) address, value32, BX_SELECTED_TYPE_STRING(channel))); return value32; return_value16: BX_DEBUG(("16-bit read from %04x = %04x {%s}", - (unsigned) address, value16, DEVICE_TYPE_STRING)); + (unsigned) address, value16, BX_SELECTED_TYPE_STRING(channel))); return value16; return_value8: BX_DEBUG(("8-bit read from %04x = %02x {%s}", - (unsigned) address, value8, DEVICE_TYPE_STRING)); + (unsigned) address, value8, BX_SELECTED_TYPE_STRING(channel))); return value8; } @@ -873,44 +933,64 @@ int ret; Boolean prev_control_reset; - if (io_len>1 && address!=0x1f0) { + Bit8u channel = BX_MAX_ATA_CHANNEL; + Bit32u port; + + for (channel=0; channel= BX_HD_THIS channels[channel].ioaddr1) + && (address <= BX_HD_THIS channels[channel].ioaddr1 + 7) ) { + port = address - BX_HD_THIS channels[channel].ioaddr1; + break; + } + else if ((address >= BX_HD_THIS channels[channel].ioaddr2) + && (address <= BX_HD_THIS channels[channel].ioaddr2 + 7) ) { + port = address - BX_HD_THIS channels[channel].ioaddr2 + 0x10; + break; + } + } + + if (channel == BX_MAX_ATA_CHANNEL) { + BX_PANIC(("Unable to find ATA channel, ioport=0x%04x", address)); + } + + if (io_len>1 && port!=0x00) { BX_PANIC(("non-byte IO write to %04x", (unsigned) address)); } - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) { + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) { switch (io_len) { case 1: BX_INFO(("8-bit write to %04x = %02x {%s}", - (unsigned) address, (unsigned) value, DEVICE_TYPE_STRING)); + (unsigned) address, (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); break; case 2: BX_INFO(("16-bit write to %04x = %04x {%s}", - (unsigned) address, (unsigned) value, DEVICE_TYPE_STRING)); + (unsigned) address, (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); break; case 4: BX_INFO(("32-bit write to %04x = %08x {%s}", - (unsigned) address, (unsigned) value, DEVICE_TYPE_STRING)); + (unsigned) address, (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); break; default: BX_INFO(("unknown-size write to %04x = %08x {%s}", - (unsigned) address, (unsigned) value, DEVICE_TYPE_STRING)); + (unsigned) address, (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); break; } } BX_DEBUG(("IO write to %04x = %02x", (unsigned) address, (unsigned) value)); - switch (address) { - case 0x1f0: + switch (port) { + case 0x00: // 0x1f0 if (io_len == 1) { BX_PANIC(("byte IO write to 0x1f0")); } - switch (BX_SELECTED_CONTROLLER.current_command) { + switch (BX_SELECTED_CONTROLLER(channel).current_command) { case 0x30: // WRITE SECTORS - if (BX_SELECTED_CONTROLLER.buffer_index >= 512) + if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) BX_PANIC(("IO write(1f0): buffer_index >= 512")); #if BX_SupportRepeatSpeedups @@ -938,231 +1018,232 @@ { switch(io_len){ case 4: - BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index+3] = (Bit8u)(value >> 24); - BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index+2] = (Bit8u)(value >> 16); + BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+3] = (Bit8u)(value >> 24); + BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+2] = (Bit8u)(value >> 16); case 2: - BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index+1] = (Bit8u)(value >> 8); - BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index] = (Bit8u) value; + BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] = (Bit8u)(value >> 8); + BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index] = (Bit8u) value; } - BX_SELECTED_CONTROLLER.buffer_index += io_len; + BX_SELECTED_CONTROLLER(channel).buffer_index += io_len; } /* if buffer completely writtten */ - if (BX_SELECTED_CONTROLLER.buffer_index >= 512) { + if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) { Bit32u logical_sector; int ret; #if TEST_WRITE_BEYOND_END==1 - BX_SELECTED_CONTROLLER.cylinder_no += 100000; + BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000; #endif - if (!calculate_logical_address(&logical_sector)) { + if (!calculate_logical_address(channel, &logical_sector)) { BX_ERROR(("write reached invalid sector %u, aborting", logical_sector)); - command_aborted (BX_SELECTED_CONTROLLER.current_command); + command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); return; } #if TEST_WRITE_BEYOND_END==2 logical_sector += 100000; #endif - ret = BX_SELECTED_HD.hard_drive->lseek(logical_sector * 512, SEEK_SET); + ret = BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET); if (ret < 0) { BX_ERROR(("could not lseek() hard drive image file at byte %u", logical_sector * 512)); - command_aborted (BX_SELECTED_CONTROLLER.current_command); + command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); return; } - ret = BX_SELECTED_HD.hard_drive->write((bx_ptr_t) BX_SELECTED_CONTROLLER.buffer, 512); + ret = BX_SELECTED_DRIVE(channel).hard_drive->write((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512); if (ret < 512) { BX_ERROR(("could not write() hard drive image file at byte %d", logical_sector*512)); - command_aborted (BX_SELECTED_CONTROLLER.current_command); + command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); return; } - BX_SELECTED_CONTROLLER.buffer_index = 0; + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; /* update sector count, sector number, cylinder, * drive, head, status * if there are more sectors, read next one in... */ - increment_address(); + increment_address(channel); /* When the write is complete, controller clears the DRQ bit and * sets the BSY bit. * If at least one more sector is to be written, controller sets DRQ bit, - * clears BSY bit, and issues IRQ 14 + * clears BSY bit, and issues IRQ */ - if (BX_SELECTED_CONTROLLER.sector_count!=0) { - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - BX_SELECTED_CONTROLLER.status.err = 0; + if (BX_SELECTED_CONTROLLER(channel).sector_count!=0) { + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; } else { /* no more sectors to write */ - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; } - raise_interrupt(); + raise_interrupt(channel); } break; case 0xa0: // PACKET - if (BX_SELECTED_CONTROLLER.buffer_index >= PACKET_SIZE) + if (BX_SELECTED_CONTROLLER(channel).buffer_index >= PACKET_SIZE) BX_PANIC(("IO write(1f0): buffer_index >= PACKET_SIZE")); - BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index] = value; - BX_SELECTED_CONTROLLER.buffer[BX_SELECTED_CONTROLLER.buffer_index+1] = (value >> 8); - BX_SELECTED_CONTROLLER.buffer_index += 2; + BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index] = value; + BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] = (value >> 8); + BX_SELECTED_CONTROLLER(channel).buffer_index += 2; /* if packet completely writtten */ - if (BX_SELECTED_CONTROLLER.buffer_index >= PACKET_SIZE) { + if (BX_SELECTED_CONTROLLER(channel).buffer_index >= PACKET_SIZE) { // complete command received - Bit8u atapi_command = BX_SELECTED_CONTROLLER.buffer[0]; + Bit8u atapi_command = BX_SELECTED_CONTROLLER(channel).buffer[0]; if (bx_dbg.cdrom) BX_INFO(("cdrom: ATAPI command 0x%x started", atapi_command)); switch (atapi_command) { case 0x00: // test unit ready - if (BX_SELECTED_HD.cdrom.ready) { - atapi_cmd_nop(); + if (BX_SELECTED_DRIVE(channel).cdrom.ready) { + atapi_cmd_nop(channel); } else { - atapi_cmd_error(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); } - raise_interrupt(); + raise_interrupt(channel); break; case 0x03: { // request sense - int alloc_length = BX_SELECTED_CONTROLLER.buffer[4]; - init_send_atapi_command(atapi_command, 18, alloc_length); + int alloc_length = BX_SELECTED_CONTROLLER(channel).buffer[4]; + init_send_atapi_command(channel, atapi_command, 18, alloc_length); // sense data - BX_SELECTED_CONTROLLER.buffer[0] = 0x70 | (1 << 7); - BX_SELECTED_CONTROLLER.buffer[1] = 0; - BX_SELECTED_CONTROLLER.buffer[2] = BX_SELECTED_HD.sense.sense_key; - BX_SELECTED_CONTROLLER.buffer[3] = BX_SELECTED_HD.sense.information.arr[0]; - BX_SELECTED_CONTROLLER.buffer[4] = BX_SELECTED_HD.sense.information.arr[1]; - BX_SELECTED_CONTROLLER.buffer[5] = BX_SELECTED_HD.sense.information.arr[2]; - BX_SELECTED_CONTROLLER.buffer[6] = BX_SELECTED_HD.sense.information.arr[3]; - BX_SELECTED_CONTROLLER.buffer[7] = 17-7; - BX_SELECTED_CONTROLLER.buffer[8] = BX_SELECTED_HD.sense.specific_inf.arr[0]; - BX_SELECTED_CONTROLLER.buffer[9] = BX_SELECTED_HD.sense.specific_inf.arr[1]; - BX_SELECTED_CONTROLLER.buffer[10] = BX_SELECTED_HD.sense.specific_inf.arr[2]; - BX_SELECTED_CONTROLLER.buffer[11] = BX_SELECTED_HD.sense.specific_inf.arr[3]; - BX_SELECTED_CONTROLLER.buffer[12] = BX_SELECTED_HD.sense.asc; - BX_SELECTED_CONTROLLER.buffer[13] = BX_SELECTED_HD.sense.ascq; - BX_SELECTED_CONTROLLER.buffer[14] = BX_SELECTED_HD.sense.fruc; - BX_SELECTED_CONTROLLER.buffer[15] = BX_SELECTED_HD.sense.key_spec.arr[0]; - BX_SELECTED_CONTROLLER.buffer[16] = BX_SELECTED_HD.sense.key_spec.arr[1]; - BX_SELECTED_CONTROLLER.buffer[17] = BX_SELECTED_HD.sense.key_spec.arr[2]; + BX_SELECTED_CONTROLLER(channel).buffer[0] = 0x70 | (1 << 7); + BX_SELECTED_CONTROLLER(channel).buffer[1] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[2] = BX_SELECTED_DRIVE(channel).sense.sense_key; + BX_SELECTED_CONTROLLER(channel).buffer[3] = BX_SELECTED_DRIVE(channel).sense.information.arr[0]; + BX_SELECTED_CONTROLLER(channel).buffer[4] = BX_SELECTED_DRIVE(channel).sense.information.arr[1]; + BX_SELECTED_CONTROLLER(channel).buffer[5] = BX_SELECTED_DRIVE(channel).sense.information.arr[2]; + BX_SELECTED_CONTROLLER(channel).buffer[6] = BX_SELECTED_DRIVE(channel).sense.information.arr[3]; + BX_SELECTED_CONTROLLER(channel).buffer[7] = 17-7; + BX_SELECTED_CONTROLLER(channel).buffer[8] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[0]; + BX_SELECTED_CONTROLLER(channel).buffer[9] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[1]; + BX_SELECTED_CONTROLLER(channel).buffer[10] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[2]; + BX_SELECTED_CONTROLLER(channel).buffer[11] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[3]; + BX_SELECTED_CONTROLLER(channel).buffer[12] = BX_SELECTED_DRIVE(channel).sense.asc; + BX_SELECTED_CONTROLLER(channel).buffer[13] = BX_SELECTED_DRIVE(channel).sense.ascq; + BX_SELECTED_CONTROLLER(channel).buffer[14] = BX_SELECTED_DRIVE(channel).sense.fruc; + BX_SELECTED_CONTROLLER(channel).buffer[15] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[0]; + BX_SELECTED_CONTROLLER(channel).buffer[16] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[1]; + BX_SELECTED_CONTROLLER(channel).buffer[17] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[2]; - ready_to_send_atapi(); + ready_to_send_atapi(channel); } break; case 0x1b: { // start stop unit - //Boolean Immed = (BX_SELECTED_CONTROLLER.buffer[1] >> 0) & 1; - Boolean LoEj = (BX_SELECTED_CONTROLLER.buffer[4] >> 1) & 1; - Boolean Start = (BX_SELECTED_CONTROLLER.buffer[4] >> 0) & 1; + //Boolean Immed = (BX_SELECTED_CONTROLLER(channel).buffer[1] >> 0) & 1; + Boolean LoEj = (BX_SELECTED_CONTROLLER(channel).buffer[4] >> 1) & 1; + Boolean Start = (BX_SELECTED_CONTROLLER(channel).buffer[4] >> 0) & 1; if (!LoEj && !Start) { // stop the disc BX_PANIC(("Stop disc not implemented")); } else if (!LoEj && Start) { // start the disc and read the TOC // BX_PANIC(("Start disc not implemented")); BX_ERROR(("FIXME: ATAPI start disc not reading TOC")); - atapi_cmd_nop(); - raise_interrupt(); + atapi_cmd_nop(channel); + raise_interrupt(channel); } else if (LoEj && !Start) { // Eject the disc - atapi_cmd_nop(); - if (BX_HD_THIS s[1].cdrom.ready) { + atapi_cmd_nop(channel); + + if (BX_SELECTED_DRIVE(channel).cdrom.ready) { #ifdef LOWLEVEL_CDROM - BX_HD_THIS s[1].cdrom.cd->eject_cdrom(); + BX_SELECTED_DRIVE(channel).cdrom.cd->eject_cdrom(); #endif - BX_HD_THIS s[1].cdrom.ready = 0; - bx_options.cdromd.Ostatus->set(BX_EJECTED); + BX_SELECTED_DRIVE(channel).cdrom.ready = 0; + bx_options.atadevice[channel][BX_SLAVE_SELECTED(channel)].Ostatus->set(BX_EJECTED); bx_gui.update_drive_status_buttons(); } - raise_interrupt(); + raise_interrupt(channel); } else { // Load the disc // My guess is that this command only closes the tray, that's a no-op for us - atapi_cmd_nop(); - raise_interrupt(); + atapi_cmd_nop(channel); + raise_interrupt(channel); } } break; case 0xbd: { // mechanism status - uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER.buffer + 8); + uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 8); if (alloc_length == 0) BX_PANIC(("Zero allocation length to MECHANISM STATUS not impl.")); - init_send_atapi_command(atapi_command, 8, alloc_length); + init_send_atapi_command(channel, atapi_command, 8, alloc_length); - BX_SELECTED_CONTROLLER.buffer[0] = 0; // reserved for non changers - BX_SELECTED_CONTROLLER.buffer[1] = 0; // reserved for non changers + BX_SELECTED_CONTROLLER(channel).buffer[0] = 0; // reserved for non changers + BX_SELECTED_CONTROLLER(channel).buffer[1] = 0; // reserved for non changers - BX_SELECTED_CONTROLLER.buffer[2] = 0; // Current LBA (TODO!) - BX_SELECTED_CONTROLLER.buffer[3] = 0; // Current LBA (TODO!) - BX_SELECTED_CONTROLLER.buffer[4] = 0; // Current LBA (TODO!) + BX_SELECTED_CONTROLLER(channel).buffer[2] = 0; // Current LBA (TODO!) + BX_SELECTED_CONTROLLER(channel).buffer[3] = 0; // Current LBA (TODO!) + BX_SELECTED_CONTROLLER(channel).buffer[4] = 0; // Current LBA (TODO!) - BX_SELECTED_CONTROLLER.buffer[5] = 1; // one slot + BX_SELECTED_CONTROLLER(channel).buffer[5] = 1; // one slot - BX_SELECTED_CONTROLLER.buffer[6] = 0; // slot table length - BX_SELECTED_CONTROLLER.buffer[7] = 0; // slot table length + BX_SELECTED_CONTROLLER(channel).buffer[6] = 0; // slot table length + BX_SELECTED_CONTROLLER(channel).buffer[7] = 0; // slot table length - ready_to_send_atapi(); + ready_to_send_atapi(channel); } break; case 0x5a: { // mode sense - uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER.buffer + 7); + uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7); - Bit8u PC = BX_SELECTED_CONTROLLER.buffer[2] >> 6; - Bit8u PageCode = BX_SELECTED_CONTROLLER.buffer[2] & 0x3f; + Bit8u PC = BX_SELECTED_CONTROLLER(channel).buffer[2] >> 6; + Bit8u PageCode = BX_SELECTED_CONTROLLER(channel).buffer[2] & 0x3f; switch (PC) { case 0x0: // current values switch (PageCode) { case 0x01: // error recovery - init_send_atapi_command(atapi_command, sizeof(error_recovery_t) + 8, alloc_length); + init_send_atapi_command(channel, atapi_command, sizeof(error_recovery_t) + 8, alloc_length); - init_mode_sense_single(&BX_SELECTED_HD.cdrom.current.error_recovery, + init_mode_sense_single(channel, &BX_SELECTED_DRIVE(channel).cdrom.current.error_recovery, sizeof(error_recovery_t)); - ready_to_send_atapi(); + ready_to_send_atapi(channel); break; case 0x2a: // CD-ROM capabilities & mech. status - init_send_atapi_command(atapi_command, 28, alloc_length); - init_mode_sense_single(&BX_SELECTED_CONTROLLER.buffer[8], 28); - BX_SELECTED_CONTROLLER.buffer[8] = 0x2a; - BX_SELECTED_CONTROLLER.buffer[9] = 0x12; - BX_SELECTED_CONTROLLER.buffer[10] = 0x00; - BX_SELECTED_CONTROLLER.buffer[11] = 0x00; - BX_SELECTED_CONTROLLER.buffer[12] = 0x00; - BX_SELECTED_CONTROLLER.buffer[13] = (3 << 5); - BX_SELECTED_CONTROLLER.buffer[14] = (unsigned char) + init_send_atapi_command(channel, atapi_command, 28, alloc_length); + init_mode_sense_single(channel, &BX_SELECTED_CONTROLLER(channel).buffer[8], 28); + BX_SELECTED_CONTROLLER(channel).buffer[8] = 0x2a; + BX_SELECTED_CONTROLLER(channel).buffer[9] = 0x12; + BX_SELECTED_CONTROLLER(channel).buffer[10] = 0x00; + BX_SELECTED_CONTROLLER(channel).buffer[11] = 0x00; + BX_SELECTED_CONTROLLER(channel).buffer[12] = 0x00; + BX_SELECTED_CONTROLLER(channel).buffer[13] = (3 << 5); + BX_SELECTED_CONTROLLER(channel).buffer[14] = (unsigned char) (1 | - (BX_SELECTED_HD.cdrom.locked ? (1 << 1) : 0) | + (BX_SELECTED_DRIVE(channel).cdrom.locked ? (1 << 1) : 0) | (1 << 3) | (1 << 5)); - BX_SELECTED_CONTROLLER.buffer[15] = 0x00; - BX_SELECTED_CONTROLLER.buffer[16] = (706 >> 8) & 0xff; - BX_SELECTED_CONTROLLER.buffer[17] = 706 & 0xff; - BX_SELECTED_CONTROLLER.buffer[18] = 0; - BX_SELECTED_CONTROLLER.buffer[19] = 2; - BX_SELECTED_CONTROLLER.buffer[20] = (512 >> 8) & 0xff; - BX_SELECTED_CONTROLLER.buffer[21] = 512 & 0xff; - BX_SELECTED_CONTROLLER.buffer[22] = (706 >> 8) & 0xff; - BX_SELECTED_CONTROLLER.buffer[23] = 706 & 0xff; - BX_SELECTED_CONTROLLER.buffer[24] = 0; - BX_SELECTED_CONTROLLER.buffer[25] = 0; - BX_SELECTED_CONTROLLER.buffer[26] = 0; - BX_SELECTED_CONTROLLER.buffer[27] = 0; - ready_to_send_atapi(); + BX_SELECTED_CONTROLLER(channel).buffer[15] = 0x00; + BX_SELECTED_CONTROLLER(channel).buffer[16] = (706 >> 8) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[17] = 706 & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[18] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[19] = 2; + BX_SELECTED_CONTROLLER(channel).buffer[20] = (512 >> 8) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[21] = 512 & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[22] = (706 >> 8) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[23] = 706 & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[24] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[25] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[26] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[27] = 0; + ready_to_send_atapi(channel); break; case 0x0d: // CD-ROM @@ -1171,9 +1252,9 @@ BX_ERROR(("cdrom: MODE SENSE (curr), code=%x" " not implemented yet", PageCode)); - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + raise_interrupt(channel); break; default: @@ -1181,9 +1262,9 @@ BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x," " not implemented by device", PC, PageCode)); - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + raise_interrupt(channel); break; } break; @@ -1198,9 +1279,9 @@ BX_ERROR(("cdrom: MODE SENSE (chg), code=%x", " not implemented yet", PageCode)); - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + raise_interrupt(channel); break; default: @@ -1208,9 +1289,9 @@ BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x," " not implemented by device", PC, PageCode)); - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + raise_interrupt(channel); break; } break; @@ -1231,16 +1312,16 @@ BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x," " not implemented by device", PC, PageCode)); - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + raise_interrupt(channel); break; } break; case 0x3: // saved values not implemented - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED); - raise_interrupt(); + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED); + raise_interrupt(channel); break; default: @@ -1251,96 +1332,96 @@ break; case 0x12: { // inquiry - uint8 alloc_length = BX_SELECTED_CONTROLLER.buffer[4]; + uint8 alloc_length = BX_SELECTED_CONTROLLER(channel).buffer[4]; - init_send_atapi_command(atapi_command, 36, alloc_length); + init_send_atapi_command(channel, atapi_command, 36, alloc_length); - BX_SELECTED_CONTROLLER.buffer[0] = 0x05; // CD-ROM - BX_SELECTED_CONTROLLER.buffer[1] = 0x80; // Removable - BX_SELECTED_CONTROLLER.buffer[2] = 0x00; // ISO, ECMA, ANSI version - BX_SELECTED_CONTROLLER.buffer[3] = 0x21; // ATAPI-2, as specified - BX_SELECTED_CONTROLLER.buffer[4] = 31; // additional length (total 36) - BX_SELECTED_CONTROLLER.buffer[5] = 0x00; // reserved - BX_SELECTED_CONTROLLER.buffer[6] = 0x00; // reserved - BX_SELECTED_CONTROLLER.buffer[7] = 0x00; // reserved + BX_SELECTED_CONTROLLER(channel).buffer[0] = 0x05; // CD-ROM + BX_SELECTED_CONTROLLER(channel).buffer[1] = 0x80; // Removable + BX_SELECTED_CONTROLLER(channel).buffer[2] = 0x00; // ISO, ECMA, ANSI version + BX_SELECTED_CONTROLLER(channel).buffer[3] = 0x21; // ATAPI-2, as specified + BX_SELECTED_CONTROLLER(channel).buffer[4] = 31; // additional length (total 36) + BX_SELECTED_CONTROLLER(channel).buffer[5] = 0x00; // reserved + BX_SELECTED_CONTROLLER(channel).buffer[6] = 0x00; // reserved + BX_SELECTED_CONTROLLER(channel).buffer[7] = 0x00; // reserved // Vendor ID const char* vendor_id = "VTAB\0\0\0\0"; int i; for (i = 0; i < 8; i++) - BX_SELECTED_CONTROLLER.buffer[8+i] = vendor_id[i]; + BX_SELECTED_CONTROLLER(channel).buffer[8+i] = vendor_id[i]; // Product ID const char* product_id = "Turbo CD-ROM\0\0\0\0"; for (i = 0; i < 16; i++) - BX_SELECTED_CONTROLLER.buffer[16+i] = product_id[i]; + BX_SELECTED_CONTROLLER(channel).buffer[16+i] = product_id[i]; // Product Revision level const char* rev_level = "R0\0\0"; for (i = 0; i < 4; i++) - BX_SELECTED_CONTROLLER.buffer[32+i] = rev_level[i]; + BX_SELECTED_CONTROLLER(channel).buffer[32+i] = rev_level[i]; - ready_to_send_atapi(); + ready_to_send_atapi(channel); } break; case 0x25: { // read cd-rom capacity // no allocation length??? - init_send_atapi_command(atapi_command, 8, 8); + init_send_atapi_command(channel, atapi_command, 8, 8); - if (BX_SELECTED_HD.cdrom.ready) { - uint32 capacity = BX_SELECTED_HD.cdrom.capacity; + if (BX_SELECTED_DRIVE(channel).cdrom.ready) { + uint32 capacity = BX_SELECTED_DRIVE(channel).cdrom.capacity; BX_INFO(("Capacity is %d sectors (%d bytes)", capacity, capacity * 2048)); - BX_SELECTED_CONTROLLER.buffer[0] = (capacity >> 24) & 0xff; - BX_SELECTED_CONTROLLER.buffer[1] = (capacity >> 16) & 0xff; - BX_SELECTED_CONTROLLER.buffer[2] = (capacity >> 8) & 0xff; - BX_SELECTED_CONTROLLER.buffer[3] = (capacity >> 0) & 0xff; - BX_SELECTED_CONTROLLER.buffer[4] = (2048 >> 24) & 0xff; - BX_SELECTED_CONTROLLER.buffer[5] = (2048 >> 16) & 0xff; - BX_SELECTED_CONTROLLER.buffer[6] = (2048 >> 8) & 0xff; - BX_SELECTED_CONTROLLER.buffer[7] = (2048 >> 0) & 0xff; - ready_to_send_atapi(); + BX_SELECTED_CONTROLLER(channel).buffer[0] = (capacity >> 24) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[1] = (capacity >> 16) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[2] = (capacity >> 8) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[3] = (capacity >> 0) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[4] = (2048 >> 24) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[5] = (2048 >> 16) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[6] = (2048 >> 8) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[7] = (2048 >> 0) & 0xff; + ready_to_send_atapi(channel); } else { - atapi_cmd_error(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(); + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + raise_interrupt(channel); } } break; case 0xbe: { // read cd - if (BX_SELECTED_HD.cdrom.ready) { + if (BX_SELECTED_DRIVE(channel).cdrom.ready) { BX_ERROR(("Read CD with CD present not implemented")); - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); + raise_interrupt(channel); } else { - atapi_cmd_error(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(); + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + raise_interrupt(channel); } } break; case 0x43: { // read toc - if (BX_SELECTED_HD.cdrom.ready) { + if (BX_SELECTED_DRIVE(channel).cdrom.ready) { #ifdef LOWLEVEL_CDROM - bool msf = (BX_SELECTED_CONTROLLER.buffer[1] >> 1) & 1; - uint8 starting_track = BX_SELECTED_CONTROLLER.buffer[6]; + bool msf = (BX_SELECTED_CONTROLLER(channel).buffer[1] >> 1) & 1; + uint8 starting_track = BX_SELECTED_CONTROLLER(channel).buffer[6]; #endif - uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER.buffer + 7); + uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7); - uint8 format = (BX_SELECTED_CONTROLLER.buffer[9] >> 6); + uint8 format = (BX_SELECTED_CONTROLLER(channel).buffer[9] >> 6); int i; switch (format) { case 0: #ifdef LOWLEVEL_CDROM int toc_length; - if (!BX_SELECTED_HD.cdrom.cd->read_toc(BX_SELECTED_CONTROLLER.buffer, - &toc_length, msf, starting_track)) { - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, + if (!(BX_SELECTED_DRIVE(channel).cdrom.cd->read_toc(BX_SELECTED_CONTROLLER(channel).buffer, + &toc_length, msf, starting_track))) { + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + raise_interrupt(channel); } else { - init_send_atapi_command(atapi_command, toc_length, alloc_length); - ready_to_send_atapi(); + init_send_atapi_command(channel, atapi_command, toc_length, alloc_length); + ready_to_send_atapi(channel); } #else BX_PANIC(("LOWLEVEL_CDROM not defined")); @@ -1349,16 +1430,16 @@ case 1: // multi session stuff. we ignore this and emulate a single session only - init_send_atapi_command(atapi_command, 12, alloc_length); + init_send_atapi_command(channel, atapi_command, 12, alloc_length); - BX_SELECTED_CONTROLLER.buffer[0] = 0; - BX_SELECTED_CONTROLLER.buffer[1] = 0x0a; - BX_SELECTED_CONTROLLER.buffer[2] = 1; - BX_SELECTED_CONTROLLER.buffer[3] = 1; + BX_SELECTED_CONTROLLER(channel).buffer[0] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[1] = 0x0a; + BX_SELECTED_CONTROLLER(channel).buffer[2] = 1; + BX_SELECTED_CONTROLLER(channel).buffer[3] = 1; for (i = 0; i < 8; i++) - BX_SELECTED_CONTROLLER.buffer[4+i] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[4+i] = 0; - ready_to_send_atapi(); + ready_to_send_atapi(channel); break; case 2: @@ -1367,114 +1448,114 @@ break; } } else { - atapi_cmd_error(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(); + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + raise_interrupt(channel); } } break; case 0x28: { // read (10) - uint32 transfer_length = read_16bit(BX_SELECTED_CONTROLLER.buffer + 7); - uint32 lba = read_32bit(BX_SELECTED_CONTROLLER.buffer + 2); + uint32 transfer_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7); + uint32 lba = read_32bit(BX_SELECTED_CONTROLLER(channel).buffer + 2); - if (!BX_SELECTED_HD.cdrom.ready) { - atapi_cmd_error(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(); + if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + raise_interrupt(channel); break; } if (transfer_length == 0) { - atapi_cmd_nop(); - raise_interrupt(); + atapi_cmd_nop(channel); + raise_interrupt(channel); BX_INFO(("READ(10) with transfer length 0, ok")); break; } - if (lba + transfer_length > BX_SELECTED_HD.cdrom.capacity) { - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); - raise_interrupt(); + if (lba + transfer_length > BX_SELECTED_DRIVE(channel).cdrom.capacity) { + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); + raise_interrupt(channel); break; } //BX_INFO(("cdrom: READ LBA=%d LEN=%d", lba, transfer_length)); // handle command - init_send_atapi_command(atapi_command, transfer_length * 2048, + init_send_atapi_command(channel, atapi_command, transfer_length * 2048, transfer_length * 2048, true); - BX_SELECTED_HD.cdrom.remaining_blocks = transfer_length; - BX_SELECTED_HD.cdrom.next_lba = lba; - ready_to_send_atapi(); + BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks = transfer_length; + BX_SELECTED_DRIVE(channel).cdrom.next_lba = lba; + ready_to_send_atapi(channel); } break; case 0x2b: { // seek - uint32 lba = read_32bit(BX_SELECTED_CONTROLLER.buffer + 2); - if (!BX_SELECTED_HD.cdrom.ready) { - atapi_cmd_error(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(); + uint32 lba = read_32bit(BX_SELECTED_CONTROLLER(channel).buffer + 2); + if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + raise_interrupt(channel); break; } - if (lba > BX_SELECTED_HD.cdrom.capacity) { - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); - raise_interrupt(); + if (lba > BX_SELECTED_DRIVE(channel).cdrom.capacity) { + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); + raise_interrupt(channel); break; } BX_INFO(("cdrom: SEEK (ignored)")); - atapi_cmd_nop(); - raise_interrupt(); + atapi_cmd_nop(channel); + raise_interrupt(channel); } break; case 0x1e: { // prevent/allow medium removal - if (BX_SELECTED_HD.cdrom.ready) { - BX_SELECTED_HD.cdrom.locked = BX_SELECTED_CONTROLLER.buffer[4] & 1; - atapi_cmd_nop(); + if (BX_SELECTED_DRIVE(channel).cdrom.ready) { + BX_SELECTED_DRIVE(channel).cdrom.locked = BX_SELECTED_CONTROLLER(channel).buffer[4] & 1; + atapi_cmd_nop(channel); } else { - atapi_cmd_error(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); } - raise_interrupt(); + raise_interrupt(channel); } break; case 0x42: { // read sub-channel - bool msf = get_packet_field(1, 1, 1); - bool sub_q = get_packet_field(2, 6, 1); - uint8 data_format = get_packet_byte(3); - uint8 track_number = get_packet_byte(6); - uint16 alloc_length = get_packet_word(7); + bool msf = get_packet_field(channel,1, 1, 1); + bool sub_q = get_packet_field(channel,2, 6, 1); + uint8 data_format = get_packet_byte(channel,3); + uint8 track_number = get_packet_byte(channel,6); + uint16 alloc_length = get_packet_word(channel,7); UNUSED(msf); UNUSED(data_format); UNUSED(track_number); - if (!BX_SELECTED_HD.cdrom.ready) { - atapi_cmd_error(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(); + if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { + atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); + raise_interrupt(channel); } else { - BX_SELECTED_CONTROLLER.buffer[0] = 0; - BX_SELECTED_CONTROLLER.buffer[1] = 0; // audio not supported - BX_SELECTED_CONTROLLER.buffer[2] = 0; - BX_SELECTED_CONTROLLER.buffer[3] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[0] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[1] = 0; // audio not supported + BX_SELECTED_CONTROLLER(channel).buffer[2] = 0; + BX_SELECTED_CONTROLLER(channel).buffer[3] = 0; int ret_len = 4; // header size if (sub_q) { // !sub_q == header only BX_ERROR(("Read sub-channel with SubQ not implemented")); - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + raise_interrupt(channel); } - init_send_atapi_command(atapi_command, ret_len, alloc_length); - ready_to_send_atapi(); + init_send_atapi_command(channel, atapi_command, ret_len, alloc_length); + ready_to_send_atapi(channel); } } break; case 0x51: { // read disc info // no-op to keep the Linux CD-ROM driver happy - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); + raise_interrupt(channel); } break; @@ -1492,8 +1573,8 @@ case 0x4e: // stop play/scan BX_ERROR(("ATAPI command 0x%x not implemented yet", atapi_command)); - atapi_cmd_error(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(); + atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); + raise_interrupt(channel); break; default: BX_PANIC(("Unknown ATAPI command 0x%x (%d)", @@ -1506,45 +1587,45 @@ default: BX_PANIC(("IO write(1f0h): current command is %02xh", - (unsigned) BX_SELECTED_CONTROLLER.current_command)); + (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); } break; - case 0x1f1: /* hard disk write precompensation */ - WRITE_FEATURES(value); - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) { + case 0x01: // hard disk write precompensation 0x1f1 + WRITE_FEATURES(channel,value); + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) { if (value == 0xff) - BX_INFO(("no precompensation {%s}", DEVICE_TYPE_STRING)); + BX_INFO(("no precompensation {%s}", BX_SELECTED_TYPE_STRING(channel))); else - BX_INFO(("precompensation value %02x {%s}", (unsigned) value, DEVICE_TYPE_STRING)); + BX_INFO(("precompensation value %02x {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); } break; - case 0x1f2: /* hard disk sector count */ - WRITE_SECTOR_COUNT(value); - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) - BX_INFO(("sector count = %u {%s}", (unsigned) value, DEVICE_TYPE_STRING)); + case 0x02: // hard disk sector count 0x1f2 + WRITE_SECTOR_COUNT(channel,value); + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) + BX_INFO(("sector count = %u {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); break; - case 0x1f3: /* hard disk sector number */ - WRITE_SECTOR_NUMBER(value); - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) - BX_INFO(("sector number = %u {%s}", (unsigned) value, DEVICE_TYPE_STRING)); + case 0x03: // hard disk sector number 0x1f3 + WRITE_SECTOR_NUMBER(channel,value); + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) + BX_INFO(("sector number = %u {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); break; - case 0x1f4: /* hard disk cylinder low */ - WRITE_CYLINDER_LOW(value); - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) - BX_INFO(("cylinder low = %02xh {%s}", (unsigned) value, DEVICE_TYPE_STRING)); + case 0x04: // hard disk cylinder low 0x1f4 + WRITE_CYLINDER_LOW(channel,value); + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) + BX_INFO(("cylinder low = %02xh {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); break; - case 0x1f5: /* hard disk cylinder high */ - WRITE_CYLINDER_HIGH(value); - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) - BX_INFO(("cylinder high = %02xh {%s}", (unsigned) value, DEVICE_TYPE_STRING)); + case 0x05: // hard disk cylinder high 0x1f5 + WRITE_CYLINDER_HIGH(channel,value); + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) + BX_INFO(("cylinder high = %02xh {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); break; - case 0x1f6: // hard disk drive and head register + case 0x06: // hard disk drive and head register 0x1f6 // b7 Extended data field for ECC // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128 // Since 512 was always used, bit 6 was taken to mean LBA mode: @@ -1555,410 +1636,399 @@ { if ( (value & 0xa0) != 0xa0 ) // 1x1xxxxx BX_INFO(("IO write 1f6 (%02x): not 1x1xxxxxb", (unsigned) value)); - Bit32u drvsel = BX_HD_THIS drive_select = (value >> 4) & 0x01; - WRITE_HEAD_NO(value & 0xf); - if (BX_SELECTED_CONTROLLER.lba_mode == 0 && ((value >> 6) & 1) == 1) + Bit32u drvsel = BX_HD_THIS channels[channel].drive_select = (value >> 4) & 0x01; + WRITE_HEAD_NO(channel,value & 0xf); + if (BX_SELECTED_CONTROLLER(channel).lba_mode == 0 && ((value >> 6) & 1) == 1) BX_INFO(("enabling LBA mode")); - WRITE_LBA_MODE((value >> 6) & 1); - if (!drvsel && !bx_options.diskc.Opresent->get ()) { - BX_ERROR (("device set to 0 which does not exist")); - BX_SELECTED_CONTROLLER.error_register = 0x04; // aborted - BX_SELECTED_CONTROLLER.status.err = 1; - } else if (drvsel && !bx_options.diskd.Opresent->get ()) { - BX_ERROR (("device set to 1 which does not exist")); - BX_SELECTED_CONTROLLER.error_register = 0x04; // aborted - BX_SELECTED_CONTROLLER.status.err = 1; - } + WRITE_LBA_MODE(channel,(value >> 6) & 1); + if (!BX_SELECTED_IS_PRESENT(channel)) { + BX_ERROR (("device set to %d which does not exist",drvsel)); + BX_SELECTED_CONTROLLER(channel).error_register = 0x04; // aborted + BX_SELECTED_CONTROLLER(channel).status.err = 1; + } break; } - case 0x1f7: // hard disk command + case 0x07: // hard disk command 0x1f7 // (mch) Writes to the command register with drive_select != 0 // are ignored if no secondary device is present - if (BX_HD_THIS drive_select != 0 && value != 0x90 && !bx_options.diskd.Opresent->get ()) + if ((BX_SLAVE_SELECTED(channel)) && (!BX_SLAVE_IS_PRESENT(channel))) break; - if (BX_SELECTED_CONTROLLER.status.busy) + if (BX_SELECTED_CONTROLLER(channel).status.busy) BX_PANIC(("hard disk: command sent, controller BUSY")); if ( (value & 0xf0) == 0x10 ) value = 0x10; switch (value) { case 0x10: // CALIBRATE DRIVE - if (BX_SELECTED_HD.device_type != IDE_DISK) + if (!BX_SELECTED_IS_HD(channel)) BX_PANIC(("calibrate drive issued to non-disk")); - if ((BX_HD_THIS drive_select == 0 && !bx_options.diskc.Opresent->get ()) || - (BX_HD_THIS drive_select != 0 && !bx_options.diskd.Opresent->get ())) { - BX_SELECTED_CONTROLLER.error_register = 0x02; // Track 0 not found - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.seek_complete = 0; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 1; - raise_interrupt(); - BX_INFO(("calibrate drive: disk%c not present", BX_HD_THIS drive_select+67)); + if (!BX_SELECTED_IS_PRESENT(channel)) { + BX_SELECTED_CONTROLLER(channel).error_register = 0x02; // Track 0 not found + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 1; + raise_interrupt(channel); + BX_INFO(("calibrate drive: disk ata%d-%d not present", channel, BX_SLAVE_SELECTED(channel))); break; } - /* move head to cylinder 0, issue IRQ 14 */ - BX_SELECTED_CONTROLLER.error_register = 0; - BX_SELECTED_CONTROLLER.cylinder_no = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.seek_complete = 1; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; - raise_interrupt(); + /* move head to cylinder 0, issue IRQ */ + BX_SELECTED_CONTROLLER(channel).error_register = 0; + BX_SELECTED_CONTROLLER(channel).cylinder_no = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + raise_interrupt(channel); break; case 0x20: // READ MULTIPLE SECTORS, with retries case 0x21: // READ MULTIPLE SECTORS, without retries /* update sector_no, always points to current sector - * after each sector is read to buffer, DRQ bit set and issue IRQ 14 + * after each sector is read to buffer, DRQ bit set and issue IRQ * if interrupt handler transfers all data words into main memory, * and more sectors to read, then set BSY bit again, clear DRQ and * read next sector into buffer * sector count of 0 means 256 sectors */ - if (BX_SELECTED_HD.device_type != IDE_DISK) + if (!BX_SELECTED_IS_HD(channel)) BX_PANIC(("read multiple issued to non-disk")); - BX_SELECTED_CONTROLLER.current_command = value; + BX_SELECTED_CONTROLLER(channel).current_command = value; // Lose98 accesses 0/0/0 in CHS mode - if (!BX_SELECTED_CONTROLLER.lba_mode && - !BX_SELECTED_CONTROLLER.head_no && - !BX_SELECTED_CONTROLLER.cylinder_no && - !BX_SELECTED_CONTROLLER.sector_no) { + if (!BX_SELECTED_CONTROLLER(channel).lba_mode && + !BX_SELECTED_CONTROLLER(channel).head_no && + !BX_SELECTED_CONTROLLER(channel).cylinder_no && + !BX_SELECTED_CONTROLLER(channel).sector_no) { BX_INFO(("Read from 0/0/0, aborting command")); - command_aborted(value); + command_aborted(channel, value); break; } #if TEST_READ_BEYOND_END==2 - BX_SELECTED_CONTROLLER.cylinder_no += 100000; + BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000; #endif - if (!calculate_logical_address(&logical_sector)) { + if (!calculate_logical_address(channel, &logical_sector)) { BX_ERROR(("initial read from sector %u out of bounds, aborting", logical_sector)); - command_aborted(value); + command_aborted(channel, value); break; } #if TEST_READ_BEYOND_END==3 logical_sector += 100000; #endif - ret=BX_SELECTED_HD.hard_drive->lseek(logical_sector * 512, SEEK_SET); + ret=BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET); if (ret < 0) { BX_ERROR (("could not lseek() hard drive image file, aborting")); - command_aborted(value); + command_aborted(channel, value); break; } - ret = BX_SELECTED_HD.hard_drive->read((bx_ptr_t) BX_SELECTED_CONTROLLER.buffer, 512); + ret = BX_SELECTED_DRIVE(channel).hard_drive->read((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512); if (ret < 512) { BX_ERROR(("logical sector was %u", (unsigned) logical_sector)); BX_ERROR(("could not read() hard drive image file at byte %d", logical_sector*512)); - command_aborted(value); + command_aborted(channel, value); break; } - BX_SELECTED_CONTROLLER.error_register = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.seek_complete = 1; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - BX_SELECTED_CONTROLLER.status.err = 0; - BX_SELECTED_CONTROLLER.buffer_index = 0; - raise_interrupt(); + BX_SELECTED_CONTROLLER(channel).error_register = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; + raise_interrupt(channel); break; case 0x30: /* WRITE SECTORS, with retries */ /* update sector_no, always points to current sector - * after each sector is read to buffer, DRQ bit set and issue IRQ 14 + * after each sector is read to buffer, DRQ bit set and issue IRQ * if interrupt handler transfers all data words into main memory, * and more sectors to read, then set BSY bit again, clear DRQ and * read next sector into buffer * sector count of 0 means 256 sectors */ - if (BX_SELECTED_HD.device_type != IDE_DISK) + if (!BX_SELECTED_IS_HD(channel)) BX_PANIC(("write multiple issued to non-disk")); - if (BX_SELECTED_CONTROLLER.status.busy) { + if (BX_SELECTED_CONTROLLER(channel).status.busy) { BX_PANIC(("write command: BSY bit set")); } - BX_SELECTED_CONTROLLER.current_command = value; + BX_SELECTED_CONTROLLER(channel).current_command = value; // implicit seek done :^) - BX_SELECTED_CONTROLLER.error_register = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - // BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.seek_complete = 1; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.err = 0; - BX_SELECTED_CONTROLLER.buffer_index = 0; + BX_SELECTED_CONTROLLER(channel).error_register = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + // BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; break; case 0x90: // EXECUTE DEVICE DIAGNOSTIC - if (BX_SELECTED_CONTROLLER.status.busy) { + if (BX_SELECTED_CONTROLLER(channel).status.busy) { BX_PANIC(("diagnostic command: BSY bit set")); } - if (BX_SELECTED_HD.device_type != IDE_DISK) + if (!BX_SELECTED_IS_HD(channel)) BX_PANIC(("drive diagnostics issued to non-disk")); - BX_SELECTED_CONTROLLER.error_register = 0x81; // Drive 1 failed, no error on drive 0 - // BX_SELECTED_CONTROLLER.status.busy = 0; // not needed - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).error_register = 0x81; // Drive 1 failed, no error on drive 0 + // BX_SELECTED_CONTROLLER(channel).status.busy = 0; // not needed + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; break; case 0x91: // INITIALIZE DRIVE PARAMETERS - if (BX_SELECTED_CONTROLLER.status.busy) { + if (BX_SELECTED_CONTROLLER(channel).status.busy) { BX_PANIC(("init drive parameters command: BSY bit set")); } - if (BX_SELECTED_HD.device_type != IDE_DISK) + if (!BX_SELECTED_IS_HD(channel)) BX_PANIC(("initialize drive parameters issued to non-disk")); // sets logical geometry of specified drive BX_DEBUG(("init drive params: sec=%u, drive sel=%u, head=%u", - (unsigned) BX_SELECTED_CONTROLLER.sector_count, - (unsigned) BX_HD_THIS drive_select, - (unsigned) BX_SELECTED_CONTROLLER.head_no)); - if ((BX_HD_THIS drive_select == 0 && !bx_options.diskc.Opresent->get ()) || - (BX_HD_THIS drive_select != 0 && !bx_options.diskd.Opresent->get ())) { - BX_PANIC(("init drive params: disk%c not present", BX_HD_THIS drive_select+67)); - //BX_SELECTED_CONTROLLER.error_register = 0x12; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; - raise_interrupt(); + (unsigned) BX_SELECTED_CONTROLLER(channel).sector_count, + (unsigned) BX_HD_THIS channels[channel].drive_select, + (unsigned) BX_SELECTED_CONTROLLER(channel).head_no)); + if (!BX_SELECTED_IS_PRESENT(channel)) { + BX_PANIC(("init drive params: disk ata%d-%d% not present", channel, BX_SLAVE_SELECTED(channel))); + //BX_SELECTED_CONTROLLER(channel).error_register = 0x12; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + raise_interrupt(channel); break; } - if (BX_SELECTED_CONTROLLER.sector_count != BX_SELECTED_HD.hard_drive->sectors) - BX_PANIC(("init drive params: sector count doesnt match")); - if ( BX_SELECTED_CONTROLLER.head_no != (BX_SELECTED_HD.hard_drive->heads-1) ) - BX_PANIC(("init drive params: head number doesn't match")); - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; - raise_interrupt(); + if (BX_SELECTED_CONTROLLER(channel).sector_count != BX_SELECTED_DRIVE(channel).hard_drive->sectors) + BX_PANIC(("init drive params: sector count doesnt match %ld!=%ld", BX_SELECTED_CONTROLLER(channel).sector_count, BX_SELECTED_DRIVE(channel).hard_drive->sectors)); + if ( BX_SELECTED_CONTROLLER(channel).head_no != (BX_SELECTED_DRIVE(channel).hard_drive->heads-1) ) + BX_PANIC(("init drive params: head number doesn't match %d != %d",BX_SELECTED_CONTROLLER(channel).head_no, BX_SELECTED_DRIVE(channel).hard_drive->heads-1)); + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + raise_interrupt(channel); break; case 0xec: // IDENTIFY DEVICE if (bx_options.OnewHardDriveSupport->get ()) { - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) BX_INFO(("Drive ID Command issued : 0xec ")); - if (!BX_HD_THIS drive_select && !bx_options.diskc.Opresent->get ()) { - BX_INFO(("1st drive not present, aborting")); - command_aborted(value); - break; - } - if (BX_HD_THIS drive_select && !bx_options.diskd.Opresent->get ()) { - BX_INFO(("2nd drive not present, aborting")); - command_aborted(value); + if (!BX_SELECTED_IS_PRESENT(channel)) { + BX_INFO(("disk ata%d-%d not present, aborting",channel,BX_SLAVE_SELECTED(channel))); + command_aborted(channel, value); break; } - if (BX_SELECTED_HD.device_type == IDE_CDROM) { - BX_SELECTED_CONTROLLER.head_no = 0; - BX_SELECTED_CONTROLLER.sector_count = 1; - BX_SELECTED_CONTROLLER.sector_no = 1; - BX_SELECTED_CONTROLLER.cylinder_no = 0xeb14; - command_aborted(0xec); + if (BX_SELECTED_IS_CD(channel)) { + BX_SELECTED_CONTROLLER(channel).head_no = 0; + BX_SELECTED_CONTROLLER(channel).sector_count = 1; + BX_SELECTED_CONTROLLER(channel).sector_no = 1; + BX_SELECTED_CONTROLLER(channel).cylinder_no = 0xeb14; + command_aborted(channel, 0xec); } else { - BX_SELECTED_CONTROLLER.current_command = value; - BX_SELECTED_CONTROLLER.error_register = 0; + BX_SELECTED_CONTROLLER(channel).current_command = value; + BX_SELECTED_CONTROLLER(channel).error_register = 0; // See ATA/ATAPI-4, 8.12 - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.write_fault = 0; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.err = 0; - - BX_SELECTED_CONTROLLER.status.seek_complete = 1; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - - BX_SELECTED_CONTROLLER.buffer_index = 0; - raise_interrupt(); - identify_drive(BX_HD_THIS drive_select); + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; + raise_interrupt(channel); + identify_drive(channel); } } else { BX_INFO(("sent IDENTIFY DEVICE (0xec) to old hard drive")); - command_aborted(value); + command_aborted(channel, value); } break; case 0xef: // SET FEATURES - switch(BX_SELECTED_CONTROLLER.features) { + switch(BX_SELECTED_CONTROLLER(channel).features) { case 0x02: // Enable and case 0x82: // Disable write cache. case 0xAA: // Enable and case 0x55: // Disable look-ahead cache. + case 0xCC: // Enable and case 0x66: // Disable reverting to power-on default - case 0xCC: // Enable reverting to power-on default - BX_INFO(("SET FEATURES subcommand 0x%02x not supported by disk.", (unsigned) BX_SELECTED_CONTROLLER.features)); - command_aborted(value); + BX_INFO(("SET FEATURES subcommand 0x%02x not supported by disk.", (unsigned) BX_SELECTED_CONTROLLER(channel).features)); + command_aborted(channel, value); break; default: - BX_PANIC(("SET FEATURES with unknown subcommand: 0x%02x", (unsigned) BX_SELECTED_CONTROLLER.features )); + BX_PANIC(("SET FEATURES with unknown subcommand: 0x%02x", (unsigned) BX_SELECTED_CONTROLLER(channel).features )); } break; case 0x40: // READ VERIFY SECTORS if (bx_options.OnewHardDriveSupport->get ()) { - if (BX_SELECTED_HD.device_type != IDE_DISK) + if (!BX_SELECTED_IS_HD(channel)) BX_PANIC(("read verify issued to non-disk")); BX_INFO(("Verify Command : 0x40 ! ")); - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; - raise_interrupt(); + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + raise_interrupt(channel); } else { BX_INFO(("sent READ VERIFY SECTORS (0x40) to old hard drive")); - command_aborted(value); + command_aborted(channel, value); } break; case 0xc6: // SET MULTIPLE MODE (mch) - if (BX_SELECTED_CONTROLLER.sector_count != 128 && - BX_SELECTED_CONTROLLER.sector_count != 64 && - BX_SELECTED_CONTROLLER.sector_count != 32 && - BX_SELECTED_CONTROLLER.sector_count != 16 && - BX_SELECTED_CONTROLLER.sector_count != 8 && - BX_SELECTED_CONTROLLER.sector_count != 4 && - BX_SELECTED_CONTROLLER.sector_count != 2) - command_aborted(value); + if (BX_SELECTED_CONTROLLER(channel).sector_count != 128 && + BX_SELECTED_CONTROLLER(channel).sector_count != 64 && + BX_SELECTED_CONTROLLER(channel).sector_count != 32 && + BX_SELECTED_CONTROLLER(channel).sector_count != 16 && + BX_SELECTED_CONTROLLER(channel).sector_count != 8 && + BX_SELECTED_CONTROLLER(channel).sector_count != 4 && + BX_SELECTED_CONTROLLER(channel).sector_count != 2) + command_aborted(channel, value); - if (BX_SELECTED_HD.device_type != IDE_DISK) + if (!BX_SELECTED_IS_HD(channel)) BX_PANIC(("set multiple mode issued to non-disk")); - BX_SELECTED_CONTROLLER.sectors_per_block = BX_SELECTED_CONTROLLER.sector_count; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.write_fault = 0; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).sectors_per_block = BX_SELECTED_CONTROLLER(channel).sector_count; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; break; // ATAPI commands case 0xa1: // IDENTIFY PACKET DEVICE - if (BX_SELECTED_HD.device_type == IDE_CDROM) { - BX_SELECTED_CONTROLLER.current_command = value; - BX_SELECTED_CONTROLLER.error_register = 0; - - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.write_fault = 0; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.err = 0; - - BX_SELECTED_CONTROLLER.status.seek_complete = 1; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - - BX_SELECTED_CONTROLLER.buffer_index = 0; - raise_interrupt(); - identify_ATAPI_drive(BX_HD_THIS drive_select); + if (BX_SELECTED_IS_CD(channel)) { + BX_SELECTED_CONTROLLER(channel).current_command = value; + BX_SELECTED_CONTROLLER(channel).error_register = 0; + + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; + raise_interrupt(channel); + identify_ATAPI_drive(channel); } else { - command_aborted(0xa1); + command_aborted(channel, 0xa1); } break; case 0x08: // DEVICE RESET (atapi) - if (BX_SELECTED_HD.device_type == IDE_CDROM) { - BX_SELECTED_CONTROLLER.status.busy = 1; - BX_SELECTED_CONTROLLER.error_register &= ~(1 << 7); + if (BX_SELECTED_IS_CD(channel)) { + BX_SELECTED_CONTROLLER(channel).status.busy = 1; + BX_SELECTED_CONTROLLER(channel).error_register &= ~(1 << 7); // device signature - BX_SELECTED_CONTROLLER.head_no = 0; - BX_SELECTED_CONTROLLER.sector_count = 1; - BX_SELECTED_CONTROLLER.sector_no = 1; - BX_SELECTED_CONTROLLER.cylinder_no = 0xeb14; - - BX_SELECTED_CONTROLLER.status.write_fault = 0; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).head_no = 0; + BX_SELECTED_CONTROLLER(channel).sector_count = 1; + BX_SELECTED_CONTROLLER(channel).sector_no = 1; + BX_SELECTED_CONTROLLER(channel).cylinder_no = 0xeb14; + + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; } else { BX_DEBUG(("ATAPI Device Reset on non-cd device")); - command_aborted(0x08); + command_aborted(channel, 0x08); } break; case 0xa0: // SEND PACKET (atapi) - if (BX_SELECTED_HD.device_type == IDE_CDROM) { + if (BX_SELECTED_IS_CD(channel)) { // PACKET - if (BX_SELECTED_CONTROLLER.features & (1 << 0)) + if (BX_SELECTED_CONTROLLER(channel).features & (1 << 0)) BX_PANIC(("PACKET-DMA not supported")); - if (BX_SELECTED_CONTROLLER.features & (1 << 1)) + if (BX_SELECTED_CONTROLLER(channel).features & (1 << 1)) BX_PANIC(("PACKET-overlapped not supported")); // We're already ready! - BX_SELECTED_CONTROLLER.sector_count = 1; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).sector_count = 1; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; // serv bit?? - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.err = 0; // NOTE: no interrupt here - BX_SELECTED_CONTROLLER.current_command = value; - BX_SELECTED_CONTROLLER.buffer_index = 0; + BX_SELECTED_CONTROLLER(channel).current_command = value; + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; } else { - command_aborted (0xa0); + command_aborted (channel, 0xa0); } break; case 0xa2: // SERVICE (atapi), optional - if (BX_SELECTED_HD.device_type == IDE_CDROM) { + if (BX_SELECTED_IS_CD(channel)) { BX_PANIC(("ATAPI SERVICE not implemented")); } else { - command_aborted (0xa2); + command_aborted (channel, 0xa2); } break; // power management case 0xe5: // CHECK POWER MODE - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.write_fault = 0; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; - BX_SELECTED_CONTROLLER.sector_count = 0xff; // Active or Idle mode - raise_interrupt(); + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + BX_SELECTED_CONTROLLER(channel).sector_count = 0xff; // Active or Idle mode + raise_interrupt(channel); break; case 0x70: // SEEK (cgs) - if (BX_SELECTED_HD.device_type == IDE_DISK) { + if (BX_SELECTED_IS_HD(channel)) { BX_DEBUG(("write cmd 0x70 (SEEK) executing")); - if (!calculate_logical_address(&logical_sector)) { + if (!calculate_logical_address(channel, &logical_sector)) { BX_ERROR(("initial seek to sector %u out of bounds, aborting", logical_sector)); - command_aborted(value); + command_aborted(channel, value); break; } - BX_SELECTED_CONTROLLER.error_register = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.seek_complete = 1; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - BX_SELECTED_CONTROLLER.status.err = 0; - BX_SELECTED_CONTROLLER.buffer_index = 0; - BX_DEBUG(("s[0].controller.control.disable_irq = %02x", (BX_HD_THIS s[0]).controller.control.disable_irq)); - BX_DEBUG(("s[1].controller.control.disable_irq = %02x", (BX_HD_THIS s[1]).controller.control.disable_irq)); - BX_DEBUG(("SEEK completed. error_register = %02x", BX_SELECTED_CONTROLLER.error_register)); - raise_interrupt(); + BX_SELECTED_CONTROLLER(channel).error_register = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; + BX_DEBUG(("s[0].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[0]).controller.control.disable_irq)); + BX_DEBUG(("s[1].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[1]).controller.control.disable_irq)); + BX_DEBUG(("SEEK completed. error_register = %02x", BX_SELECTED_CONTROLLER(channel).error_register)); + raise_interrupt(channel); BX_DEBUG(("SEEK interrupt completed")); } else { BX_ERROR(("write cmd 0x70 (SEEK) not supported for non-disk")); - command_aborted(0x70); + command_aborted(channel, 0x70); } break; @@ -1967,161 +2037,150 @@ // List all the write operations that are defined in the ATA/ATAPI spec // that we don't support. Commands that are listed here will cause a // BX_ERROR, which is non-fatal, and the command will be aborted. - case 0x22: BX_ERROR(("write cmd 0x22 (READ LONG) not supported")); command_aborted(0x22); break; - case 0x23: BX_ERROR(("write cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(0x23); break; - case 0x24: BX_ERROR(("write cmd 0x24 (READ SECTORS EXT) not supported"));command_aborted(0x24); break; - case 0x25: BX_ERROR(("write cmd 0x25 (READ DMA EXT) not supported"));command_aborted(0x25); break; - case 0x26: BX_ERROR(("write cmd 0x26 (READ DMA QUEUED EXT) not supported"));command_aborted(0x26); break; - case 0x27: BX_ERROR(("write cmd 0x27 (READ NATIVE MAX ADDRESS EXT) not supported"));command_aborted(0x27); break; - case 0x29: BX_ERROR(("write cmd 0x29 (READ MULTIPLE EXT) not supported"));command_aborted(0x29); break; - case 0x2A: BX_ERROR(("write cmd 0x2A (READ STREAM DMA) not supported"));command_aborted(0x2A); break; - case 0x2B: BX_ERROR(("write cmd 0x2B (READ STREAM PIO) not supported"));command_aborted(0x2B); break; - case 0x2F: BX_ERROR(("write cmd 0x2F (READ LOG EXT) not supported"));command_aborted(0x2F); break; - case 0x31: BX_ERROR(("write cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(0x31); break; - case 0x32: BX_ERROR(("write cmd 0x32 (WRITE LONG) not supported")); command_aborted(0x32); break; - case 0x33: BX_ERROR(("write cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(0x33); break; - case 0x34: BX_ERROR(("write cmd 0x34 (WRITE SECTORS EXT) not supported"));command_aborted(0x34); break; - case 0x35: BX_ERROR(("write cmd 0x35 (WRITE DMA EXT) not supported"));command_aborted(0x35); break; - case 0x36: BX_ERROR(("write cmd 0x36 (WRITE DMA QUEUED EXT) not supported"));command_aborted(0x36); break; - case 0x37: BX_ERROR(("write cmd 0x37 (SET MAX ADDRESS EXT) not supported"));command_aborted(0x37); break; - case 0x38: BX_ERROR(("write cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported"));command_aborted(0x38); break; - case 0x39: BX_ERROR(("write cmd 0x39 (WRITE MULTIPLE EXT) not supported"));command_aborted(0x39); break; - case 0x3A: BX_ERROR(("write cmd 0x3A (WRITE STREAM DMA) not supported"));command_aborted(0x3A); break; - case 0x3B: BX_ERROR(("write cmd 0x3B (WRITE STREAM PIO) not supported"));command_aborted(0x3B); break; - case 0x3F: BX_ERROR(("write cmd 0x3F (WRITE LOG EXT) not supported"));command_aborted(0x3F); break; - case 0x41: BX_ERROR(("write cmd 0x41 (READ VERIFY SECTORS NO RETRY) not supported")); command_aborted(0x41); break; - case 0x42: BX_ERROR(("write cmd 0x42 (READ VERIFY SECTORS EXT) not supported"));command_aborted(0x42); break; - case 0x50: BX_ERROR(("write cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(0x50); break; - case 0x51: BX_ERROR(("write cmd 0x51 (CONFIGURE STREAM) not supported"));command_aborted(0x51); break; - case 0x87: BX_ERROR(("write cmd 0x87 (CFA TRANSLATE SECTOR) not supported"));command_aborted(0x87); break; - case 0x92: BX_ERROR(("write cmd 0x92 (DOWNLOAD MICROCODE) not supported"));command_aborted(0x92); break; - case 0x94: BX_ERROR(("write cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(0x94); break; - case 0x95: BX_ERROR(("write cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(0x95); break; - case 0x96: BX_ERROR(("write cmd 0x96 (STANDBY) not supported")); command_aborted(0x96); break; - case 0x97: BX_ERROR(("write cmd 0x97 (IDLE) not supported")); command_aborted(0x97); break; - case 0x98: BX_ERROR(("write cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(0x98); break; - case 0x99: BX_ERROR(("write cmd 0x99 (SLEEP) not supported")); command_aborted(0x99); break; - case 0xB0: BX_ERROR(("write cmd 0xB0 (SMART commands) not supported"));command_aborted(0xB0); break; - case 0xB1: BX_ERROR(("write cmd 0xB1 (DEVICE CONFIGURATION commands) not supported"));command_aborted(0xB1); break; - case 0xC0: BX_ERROR(("write cmd 0xC0 (CFA ERASE SECTORS) not supported"));command_aborted(0xC0); break; - case 0xC4: BX_ERROR(("write cmd 0xC4 (READ MULTIPLE) not supported"));command_aborted(0xC4); break; - case 0xC5: BX_ERROR(("write cmd 0xC5 (WRITE MULTIPLE) not supported"));command_aborted(0xC5); break; - case 0xC7: BX_ERROR(("write cmd 0xC7 (READ DMA QUEUED) not supported"));command_aborted(0xC7); break; - case 0xC8: BX_ERROR(("write cmd 0xC8 (READ DMA) not supported"));command_aborted(0xC8); break; - case 0xC9: BX_ERROR(("write cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(0xC9); break; - case 0xCA: BX_ERROR(("write cmd 0xCA (WRITE DMA) not supported"));command_aborted(0xCA); break; - case 0xCC: BX_ERROR(("write cmd 0xCC (WRITE DMA QUEUED) not supported"));command_aborted(0xCC); break; - case 0xCD: BX_ERROR(("write cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported"));command_aborted(0xCD); break; - case 0xD1: BX_ERROR(("write cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported"));command_aborted(0xD1); break; - case 0xDA: BX_ERROR(("write cmd 0xDA (GET MEDIA STATUS) not supported"));command_aborted(0xDA); break; - case 0xDE: BX_ERROR(("write cmd 0xDE (MEDIA LOCK) not supported"));command_aborted(0xDE); break; - case 0xDF: BX_ERROR(("write cmd 0xDF (MEDIA UNLOCK) not supported"));command_aborted(0xDF); break; - case 0xE0: BX_ERROR(("write cmd 0xE0 (STANDBY IMMEDIATE) not supported"));command_aborted(0xE0); break; - case 0xE1: BX_ERROR(("write cmd 0xE1 (IDLE IMMEDIATE) not supported"));command_aborted(0xE1); break; - case 0xE2: BX_ERROR(("write cmd 0xE2 (STANDBY) not supported"));command_aborted(0xE2); break; - case 0xE3: BX_ERROR(("write cmd 0xE3 (IDLE) not supported"));command_aborted(0xE3); break; - case 0xE4: BX_ERROR(("write cmd 0xE4 (READ BUFFER) not supported"));command_aborted(0xE4); break; - case 0xE6: BX_ERROR(("write cmd 0xE6 (SLEEP) not supported"));command_aborted(0xE6); break; - case 0xE7: BX_ERROR(("write cmd 0xE7 (FLUSH CACHE) not supported"));command_aborted(0xE7); break; - case 0xE8: BX_ERROR(("write cmd 0xE8 (WRITE BUFFER) not supported"));command_aborted(0xE8); break; - case 0xEA: BX_ERROR(("write cmd 0xEA (FLUSH CACHE EXT) not supported"));command_aborted(0xEA); break; - case 0xED: BX_ERROR(("write cmd 0xED (MEDIA EJECT) not supported"));command_aborted(0xED); break; - case 0xF1: BX_ERROR(("write cmd 0xF1 (SECURITY SET PASSWORD) not supported"));command_aborted(0xF1); break; - case 0xF2: BX_ERROR(("write cmd 0xF2 (SECURITY UNLOCK) not supported"));command_aborted(0xF2); break; - case 0xF3: BX_ERROR(("write cmd 0xF3 (SECURITY ERASE PREPARE) not supported"));command_aborted(0xF3); break; - case 0xF4: BX_ERROR(("write cmd 0xF4 (SECURITY ERASE UNIT) not supported"));command_aborted(0xF4); break; - case 0xF5: BX_ERROR(("write cmd 0xF5 (SECURITY FREEZE LOCK) not supported"));command_aborted(0xF5); break; - case 0xF6: BX_ERROR(("write cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported"));command_aborted(0xF6); break; - case 0xF8: BX_ERROR(("write cmd 0xF8 (READ NATIVE MAX ADDRESS) not supported"));command_aborted(0xF8); break; - case 0xF9: BX_ERROR(("write cmd 0xF9 (SET MAX ADDRESS) not supported"));command_aborted(0xF9); break; + case 0x22: BX_ERROR(("write cmd 0x22 (READ LONG) not supported")); command_aborted(channel, 0x22); break; + case 0x23: BX_ERROR(("write cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(channel, 0x23); break; + case 0x24: BX_ERROR(("write cmd 0x24 (READ SECTORS EXT) not supported"));command_aborted(channel, 0x24); break; + case 0x25: BX_ERROR(("write cmd 0x25 (READ DMA EXT) not supported"));command_aborted(channel, 0x25); break; + case 0x26: BX_ERROR(("write cmd 0x26 (READ DMA QUEUED EXT) not supported"));command_aborted(channel, 0x26); break; + case 0x27: BX_ERROR(("write cmd 0x27 (READ NATIVE MAX ADDRESS EXT) not supported"));command_aborted(channel, 0x27); break; + case 0x29: BX_ERROR(("write cmd 0x29 (READ MULTIPLE EXT) not supported"));command_aborted(channel, 0x29); break; + case 0x2A: BX_ERROR(("write cmd 0x2A (READ STREAM DMA) not supported"));command_aborted(channel, 0x2A); break; + case 0x2B: BX_ERROR(("write cmd 0x2B (READ STREAM PIO) not supported"));command_aborted(channel, 0x2B); break; + case 0x2F: BX_ERROR(("write cmd 0x2F (READ LOG EXT) not supported"));command_aborted(channel, 0x2F); break; + case 0x31: BX_ERROR(("write cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(channel, 0x31); break; + case 0x32: BX_ERROR(("write cmd 0x32 (WRITE LONG) not supported")); command_aborted(channel, 0x32); break; + case 0x33: BX_ERROR(("write cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(channel, 0x33); break; + case 0x34: BX_ERROR(("write cmd 0x34 (WRITE SECTORS EXT) not supported"));command_aborted(channel, 0x34); break; + case 0x35: BX_ERROR(("write cmd 0x35 (WRITE DMA EXT) not supported"));command_aborted(channel, 0x35); break; + case 0x36: BX_ERROR(("write cmd 0x36 (WRITE DMA QUEUED EXT) not supported"));command_aborted(channel, 0x36); break; + case 0x37: BX_ERROR(("write cmd 0x37 (SET MAX ADDRESS EXT) not supported"));command_aborted(channel, 0x37); break; + case 0x38: BX_ERROR(("write cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported"));command_aborted(channel, 0x38); break; + case 0x39: BX_ERROR(("write cmd 0x39 (WRITE MULTIPLE EXT) not supported"));command_aborted(channel, 0x39); break; + case 0x3A: BX_ERROR(("write cmd 0x3A (WRITE STREAM DMA) not supported"));command_aborted(channel, 0x3A); break; + case 0x3B: BX_ERROR(("write cmd 0x3B (WRITE STREAM PIO) not supported"));command_aborted(channel, 0x3B); break; + case 0x3F: BX_ERROR(("write cmd 0x3F (WRITE LOG EXT) not supported"));command_aborted(channel, 0x3F); break; + case 0x41: BX_ERROR(("write cmd 0x41 (READ VERIFY SECTORS NO RETRY) not supported")); command_aborted(channel, 0x41); break; + case 0x42: BX_ERROR(("write cmd 0x42 (READ VERIFY SECTORS EXT) not supported"));command_aborted(channel, 0x42); break; + case 0x50: BX_ERROR(("write cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(channel, 0x50); break; + case 0x51: BX_ERROR(("write cmd 0x51 (CONFIGURE STREAM) not supported"));command_aborted(channel, 0x51); break; + case 0x87: BX_ERROR(("write cmd 0x87 (CFA TRANSLATE SECTOR) not supported"));command_aborted(channel, 0x87); break; + case 0x92: BX_ERROR(("write cmd 0x92 (DOWNLOAD MICROCODE) not supported"));command_aborted(channel, 0x92); break; + case 0x94: BX_ERROR(("write cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0x94); break; + case 0x95: BX_ERROR(("write cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0x95); break; + case 0x96: BX_ERROR(("write cmd 0x96 (STANDBY) not supported")); command_aborted(channel, 0x96); break; + case 0x97: BX_ERROR(("write cmd 0x97 (IDLE) not supported")); command_aborted(channel, 0x97); break; + case 0x98: BX_ERROR(("write cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(channel, 0x98); break; + case 0x99: BX_ERROR(("write cmd 0x99 (SLEEP) not supported")); command_aborted(channel, 0x99); break; + case 0xB0: BX_ERROR(("write cmd 0xB0 (SMART commands) not supported"));command_aborted(channel, 0xB0); break; + case 0xB1: BX_ERROR(("write cmd 0xB1 (DEVICE CONFIGURATION commands) not supported"));command_aborted(channel, 0xB1); break; + case 0xC0: BX_ERROR(("write cmd 0xC0 (CFA ERASE SECTORS) not supported"));command_aborted(channel, 0xC0); break; + case 0xC4: BX_ERROR(("write cmd 0xC4 (READ MULTIPLE) not supported"));command_aborted(channel, 0xC4); break; + case 0xC5: BX_ERROR(("write cmd 0xC5 (WRITE MULTIPLE) not supported"));command_aborted(channel, 0xC5); break; + case 0xC7: BX_ERROR(("write cmd 0xC7 (READ DMA QUEUED) not supported"));command_aborted(channel, 0xC7); break; + case 0xC8: BX_ERROR(("write cmd 0xC8 (READ DMA) not supported"));command_aborted(channel, 0xC8); break; + case 0xC9: BX_ERROR(("write cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(channel, 0xC9); break; + case 0xCA: BX_ERROR(("write cmd 0xCA (WRITE DMA) not supported"));command_aborted(channel, 0xCA); break; + case 0xCC: BX_ERROR(("write cmd 0xCC (WRITE DMA QUEUED) not supported"));command_aborted(channel, 0xCC); break; + case 0xCD: BX_ERROR(("write cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported"));command_aborted(channel, 0xCD); break; + case 0xD1: BX_ERROR(("write cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported"));command_aborted(channel, 0xD1); break; + case 0xDA: BX_ERROR(("write cmd 0xDA (GET MEDIA STATUS) not supported"));command_aborted(channel, 0xDA); break; + case 0xDE: BX_ERROR(("write cmd 0xDE (MEDIA LOCK) not supported"));command_aborted(channel, 0xDE); break; + case 0xDF: BX_ERROR(("write cmd 0xDF (MEDIA UNLOCK) not supported"));command_aborted(channel, 0xDF); break; + case 0xE0: BX_ERROR(("write cmd 0xE0 (STANDBY IMMEDIATE) not supported"));command_aborted(channel, 0xE0); break; + case 0xE1: BX_ERROR(("write cmd 0xE1 (IDLE IMMEDIATE) not supported"));command_aborted(channel, 0xE1); break; + case 0xE2: BX_ERROR(("write cmd 0xE2 (STANDBY) not supported"));command_aborted(channel, 0xE2); break; + case 0xE3: BX_ERROR(("write cmd 0xE3 (IDLE) not supported"));command_aborted(channel, 0xE3); break; + case 0xE4: BX_ERROR(("write cmd 0xE4 (READ BUFFER) not supported"));command_aborted(channel, 0xE4); break; + case 0xE6: BX_ERROR(("write cmd 0xE6 (SLEEP) not supported"));command_aborted(channel, 0xE6); break; + case 0xE7: BX_ERROR(("write cmd 0xE7 (FLUSH CACHE) not supported"));command_aborted(channel, 0xE7); break; + case 0xE8: BX_ERROR(("write cmd 0xE8 (WRITE BUFFER) not supported"));command_aborted(channel, 0xE8); break; + case 0xEA: BX_ERROR(("write cmd 0xEA (FLUSH CACHE EXT) not supported"));command_aborted(channel, 0xEA); break; + case 0xED: BX_ERROR(("write cmd 0xED (MEDIA EJECT) not supported"));command_aborted(channel, 0xED); break; + case 0xF1: BX_ERROR(("write cmd 0xF1 (SECURITY SET PASSWORD) not supported"));command_aborted(channel, 0xF1); break; + case 0xF2: BX_ERROR(("write cmd 0xF2 (SECURITY UNLOCK) not supported"));command_aborted(channel, 0xF2); break; + case 0xF3: BX_ERROR(("write cmd 0xF3 (SECURITY ERASE PREPARE) not supported"));command_aborted(channel, 0xF3); break; + case 0xF4: BX_ERROR(("write cmd 0xF4 (SECURITY ERASE UNIT) not supported"));command_aborted(channel, 0xF4); break; + case 0xF5: BX_ERROR(("write cmd 0xF5 (SECURITY FREEZE LOCK) not supported"));command_aborted(channel, 0xF5); break; + case 0xF6: BX_ERROR(("write cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported"));command_aborted(channel, 0xF6); break; + case 0xF8: BX_ERROR(("write cmd 0xF8 (READ NATIVE MAX ADDRESS) not supported"));command_aborted(channel, 0xF8); break; + case 0xF9: BX_ERROR(("write cmd 0xF9 (SET MAX ADDRESS) not supported"));command_aborted(channel, 0xF9); break; default: BX_PANIC(("IO write(1f7h): command 0x%02x", (unsigned) value)); // if user foolishly decides to continue, abort the command // so that the software knows the drive didn't understand it. - command_aborted(value); + command_aborted(channel, value); } break; - case 0x3f6: // hard disk adapter control + case 0x16: // hard disk adapter control 0x3f6 // (mch) Even if device 1 was selected, a write to this register // goes to device 0 (if device 1 is absent) - prev_control_reset = BX_SELECTED_CONTROLLER.control.reset; - BX_HD_THIS s[0].controller.control.reset = value & 0x04; - BX_HD_THIS s[1].controller.control.reset = value & 0x04; - // CGS: was: BX_SELECTED_CONTROLLER.control.disable_irq = value & 0x02; - BX_HD_THIS s[0].controller.control.disable_irq = value & 0x02; - BX_HD_THIS s[1].controller.control.disable_irq = value & 0x02; - //BX_DEBUG(( "adpater control reg: reset controller = %d", - // (unsigned) (BX_SELECTED_CONTROLLER.control.reset) ? 1 : 0 )); - //BX_DEBUG(( "adpater control reg: disable_irq(14) = %d", - // (unsigned) (BX_SELECTED_CONTROLLER.control.disable_irq) ? 1 : 0 )); - if (!prev_control_reset && BX_SELECTED_CONTROLLER.control.reset) { + prev_control_reset = BX_SELECTED_CONTROLLER(channel).control.reset; + BX_HD_THIS channels[channel].drives[0].controller.control.reset = value & 0x04; + BX_HD_THIS channels[channel].drives[1].controller.control.reset = value & 0x04; + // CGS: was: BX_SELECTED_CONTROLLER(channel).control.disable_irq = value & 0x02; + BX_HD_THIS channels[channel].drives[0].controller.control.disable_irq = value & 0x02; + BX_HD_THIS channels[channel].drives[1].controller.control.disable_irq = value & 0x02; + + BX_DEBUG(( "adpater control reg: reset controller = %d", + (unsigned) (BX_SELECTED_CONTROLLER(channel).control.reset) ? 1 : 0 )); + BX_DEBUG(( "adpater control reg: disable_irq(X) = %d", + (unsigned) (BX_SELECTED_CONTROLLER(channel).control.disable_irq) ? 1 : 0 )); + + if (!prev_control_reset && BX_SELECTED_CONTROLLER(channel).control.reset) { // transition from 0 to 1 causes all drives to reset BX_DEBUG(("hard drive: RESET")); // (mch) Set BSY, drive not ready for (int id = 0; id < 2; id++) { - BX_CONTROLLER(id).status.busy = 1; - BX_CONTROLLER(id).status.drive_ready = 0; - BX_CONTROLLER(id).reset_in_progress = 1; + BX_CONTROLLER(channel,id).status.busy = 1; + BX_CONTROLLER(channel,id).status.drive_ready = 0; + BX_CONTROLLER(channel,id).reset_in_progress = 1; - BX_CONTROLLER(id).status.write_fault = 0; - BX_CONTROLLER(id).status.seek_complete = 1; - BX_CONTROLLER(id).status.drq = 0; - BX_CONTROLLER(id).status.corrected_data = 0; - BX_CONTROLLER(id).status.err = 0; + BX_CONTROLLER(channel,id).status.write_fault = 0; + BX_CONTROLLER(channel,id).status.seek_complete = 1; + BX_CONTROLLER(channel,id).status.drq = 0; + BX_CONTROLLER(channel,id).status.corrected_data = 0; + BX_CONTROLLER(channel,id).status.err = 0; - BX_CONTROLLER(id).error_register = 0x01; // diagnostic code: no error + BX_CONTROLLER(channel,id).error_register = 0x01; // diagnostic code: no error - BX_CONTROLLER(id).current_command = 0x00; - BX_CONTROLLER(id).buffer_index = 0; + BX_CONTROLLER(channel,id).current_command = 0x00; + BX_CONTROLLER(channel,id).buffer_index = 0; - BX_CONTROLLER(id).sectors_per_block = 0x80; - BX_CONTROLLER(id).lba_mode = 0; + BX_CONTROLLER(channel,id).sectors_per_block = 0x80; + BX_CONTROLLER(channel,id).lba_mode = 0; - BX_CONTROLLER(id).control.disable_irq = 0; + BX_CONTROLLER(channel,id).control.disable_irq = 0; } - } else if (BX_SELECTED_CONTROLLER.reset_in_progress && - !BX_SELECTED_CONTROLLER.control.reset) { + } else if (BX_SELECTED_CONTROLLER(channel).reset_in_progress && + !BX_SELECTED_CONTROLLER(channel).control.reset) { // Clear BSY and DRDY - BX_DEBUG(("Reset complete {%s}", DEVICE_TYPE_STRING)); + BX_DEBUG(("Reset complete {%s}", BX_SELECTED_TYPE_STRING(channel))); for (int id = 0; id < 2; id++) { - BX_CONTROLLER(id).status.busy = 0; - BX_CONTROLLER(id).status.drive_ready = 1; - BX_CONTROLLER(id).reset_in_progress = 0; + BX_CONTROLLER(channel,id).status.busy = 0; + BX_CONTROLLER(channel,id).status.drive_ready = 1; + BX_CONTROLLER(channel,id).reset_in_progress = 0; // Device signature - if (BX_HD_THIS s[id].device_type == IDE_DISK) { - BX_CONTROLLER(id).head_no = 0; - BX_CONTROLLER(id).sector_count = 1; - BX_CONTROLLER(id).sector_no = 1; - BX_CONTROLLER(id).cylinder_no = 0; + if (BX_DRIVE_IS_HD(channel,id)) { + BX_CONTROLLER(channel,id).head_no = 0; + BX_CONTROLLER(channel,id).sector_count = 1; + BX_CONTROLLER(channel,id).sector_no = 1; + BX_CONTROLLER(channel,id).cylinder_no = 0; } else { - BX_CONTROLLER(id).head_no = 0; - BX_CONTROLLER(id).sector_count = 1; - BX_CONTROLLER(id).sector_no = 1; - BX_CONTROLLER(id).cylinder_no = 0xeb14; + BX_CONTROLLER(channel,id).head_no = 0; + BX_CONTROLLER(channel,id).sector_count = 1; + BX_CONTROLLER(channel,id).sector_no = 1; + BX_CONTROLLER(channel,id).cylinder_no = 0xeb14; } } } - BX_DEBUG(("s[0].controller.control.disable_irq = %02x", (BX_HD_THIS s[0]).controller.control.disable_irq)); - BX_DEBUG(("s[1].controller.control.disable_irq = %02x", (BX_HD_THIS s[1]).controller.control.disable_irq)); + BX_DEBUG(("s[0].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[0]).controller.control.disable_irq)); + BX_DEBUG(("s[1].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[1]).controller.control.disable_irq)); break; -#if 0 - // you'll need these to support second IDE controller, not needed yet. - case 0x170: - case 0x171: - case 0x172: - case 0x173: - case 0x174: - case 0x175: - case 0x176: - case 0x177: - BX_DEBUG(("ignoring write to 0x%04x", address)); - break; -#endif default: BX_PANIC(("hard drive: io write to address %x = %02x", @@ -2132,30 +2191,32 @@ void bx_hard_drive_c::close_harddrive(void) { - BX_HD_THIS s[0].hard_drive->close(); - BX_HD_THIS s[1].hard_drive->close(); + for (Bit8u channel=0; channelclose(); + BX_HD_THIS channels[channel].drives[1].hard_drive->close(); + } } Boolean -bx_hard_drive_c::calculate_logical_address(Bit32u *sector) +bx_hard_drive_c::calculate_logical_address(Bit8u channel, Bit32u *sector) { Bit32u logical_sector; - if (BX_SELECTED_CONTROLLER.lba_mode) { - //bx_printf ("disk: calculate: %d %d %d\n", ((Bit32u)BX_SELECTED_CONTROLLER.head_no), ((Bit32u)BX_SELECTED_CONTROLLER.cylinder_no), (Bit32u)BX_SELECTED_CONTROLLER.sector_no); - logical_sector = ((Bit32u)BX_SELECTED_CONTROLLER.head_no) << 24 | - ((Bit32u)BX_SELECTED_CONTROLLER.cylinder_no) << 8 | - (Bit32u)BX_SELECTED_CONTROLLER.sector_no; + if (BX_SELECTED_CONTROLLER(channel).lba_mode) { + //bx_printf ("disk: calculate: %d %d %d\n", ((Bit32u)BX_SELECTED_CONTROLLER(channel).head_no), ((Bit32u)BX_SELECTED_CONTROLLER(channel).cylinder_no), (Bit32u)BX_SELECTED_CONTROLLER(channel).sector_no); + logical_sector = ((Bit32u)BX_SELECTED_CONTROLLER(channel).head_no) << 24 | + ((Bit32u)BX_SELECTED_CONTROLLER(channel).cylinder_no) << 8 | + (Bit32u)BX_SELECTED_CONTROLLER(channel).sector_no; //bx_printf ("disk: result: %u\n", logical_sector); } else - logical_sector = (BX_SELECTED_CONTROLLER.cylinder_no * BX_SELECTED_HD.hard_drive->heads * - BX_SELECTED_HD.hard_drive->sectors) + - (BX_SELECTED_CONTROLLER.head_no * BX_SELECTED_HD.hard_drive->sectors) + - (BX_SELECTED_CONTROLLER.sector_no - 1); + logical_sector = (BX_SELECTED_CONTROLLER(channel).cylinder_no * BX_SELECTED_DRIVE(channel).hard_drive->heads * + BX_SELECTED_DRIVE(channel).hard_drive->sectors) + + (BX_SELECTED_CONTROLLER(channel).head_no * BX_SELECTED_DRIVE(channel).hard_drive->sectors) + + (BX_SELECTED_CONTROLLER(channel).sector_no - 1); if (logical_sector >= - (BX_SELECTED_HD.hard_drive->cylinders * BX_SELECTED_HD.hard_drive->heads * BX_SELECTED_HD.hard_drive->sectors)) { + (BX_SELECTED_DRIVE(channel).hard_drive->cylinders * BX_SELECTED_DRIVE(channel).hard_drive->heads * BX_SELECTED_DRIVE(channel).hard_drive->sectors)) { BX_ERROR (("calc_log_addr: out of bounds")); return false; } @@ -2164,246 +2225,238 @@ } void -bx_hard_drive_c::increment_address() +bx_hard_drive_c::increment_address(Bit8u channel) { - BX_SELECTED_CONTROLLER.sector_count--; + BX_SELECTED_CONTROLLER(channel).sector_count--; - if (BX_SELECTED_CONTROLLER.lba_mode) { + if (BX_SELECTED_CONTROLLER(channel).lba_mode) { Bit32u current_address; - calculate_logical_address(¤t_address); + calculate_logical_address(channel, ¤t_address); current_address++; - BX_SELECTED_CONTROLLER.head_no = (current_address >> 24) & 0xf; - BX_SELECTED_CONTROLLER.cylinder_no = (current_address >> 8) & 0xffff; - BX_SELECTED_CONTROLLER.sector_no = (current_address) & 0xff; + BX_SELECTED_CONTROLLER(channel).head_no = (current_address >> 24) & 0xf; + BX_SELECTED_CONTROLLER(channel).cylinder_no = (current_address >> 8) & 0xffff; + BX_SELECTED_CONTROLLER(channel).sector_no = (current_address) & 0xff; } else { - BX_SELECTED_CONTROLLER.sector_no++; - if (BX_SELECTED_CONTROLLER.sector_no > BX_SELECTED_HD.hard_drive->sectors) { - BX_SELECTED_CONTROLLER.sector_no = 1; - BX_SELECTED_CONTROLLER.head_no++; - if (BX_SELECTED_CONTROLLER.head_no >= BX_SELECTED_HD.hard_drive->heads) { - BX_SELECTED_CONTROLLER.head_no = 0; - BX_SELECTED_CONTROLLER.cylinder_no++; - if (BX_SELECTED_CONTROLLER.cylinder_no >= BX_SELECTED_HD.hard_drive->cylinders) - BX_SELECTED_CONTROLLER.cylinder_no = BX_SELECTED_HD.hard_drive->cylinders - 1; + BX_SELECTED_CONTROLLER(channel).sector_no++; + if (BX_SELECTED_CONTROLLER(channel).sector_no > BX_SELECTED_DRIVE(channel).hard_drive->sectors) { + BX_SELECTED_CONTROLLER(channel).sector_no = 1; + BX_SELECTED_CONTROLLER(channel).head_no++; + if (BX_SELECTED_CONTROLLER(channel).head_no >= BX_SELECTED_DRIVE(channel).hard_drive->heads) { + BX_SELECTED_CONTROLLER(channel).head_no = 0; + BX_SELECTED_CONTROLLER(channel).cylinder_no++; + if (BX_SELECTED_CONTROLLER(channel).cylinder_no >= BX_SELECTED_DRIVE(channel).hard_drive->cylinders) + BX_SELECTED_CONTROLLER(channel).cylinder_no = BX_SELECTED_DRIVE(channel).hard_drive->cylinders - 1; } } } } void -bx_hard_drive_c::identify_ATAPI_drive(unsigned drive) +bx_hard_drive_c::identify_ATAPI_drive(Bit8u channel) { unsigned i; - if (drive != (unsigned)BX_HD_THIS drive_select) { - BX_PANIC(("identify_drive panic (drive != drive_select)")); - } - - BX_SELECTED_HD.id_drive[0] = (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0); // Removable CDROM, 50us response, 12 byte packets + BX_SELECTED_DRIVE(channel).id_drive[0] = (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0); // Removable CDROM, 50us response, 12 byte packets for (i = 1; i <= 9; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0"; for (i = 0; i < 10; i++) { - BX_SELECTED_HD.id_drive[10+i] = (serial_number[i*2] << 8) | + BX_SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) | serial_number[i*2 + 1]; } for (i = 20; i <= 22; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; const char* firmware = "ALPHA1 "; for (i = 0; i < strlen(firmware)/2; i++) { - BX_SELECTED_HD.id_drive[23+i] = (firmware[i*2] << 8) | + BX_SELECTED_DRIVE(channel).id_drive[23+i] = (firmware[i*2] << 8) | firmware[i*2 + 1]; } BX_ASSERT((23+i) == 27); - for (i = 0; i < strlen((char *) model_no)/2; i++) { - BX_SELECTED_HD.id_drive[27+i] = (model_no[i*2] << 8) | - model_no[i*2 + 1]; + for (i = 0; i < strlen((char *) BX_SELECTED_MODEL(channel))/2; i++) { + BX_SELECTED_DRIVE(channel).id_drive[27+i] = (BX_SELECTED_MODEL(channel)[i*2] << 8) | + BX_SELECTED_MODEL(channel)[i*2 + 1]; } BX_ASSERT((27+i) == 47); - BX_SELECTED_HD.id_drive[47] = 0; - BX_SELECTED_HD.id_drive[48] = 1; // 32 bits access + BX_SELECTED_DRIVE(channel).id_drive[47] = 0; + BX_SELECTED_DRIVE(channel).id_drive[48] = 1; // 32 bits access - BX_SELECTED_HD.id_drive[49] = (1 << 9); // LBA supported + BX_SELECTED_DRIVE(channel).id_drive[49] = (1 << 9); // LBA supported - BX_SELECTED_HD.id_drive[50] = 0; - BX_SELECTED_HD.id_drive[51] = 0; - BX_SELECTED_HD.id_drive[52] = 0; + BX_SELECTED_DRIVE(channel).id_drive[50] = 0; + BX_SELECTED_DRIVE(channel).id_drive[51] = 0; + BX_SELECTED_DRIVE(channel).id_drive[52] = 0; - BX_SELECTED_HD.id_drive[53] = 3; // words 64-70, 54-58 valid + BX_SELECTED_DRIVE(channel).id_drive[53] = 3; // words 64-70, 54-58 valid for (i = 54; i <= 62; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // copied from CFA540A - BX_SELECTED_HD.id_drive[63] = 0x0103; // variable (DMA stuff) - BX_SELECTED_HD.id_drive[64] = 0x0001; // PIO - BX_SELECTED_HD.id_drive[65] = 0x00b4; - BX_SELECTED_HD.id_drive[66] = 0x00b4; - BX_SELECTED_HD.id_drive[67] = 0x012c; - BX_SELECTED_HD.id_drive[68] = 0x00b4; - - BX_SELECTED_HD.id_drive[69] = 0; - BX_SELECTED_HD.id_drive[70] = 0; - BX_SELECTED_HD.id_drive[71] = 30; // faked - BX_SELECTED_HD.id_drive[72] = 30; // faked - BX_SELECTED_HD.id_drive[73] = 0; - BX_SELECTED_HD.id_drive[74] = 0; + BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0103; // variable (DMA stuff) + BX_SELECTED_DRIVE(channel).id_drive[64] = 0x0001; // PIO + BX_SELECTED_DRIVE(channel).id_drive[65] = 0x00b4; + BX_SELECTED_DRIVE(channel).id_drive[66] = 0x00b4; + BX_SELECTED_DRIVE(channel).id_drive[67] = 0x012c; + BX_SELECTED_DRIVE(channel).id_drive[68] = 0x00b4; + + BX_SELECTED_DRIVE(channel).id_drive[69] = 0; + BX_SELECTED_DRIVE(channel).id_drive[70] = 0; + BX_SELECTED_DRIVE(channel).id_drive[71] = 30; // faked + BX_SELECTED_DRIVE(channel).id_drive[72] = 30; // faked + BX_SELECTED_DRIVE(channel).id_drive[73] = 0; + BX_SELECTED_DRIVE(channel).id_drive[74] = 0; - BX_SELECTED_HD.id_drive[75] = 0; + BX_SELECTED_DRIVE(channel).id_drive[75] = 0; for (i = 76; i <= 79; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - BX_SELECTED_HD.id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4 - BX_SELECTED_HD.id_drive[81] = 0; - BX_SELECTED_HD.id_drive[82] = 0; - BX_SELECTED_HD.id_drive[83] = 0; - BX_SELECTED_HD.id_drive[84] = 0; - BX_SELECTED_HD.id_drive[85] = 0; - BX_SELECTED_HD.id_drive[86] = 0; - BX_SELECTED_HD.id_drive[87] = 0; - BX_SELECTED_HD.id_drive[88] = 0; + BX_SELECTED_DRIVE(channel).id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4 + BX_SELECTED_DRIVE(channel).id_drive[81] = 0; + BX_SELECTED_DRIVE(channel).id_drive[82] = 0; + BX_SELECTED_DRIVE(channel).id_drive[83] = 0; + BX_SELECTED_DRIVE(channel).id_drive[84] = 0; + BX_SELECTED_DRIVE(channel).id_drive[85] = 0; + BX_SELECTED_DRIVE(channel).id_drive[86] = 0; + BX_SELECTED_DRIVE(channel).id_drive[87] = 0; + BX_SELECTED_DRIVE(channel).id_drive[88] = 0; for (i = 89; i <= 126; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - BX_SELECTED_HD.id_drive[127] = 0; - BX_SELECTED_HD.id_drive[128] = 0; + BX_SELECTED_DRIVE(channel).id_drive[127] = 0; + BX_SELECTED_DRIVE(channel).id_drive[128] = 0; for (i = 129; i <= 159; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; for (i = 160; i <= 255; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // now convert the id_drive array (native 256 word format) to // the controller buffer (512 bytes) Bit16u temp16; for (i = 0; i <= 255; i++) { - temp16 = BX_SELECTED_HD.id_drive[i]; - BX_SELECTED_CONTROLLER.buffer[i*2] = temp16 & 0x00ff; - BX_SELECTED_CONTROLLER.buffer[i*2+1] = temp16 >> 8; + temp16 = BX_SELECTED_DRIVE(channel).id_drive[i]; + BX_SELECTED_CONTROLLER(channel).buffer[i*2] = temp16 & 0x00ff; + BX_SELECTED_CONTROLLER(channel).buffer[i*2+1] = temp16 >> 8; } } void -bx_hard_drive_c::identify_drive(unsigned drive) +bx_hard_drive_c::identify_drive(Bit8u channel) { unsigned i; Bit32u temp32; Bit16u temp16; - if (drive != BX_HD_THIS drive_select) { - BX_PANIC(("identify_drive panic (drive != drive_select)")); - } - #if defined(CONNER_CFA540A) - BX_SELECTED_HD.id_drive[0] = 0x0c5a; - BX_SELECTED_HD.id_drive[1] = 0x0418; - BX_SELECTED_HD.id_drive[2] = 0; - BX_SELECTED_HD.id_drive[3] = BX_SELECTED_HD.hard_drive->heads; - BX_SELECTED_HD.id_drive[4] = 0x9fb7; - BX_SELECTED_HD.id_drive[5] = 0x0289; - BX_SELECTED_HD.id_drive[6] = BX_SELECTED_HD.hard_drive->sectors; - BX_SELECTED_HD.id_drive[7] = 0x0030; - BX_SELECTED_HD.id_drive[8] = 0x000a; - BX_SELECTED_HD.id_drive[9] = 0x0000; + BX_SELECTED_DRIVE(channel).id_drive[0] = 0x0c5a; + BX_SELECTED_DRIVE(channel).id_drive[1] = 0x0418; + BX_SELECTED_DRIVE(channel).id_drive[2] = 0; + BX_SELECTED_DRIVE(channel).id_drive[3] = BX_SELECTED_DRIVE(channel).hard_drive->heads; + BX_SELECTED_DRIVE(channel).id_drive[4] = 0x9fb7; + BX_SELECTED_DRIVE(channel).id_drive[5] = 0x0289; + BX_SELECTED_DRIVE(channel).id_drive[6] = BX_SELECTED_DRIVE(channel).hard_drive->sectors; + BX_SELECTED_DRIVE(channel).id_drive[7] = 0x0030; + BX_SELECTED_DRIVE(channel).id_drive[8] = 0x000a; + BX_SELECTED_DRIVE(channel).id_drive[9] = 0x0000; char* serial_number = " CA00GSQ\0\0\0\0\0\0\0\0\0\0\0\0"; for (i = 0; i < 10; i++) { - BX_SELECTED_HD.id_drive[10+i] = (serial_number[i*2] << 8) | + BX_SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) | serial_number[i*2 + 1]; } - BX_SELECTED_HD.id_drive[20] = 3; - BX_SELECTED_HD.id_drive[21] = 512; // 512 Sectors = 256kB cache - BX_SELECTED_HD.id_drive[22] = 4; + BX_SELECTED_DRIVE(channel).id_drive[20] = 3; + BX_SELECTED_DRIVE(channel).id_drive[21] = 512; // 512 Sectors = 256kB cache + BX_SELECTED_DRIVE(channel).id_drive[22] = 4; char* firmware = "8FT054 "; for (i = 0; i < strlen(firmware)/2; i++) { - BX_SELECTED_HD.id_drive[23+i] = (firmware[i*2] << 8) | + BX_SELECTED_DRIVE(channel).id_drive[23+i] = (firmware[i*2] << 8) | firmware[i*2 + 1]; } BX_ASSERT((23+i) == 27); char* model = "Conner Peripherals 540MB - CFA540A "; for (i = 0; i < strlen(model)/2; i++) { - BX_SELECTED_HD.id_drive[27+i] = (model[i*2] << 8) | + BX_SELECTED_DRIVE(channel).id_drive[27+i] = (model[i*2] << 8) | model[i*2 + 1]; } BX_ASSERT((27+i) == 47); - BX_SELECTED_HD.id_drive[47] = 0x8080; // multiple mode identification - BX_SELECTED_HD.id_drive[48] = 0; - BX_SELECTED_HD.id_drive[49] = 0x0f01; - - BX_SELECTED_HD.id_drive[50] = 0; - - BX_SELECTED_HD.id_drive[51] = 0; - BX_SELECTED_HD.id_drive[52] = 0x0002; - BX_SELECTED_HD.id_drive[53] = 0x0003; - BX_SELECTED_HD.id_drive[54] = 0x0418; - - BX_SELECTED_HD.id_drive[55] = BX_SELECTED_HD.hard_drive->heads; - BX_SELECTED_HD.id_drive[56] = BX_SELECTED_HD.hard_drive->sectors; - - BX_SELECTED_HD.id_drive[57] = 0x1e80; - BX_SELECTED_HD.id_drive[58] = 0x0010; - BX_SELECTED_HD.id_drive[59] = 0x0100 | BX_SELECTED_CONTROLLER.sectors_per_block; - BX_SELECTED_HD.id_drive[60] = 0x20e0; - BX_SELECTED_HD.id_drive[61] = 0x0010; - - BX_SELECTED_HD.id_drive[62] = 0; - - BX_SELECTED_HD.id_drive[63] = 0x0103; // variable (DMA stuff) - BX_SELECTED_HD.id_drive[64] = 0x0001; // PIO - BX_SELECTED_HD.id_drive[65] = 0x00b4; - BX_SELECTED_HD.id_drive[66] = 0x00b4; - BX_SELECTED_HD.id_drive[67] = 0x012c; - BX_SELECTED_HD.id_drive[68] = 0x00b4; + BX_SELECTED_DRIVE(channel).id_drive[47] = 0x8080; // multiple mode identification + BX_SELECTED_DRIVE(channel).id_drive[48] = 0; + BX_SELECTED_DRIVE(channel).id_drive[49] = 0x0f01; + + BX_SELECTED_DRIVE(channel).id_drive[50] = 0; + + BX_SELECTED_DRIVE(channel).id_drive[51] = 0; + BX_SELECTED_DRIVE(channel).id_drive[52] = 0x0002; + BX_SELECTED_DRIVE(channel).id_drive[53] = 0x0003; + BX_SELECTED_DRIVE(channel).id_drive[54] = 0x0418; + + BX_SELECTED_DRIVE(channel).id_drive[55] = BX_SELECTED_DRIVE(channel).hard_drive->heads; + BX_SELECTED_DRIVE(channel).id_drive[56] = BX_SELECTED_DRIVE(channel).hard_drive->sectors; + + BX_SELECTED_DRIVE(channel).id_drive[57] = 0x1e80; + BX_SELECTED_DRIVE(channel).id_drive[58] = 0x0010; + BX_SELECTED_DRIVE(channel).id_drive[59] = 0x0100 | BX_SELECTED_CONTROLLER(channel).sectors_per_block; + BX_SELECTED_DRIVE(channel).id_drive[60] = 0x20e0; + BX_SELECTED_DRIVE(channel).id_drive[61] = 0x0010; + + BX_SELECTED_DRIVE(channel).id_drive[62] = 0; + + BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0103; // variable (DMA stuff) + BX_SELECTED_DRIVE(channel).id_drive[64] = 0x0001; // PIO + BX_SELECTED_DRIVE(channel).id_drive[65] = 0x00b4; + BX_SELECTED_DRIVE(channel).id_drive[66] = 0x00b4; + BX_SELECTED_DRIVE(channel).id_drive[67] = 0x012c; + BX_SELECTED_DRIVE(channel).id_drive[68] = 0x00b4; for (i = 69; i <= 79; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - BX_SELECTED_HD.id_drive[80] = 0; + BX_SELECTED_DRIVE(channel).id_drive[80] = 0; - BX_SELECTED_HD.id_drive[81] = 0; + BX_SELECTED_DRIVE(channel).id_drive[81] = 0; - BX_SELECTED_HD.id_drive[82] = 0; - BX_SELECTED_HD.id_drive[83] = 0; - BX_SELECTED_HD.id_drive[84] = 0; - BX_SELECTED_HD.id_drive[85] = 0; - BX_SELECTED_HD.id_drive[86] = 0; - BX_SELECTED_HD.id_drive[87] = 0; + BX_SELECTED_DRIVE(channel).id_drive[82] = 0; + BX_SELECTED_DRIVE(channel).id_drive[83] = 0; + BX_SELECTED_DRIVE(channel).id_drive[84] = 0; + BX_SELECTED_DRIVE(channel).id_drive[85] = 0; + BX_SELECTED_DRIVE(channel).id_drive[86] = 0; + BX_SELECTED_DRIVE(channel).id_drive[87] = 0; for (i = 88; i <= 127; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - BX_SELECTED_HD.id_drive[128] = 0x0418; - BX_SELECTED_HD.id_drive[129] = 0x103f; - BX_SELECTED_HD.id_drive[130] = 0x0418; - BX_SELECTED_HD.id_drive[131] = 0x103f; - BX_SELECTED_HD.id_drive[132] = 0x0004; - BX_SELECTED_HD.id_drive[133] = 0xffff; - BX_SELECTED_HD.id_drive[134] = 0; - BX_SELECTED_HD.id_drive[135] = 0x5050; + BX_SELECTED_DRIVE(channel).id_drive[128] = 0x0418; + BX_SELECTED_DRIVE(channel).id_drive[129] = 0x103f; + BX_SELECTED_DRIVE(channel).id_drive[130] = 0x0418; + BX_SELECTED_DRIVE(channel).id_drive[131] = 0x103f; + BX_SELECTED_DRIVE(channel).id_drive[132] = 0x0004; + BX_SELECTED_DRIVE(channel).id_drive[133] = 0xffff; + BX_SELECTED_DRIVE(channel).id_drive[134] = 0; + BX_SELECTED_DRIVE(channel).id_drive[135] = 0x5050; for (i = 136; i <= 144; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - BX_SELECTED_HD.id_drive[145] = 0x302e; - BX_SELECTED_HD.id_drive[146] = 0x3245; - BX_SELECTED_HD.id_drive[147] = 0x2020; - BX_SELECTED_HD.id_drive[148] = 0x2020; + BX_SELECTED_DRIVE(channel).id_drive[145] = 0x302e; + BX_SELECTED_DRIVE(channel).id_drive[146] = 0x3245; + BX_SELECTED_DRIVE(channel).id_drive[147] = 0x2020; + BX_SELECTED_DRIVE(channel).id_drive[148] = 0x2020; for (i = 149; i <= 255; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; #else @@ -2433,36 +2486,36 @@ // bit 2: 1=soft sectored // bit 1: 1=hard sectored // bit 0: 0=reserved - BX_SELECTED_HD.id_drive[0] = 0x0040; + BX_SELECTED_DRIVE(channel).id_drive[0] = 0x0040; // Word 1: number of user-addressable cylinders in // default translation mode. If the value in words 60-61 // exceed 16,515,072, this word shall contain 16,383. - BX_SELECTED_HD.id_drive[1] = BX_SELECTED_HD.hard_drive->cylinders; + BX_SELECTED_DRIVE(channel).id_drive[1] = BX_SELECTED_DRIVE(channel).hard_drive->cylinders; // Word 2: reserved - BX_SELECTED_HD.id_drive[2] = 0; + BX_SELECTED_DRIVE(channel).id_drive[2] = 0; // Word 3: number of user-addressable heads in default // translation mode - BX_SELECTED_HD.id_drive[3] = BX_SELECTED_HD.hard_drive->heads; + BX_SELECTED_DRIVE(channel).id_drive[3] = BX_SELECTED_DRIVE(channel).hard_drive->heads; // Word 4: # unformatted bytes per translated track in default xlate mode // Word 5: # unformatted bytes per sector in default xlated mode // Word 6: # user-addressable sectors per track in default xlate mode // Note: words 4,5 are now "Vendor specific (obsolete)" - BX_SELECTED_HD.id_drive[4] = (512 * BX_SELECTED_HD.hard_drive->sectors); - BX_SELECTED_HD.id_drive[5] = 512; - BX_SELECTED_HD.id_drive[6] = BX_SELECTED_HD.hard_drive->sectors; + BX_SELECTED_DRIVE(channel).id_drive[4] = (512 * BX_SELECTED_DRIVE(channel).hard_drive->sectors); + BX_SELECTED_DRIVE(channel).id_drive[5] = 512; + BX_SELECTED_DRIVE(channel).id_drive[6] = BX_SELECTED_DRIVE(channel).hard_drive->sectors; // Word 7-9: Vendor specific for (i=7; i<=9; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // Word 10-19: Serial number (20 ASCII characters, 0000h=not specified) // This field is right justified and padded with spaces (20h). for (i=10; i<=19; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // Word 20: buffer type // 0000h = not specified @@ -2475,92 +2528,92 @@ // simulatenous data xfers with a read caching // capability. // 0004h-ffffh = reserved - BX_SELECTED_HD.id_drive[20] = 3; + BX_SELECTED_DRIVE(channel).id_drive[20] = 3; // Word 21: buffer size in 512 byte increments, 0000h = not specified - BX_SELECTED_HD.id_drive[21] = 512; // 512 Sectors = 256kB cache + BX_SELECTED_DRIVE(channel).id_drive[21] = 512; // 512 Sectors = 256kB cache // Word 22: # of ECC bytes available on read/write long cmds // 0000h = not specified - BX_SELECTED_HD.id_drive[22] = 4; + BX_SELECTED_DRIVE(channel).id_drive[22] = 4; // Word 23..26: Firmware revision (8 ascii chars, 0000h=not specified) // This field is left justified and padded with spaces (20h) for (i=23; i<=26; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // Word 27..46: Model number (40 ascii chars, 0000h=not specified) // This field is left justified and padded with spaces (20h) // for (i=27; i<=46; i++) -// BX_SELECTED_HD.id_drive[i] = 0; +// BX_SELECTED_DRIVE(channel).id_drive[i] = 0; for (i=0; i<20; i++) { - BX_SELECTED_HD.id_drive[27+i] = (model_no[i*2] << 8) | - model_no[i*2 + 1]; + BX_SELECTED_DRIVE(channel).id_drive[27+i] = (BX_SELECTED_MODEL(channel)[i*2] << 8) | + BX_SELECTED_MODEL(channel)[i*2 + 1]; } // Word 47: 15-8 Vendor unique // 7-0 00h= read/write multiple commands not implemented // xxh= maximum # of sectors that can be transferred // per interrupt on read and write multiple commands - BX_SELECTED_HD.id_drive[47] = max_multiple_sectors; + BX_SELECTED_DRIVE(channel).id_drive[47] = max_multiple_sectors; // Word 48: 0000h = cannot perform dword IO // 0001h = can perform dword IO - BX_SELECTED_HD.id_drive[48] = 1; + BX_SELECTED_DRIVE(channel).id_drive[48] = 1; // Word 49: Capabilities // 15-10: 0 = reserved // 9: 1 = LBA supported // 8: 1 = DMA supported // 7-0: Vendor unique - BX_SELECTED_HD.id_drive[49] = 1<<9; + BX_SELECTED_DRIVE(channel).id_drive[49] = 1<<9; // Word 50: Reserved - BX_SELECTED_HD.id_drive[50] = 0; + BX_SELECTED_DRIVE(channel).id_drive[50] = 0; // Word 51: 15-8 PIO data transfer cycle timing mode // 7-0 Vendor unique - BX_SELECTED_HD.id_drive[51] = 0x200; + BX_SELECTED_DRIVE(channel).id_drive[51] = 0x200; // Word 52: 15-8 DMA data transfer cycle timing mode // 7-0 Vendor unique - BX_SELECTED_HD.id_drive[52] = 0x200; + BX_SELECTED_DRIVE(channel).id_drive[52] = 0x200; // Word 53: 15-1 Reserved // 0 1=the fields reported in words 54-58 are valid // 0=the fields reported in words 54-58 may be valid - BX_SELECTED_HD.id_drive[53] = 0; + BX_SELECTED_DRIVE(channel).id_drive[53] = 0; // Word 54: # of user-addressable cylinders in curr xlate mode // Word 55: # of user-addressable heads in curr xlate mode // Word 56: # of user-addressable sectors/track in curr xlate mode - BX_SELECTED_HD.id_drive[54] = BX_SELECTED_HD.hard_drive->cylinders; - BX_SELECTED_HD.id_drive[55] = BX_SELECTED_HD.hard_drive->heads; - BX_SELECTED_HD.id_drive[56] = BX_SELECTED_HD.hard_drive->sectors; + BX_SELECTED_DRIVE(channel).id_drive[54] = BX_SELECTED_DRIVE(channel).hard_drive->cylinders; + BX_SELECTED_DRIVE(channel).id_drive[55] = BX_SELECTED_DRIVE(channel).hard_drive->heads; + BX_SELECTED_DRIVE(channel).id_drive[56] = BX_SELECTED_DRIVE(channel).hard_drive->sectors; // Word 57-58: Current capacity in sectors // Excludes all sectors used for device specific purposes. temp32 = - BX_SELECTED_HD.hard_drive->cylinders * - BX_SELECTED_HD.hard_drive->heads * - BX_SELECTED_HD.hard_drive->sectors; - BX_SELECTED_HD.id_drive[57] = (temp32 & 0xffff); // LSW - BX_SELECTED_HD.id_drive[58] = (temp32 >> 16); // MSW + BX_SELECTED_DRIVE(channel).hard_drive->cylinders * + BX_SELECTED_DRIVE(channel).hard_drive->heads * + BX_SELECTED_DRIVE(channel).hard_drive->sectors; + BX_SELECTED_DRIVE(channel).id_drive[57] = (temp32 & 0xffff); // LSW + BX_SELECTED_DRIVE(channel).id_drive[58] = (temp32 >> 16); // MSW // Word 59: 15-9 Reserved // 8 1=multiple sector setting is valid // 7-0 current setting for number of sectors that can be // transferred per interrupt on R/W multiple commands - BX_SELECTED_HD.id_drive[59] = 0x0000 | curr_multiple_sectors; + BX_SELECTED_DRIVE(channel).id_drive[59] = 0x0000 | curr_multiple_sectors; // Word 60-61: // If drive supports LBA Mode, these words reflect total # of user // addressable sectors. This value does not depend on the current // drive geometry. If the drive does not support LBA mode, these // words shall be set to 0. - Bit32u num_sects = BX_SELECTED_HD.hard_drive->cylinders * BX_SELECTED_HD.hard_drive->heads * BX_SELECTED_HD.hard_drive->sectors; - BX_SELECTED_HD.id_drive[60] = num_sects & 0xffff; // LSW - BX_SELECTED_HD.id_drive[61] = num_sects >> 16; // MSW + Bit32u num_sects = BX_SELECTED_DRIVE(channel).hard_drive->cylinders * BX_SELECTED_DRIVE(channel).hard_drive->heads * BX_SELECTED_DRIVE(channel).hard_drive->sectors; + BX_SELECTED_DRIVE(channel).id_drive[60] = num_sects & 0xffff; // LSW + BX_SELECTED_DRIVE(channel).id_drive[61] = num_sects >> 16; // MSW // Word 62: 15-8 single word DMA transfer mode active // 7-0 single word DMA transfer modes supported @@ -2568,7 +2621,7 @@ // supported e.g., if Mode 0 is supported bit 0 is set. // The high order byte contains a single bit set to indiciate // which mode is active. - BX_SELECTED_HD.id_drive[62] = 0x0; + BX_SELECTED_DRIVE(channel).id_drive[62] = 0x0; // Word 63: 15-8 multiword DMA transfer mode active // 7-0 multiword DMA transfer modes supported @@ -2576,11 +2629,11 @@ // supported e.g., if Mode 0 is supported bit 0 is set. // The high order byte contains a single bit set to indiciate // which mode is active. - BX_SELECTED_HD.id_drive[63] = 0x0; + BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0; // Word 64-79 Reserved for (i=64; i<=79; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // Word 80: 15-5 reserved // 4 supports ATA/ATAPI-4 @@ -2588,10 +2641,10 @@ // 2 supports ATA-2 // 1 supports ATA-1 // 0 reserved - BX_SELECTED_HD.id_drive[80] = (1 << 2) | (1 << 1); + BX_SELECTED_DRIVE(channel).id_drive[80] = (1 << 2) | (1 << 1); // Word 81: Minor version number - BX_SELECTED_HD.id_drive[81] = 0; + BX_SELECTED_DRIVE(channel).id_drive[81] = 0; // Word 82: 15 obsolete // 14 NOP command supported @@ -2609,226 +2662,257 @@ // 2 supports removable media feature set // 1 supports securite mode feature set // 0 support SMART feature set - BX_SELECTED_HD.id_drive[82] = 1 << 14; - BX_SELECTED_HD.id_drive[83] = 1 << 14; - BX_SELECTED_HD.id_drive[84] = 1 << 14; - BX_SELECTED_HD.id_drive[85] = 1 << 14; - BX_SELECTED_HD.id_drive[86] = 0; - BX_SELECTED_HD.id_drive[87] = 1 << 14; + BX_SELECTED_DRIVE(channel).id_drive[82] = 1 << 14; + BX_SELECTED_DRIVE(channel).id_drive[83] = 1 << 14; + BX_SELECTED_DRIVE(channel).id_drive[84] = 1 << 14; + BX_SELECTED_DRIVE(channel).id_drive[85] = 1 << 14; + BX_SELECTED_DRIVE(channel).id_drive[86] = 0; + BX_SELECTED_DRIVE(channel).id_drive[87] = 1 << 14; for (i=88; i<=127; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // Word 128-159 Vendor unique for (i=128; i<=159; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // Word 160-255 Reserved for (i=160; i<=255; i++) - BX_SELECTED_HD.id_drive[i] = 0; + BX_SELECTED_DRIVE(channel).id_drive[i] = 0; #endif - BX_DEBUG(("Drive ID Info. initialized : %04d {%s}", 512, DEVICE_TYPE_STRING)); + BX_DEBUG(("Drive ID Info. initialized : %04d {%s}", 512, BX_SELECTED_TYPE_STRING(channel))); // now convert the id_drive array (native 256 word format) to // the controller buffer (512 bytes) for (i=0; i<=255; i++) { - temp16 = BX_SELECTED_HD.id_drive[i]; - BX_SELECTED_CONTROLLER.buffer[i*2] = temp16 & 0x00ff; - BX_SELECTED_CONTROLLER.buffer[i*2+1] = temp16 >> 8; + temp16 = BX_SELECTED_DRIVE(channel).id_drive[i]; + BX_SELECTED_CONTROLLER(channel).buffer[i*2] = temp16 & 0x00ff; + BX_SELECTED_CONTROLLER(channel).buffer[i*2+1] = temp16 >> 8; } } void -bx_hard_drive_c::init_send_atapi_command(Bit8u command, int req_length, int alloc_length, bool lazy) +bx_hard_drive_c::init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy) { - // BX_SELECTED_CONTROLLER.byte_count is a union of BX_SELECTED_CONTROLLER.cylinder_no; + // BX_SELECTED_CONTROLLER(channel).byte_count is a union of BX_SELECTED_CONTROLLER(channel).cylinder_no; // lazy is used to force a data read in the buffer at the next read. - if (BX_SELECTED_CONTROLLER.byte_count == 0xffff) - BX_SELECTED_CONTROLLER.byte_count = 0xfffe; + if (BX_SELECTED_CONTROLLER(channel).byte_count == 0xffff) + BX_SELECTED_CONTROLLER(channel).byte_count = 0xfffe; - if ((BX_SELECTED_CONTROLLER.byte_count & 1) - && !(alloc_length <= BX_SELECTED_CONTROLLER.byte_count)) { + if ((BX_SELECTED_CONTROLLER(channel).byte_count & 1) + && !(alloc_length <= BX_SELECTED_CONTROLLER(channel).byte_count)) { BX_INFO(("Odd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%04x", - BX_SELECTED_CONTROLLER.byte_count, command, BX_SELECTED_CONTROLLER.byte_count - 1)); - BX_SELECTED_CONTROLLER.byte_count -= 1; + BX_SELECTED_CONTROLLER(channel).byte_count, command, BX_SELECTED_CONTROLLER(channel).byte_count - 1)); + BX_SELECTED_CONTROLLER(channel).byte_count -= 1; } - if (BX_SELECTED_CONTROLLER.byte_count == 0) + if (BX_SELECTED_CONTROLLER(channel).byte_count == 0) BX_PANIC(("ATAPI command with zero byte count")); if (alloc_length < 0) BX_PANIC(("Allocation length < 0")); if (alloc_length == 0) - alloc_length = BX_SELECTED_CONTROLLER.byte_count; + alloc_length = BX_SELECTED_CONTROLLER(channel).byte_count; - BX_SELECTED_CONTROLLER.interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER.interrupt_reason.c_d = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drq = 1; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 1; + BX_SELECTED_CONTROLLER(channel).status.err = 0; // no bytes transfered yet if (lazy) - BX_SELECTED_CONTROLLER.buffer_index = 2048; + BX_SELECTED_CONTROLLER(channel).buffer_index = 2048; else - BX_SELECTED_CONTROLLER.buffer_index = 0; - BX_SELECTED_CONTROLLER.drq_index = 0; + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; + BX_SELECTED_CONTROLLER(channel).drq_index = 0; - if (BX_SELECTED_CONTROLLER.byte_count > req_length) - BX_SELECTED_CONTROLLER.byte_count = req_length; + if (BX_SELECTED_CONTROLLER(channel).byte_count > req_length) + BX_SELECTED_CONTROLLER(channel).byte_count = req_length; - if (BX_SELECTED_CONTROLLER.byte_count > alloc_length) - BX_SELECTED_CONTROLLER.byte_count = alloc_length; + if (BX_SELECTED_CONTROLLER(channel).byte_count > alloc_length) + BX_SELECTED_CONTROLLER(channel).byte_count = alloc_length; - BX_SELECTED_HD.atapi.command = command; - BX_SELECTED_HD.atapi.drq_bytes = BX_SELECTED_CONTROLLER.byte_count; - BX_SELECTED_HD.atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length; + BX_SELECTED_DRIVE(channel).atapi.command = command; + BX_SELECTED_DRIVE(channel).atapi.drq_bytes = BX_SELECTED_CONTROLLER(channel).byte_count; + BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length; // if (lazy) { // // bias drq_bytes and total_bytes_remaining - // BX_SELECTED_HD.atapi.drq_bytes += 2048; - // BX_SELECTED_HD.atapi.total_bytes_remaining += 2048; + // BX_SELECTED_DRIVE(channel).atapi.drq_bytes += 2048; + // BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining += 2048; // } } void -bx_hard_drive_c::atapi_cmd_error(sense_t sense_key, asc_t asc) +bx_hard_drive_c::atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc) { - BX_SELECTED_CONTROLLER.error_register = sense_key << 4; - BX_SELECTED_CONTROLLER.interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER.interrupt_reason.c_d = 1; - BX_SELECTED_CONTROLLER.interrupt_reason.rel = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.write_fault = 0; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 1; - - BX_SELECTED_HD.sense.sense_key = sense_key; - BX_SELECTED_HD.sense.asc = asc; - BX_SELECTED_HD.sense.ascq = 0; + BX_ERROR(("atapi_cmd_error channel=%02x key=%02x asc=%02x", channel, sense_key, asc)); + + BX_SELECTED_CONTROLLER(channel).error_register = sense_key << 4; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 1; + + BX_SELECTED_DRIVE(channel).sense.sense_key = sense_key; + BX_SELECTED_DRIVE(channel).sense.asc = asc; + BX_SELECTED_DRIVE(channel).sense.ascq = 0; } void -bx_hard_drive_c::atapi_cmd_nop() +bx_hard_drive_c::atapi_cmd_nop(Bit8u channel) { - BX_SELECTED_CONTROLLER.interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER.interrupt_reason.c_d = 1; - BX_SELECTED_CONTROLLER.interrupt_reason.rel = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.err = 0; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; + BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.err = 0; } void -bx_hard_drive_c::init_mode_sense_single(const void* src, int size) +bx_hard_drive_c::init_mode_sense_single(Bit8u channel, const void* src, int size) { // Header - BX_SELECTED_CONTROLLER.buffer[0] = (size+6) >> 8; - BX_SELECTED_CONTROLLER.buffer[1] = (size+6) & 0xff; - BX_SELECTED_CONTROLLER.buffer[2] = 0x70; // no media present - BX_SELECTED_CONTROLLER.buffer[3] = 0; // reserved - BX_SELECTED_CONTROLLER.buffer[4] = 0; // reserved - BX_SELECTED_CONTROLLER.buffer[5] = 0; // reserved - BX_SELECTED_CONTROLLER.buffer[6] = 0; // reserved - BX_SELECTED_CONTROLLER.buffer[7] = 0; // reserved + BX_SELECTED_CONTROLLER(channel).buffer[0] = (size+6) >> 8; + BX_SELECTED_CONTROLLER(channel).buffer[1] = (size+6) & 0xff; + BX_SELECTED_CONTROLLER(channel).buffer[2] = 0x70; // no media present + BX_SELECTED_CONTROLLER(channel).buffer[3] = 0; // reserved + BX_SELECTED_CONTROLLER(channel).buffer[4] = 0; // reserved + BX_SELECTED_CONTROLLER(channel).buffer[5] = 0; // reserved + BX_SELECTED_CONTROLLER(channel).buffer[6] = 0; // reserved + BX_SELECTED_CONTROLLER(channel).buffer[7] = 0; // reserved // Data - memcpy(BX_SELECTED_CONTROLLER.buffer + 8, src, size); + memcpy(BX_SELECTED_CONTROLLER(channel).buffer + 8, src, size); } void -bx_hard_drive_c::ready_to_send_atapi() +bx_hard_drive_c::ready_to_send_atapi(Bit8u channel) { - raise_interrupt(); + raise_interrupt(channel); } void -bx_hard_drive_c::raise_interrupt() +bx_hard_drive_c::raise_interrupt(Bit8u channel) { - BX_DEBUG(("raise_interrupt called, disable_irq = %02x", BX_SELECTED_CONTROLLER.control.disable_irq)); - if (!BX_SELECTED_CONTROLLER.control.disable_irq) { BX_DEBUG(("raising interrupt")); } else { BX_DEBUG(("Not raising interrupt")); } - if (!BX_SELECTED_CONTROLLER.control.disable_irq) { - Bit32u irq = 14; // always 1st IDE controller - // for second controller, you would want irq 15 - BX_DEBUG(("Raising interrupt %d {%s}", irq, DEVICE_TYPE_STRING)); + BX_DEBUG(("raise_interrupt called, disable_irq = %02x", BX_SELECTED_CONTROLLER(channel).control.disable_irq)); + if (!BX_SELECTED_CONTROLLER(channel).control.disable_irq) { BX_DEBUG(("raising interrupt")); } else { BX_DEBUG(("Not raising interrupt")); } + if (!BX_SELECTED_CONTROLLER(channel).control.disable_irq) { + Bit32u irq = BX_HD_THIS channels[channel].irq; + BX_DEBUG(("Raising interrupt %d {%s}", irq, BX_SELECTED_TYPE_STRING(channel))); BX_HD_THIS devices->pic->raise_irq(irq); } else { - if (bx_dbg.disk || (CDROM_SELECTED && bx_dbg.cdrom)) - BX_INFO(("Interrupt masked {%s}", DEVICE_TYPE_STRING)); + if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) + BX_INFO(("Interrupt masked {%s}", BX_SELECTED_TYPE_STRING(channel))); } } void -bx_hard_drive_c::command_aborted(unsigned value) +bx_hard_drive_c::command_aborted(Bit8u channel, unsigned value) { - BX_DEBUG(("aborting on command 0x%02x {%s}", value, DEVICE_TYPE_STRING)); - BX_SELECTED_CONTROLLER.current_command = 0; - BX_SELECTED_CONTROLLER.status.busy = 0; - BX_SELECTED_CONTROLLER.status.drive_ready = 1; - BX_SELECTED_CONTROLLER.status.err = 1; - BX_SELECTED_CONTROLLER.error_register = 0x04; // command ABORTED - BX_SELECTED_CONTROLLER.status.drq = 0; - BX_SELECTED_CONTROLLER.status.seek_complete = 0; - BX_SELECTED_CONTROLLER.status.corrected_data = 0; - BX_SELECTED_CONTROLLER.buffer_index = 0; - raise_interrupt(); + BX_DEBUG(("aborting on command 0x%02x {%s}", value, BX_SELECTED_TYPE_STRING(channel))); + BX_SELECTED_CONTROLLER(channel).current_command = 0; + BX_SELECTED_CONTROLLER(channel).status.busy = 0; + BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; + BX_SELECTED_CONTROLLER(channel).status.err = 1; + BX_SELECTED_CONTROLLER(channel).error_register = 0x04; // command ABORTED + BX_SELECTED_CONTROLLER(channel).status.drq = 0; + BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0; + BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; + BX_SELECTED_CONTROLLER(channel).buffer_index = 0; + raise_interrupt(channel); +} + + Bit32u +bx_hard_drive_c::get_device_handle(Bit8u channel, Bit8u device) +{ + BX_DEBUG(("get_device_handle %d %d",channel, device)); + if ((channel < BX_MAX_ATA_CHANNEL) && (device < 2)) { + return ((channel*2) + device); + } + + return BX_MAX_ATA_CHANNEL*2; +} + + Bit32u +bx_hard_drive_c::get_first_cd_handle(void) +{ + for (Bit8u channel=0; channel= BX_MAX_ATA_CHANNEL*2 ) return 0; + + Bit8u channel = handle / 2; + Bit8u device = handle % 2; + return( BX_HD_THIS channels[channel].drives[device].cdrom.ready ); } unsigned -bx_hard_drive_c::set_cd_media_status(unsigned status) +bx_hard_drive_c::set_cd_media_status(Bit32u handle, unsigned status) { + if ( handle >= BX_MAX_ATA_CHANNEL*2 ) return 0; + + Bit8u channel = handle / 2; + Bit8u device = handle % 2; + // if setting to the current value, nothing to do - if (status == BX_HD_THIS s[1].cdrom.ready) + if (status == BX_HD_THIS channels[channel].drives[device].cdrom.ready) return(status); // return 0 if no cdromd is present - if (!bx_options.cdromd.Opresent->get()) + if (!BX_DRIVE_IS_CD(channel,device)) return(0); if (status == 0) { // eject cdrom if not locked by guest OS - if (BX_HD_THIS s[1].cdrom.locked) return(1); + if (BX_HD_THIS channels[channel].drives[device].cdrom.locked) return(1); else { #ifdef LOWLEVEL_CDROM - BX_HD_THIS s[1].cdrom.cd->eject_cdrom(); + BX_HD_THIS channels[channel].drives[device].cdrom.cd->eject_cdrom(); #endif - BX_HD_THIS s[1].cdrom.ready = 0; - bx_options.cdromd.Ostatus->set(BX_EJECTED); + BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; + bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED); } } else { // insert cdrom #ifdef LOWLEVEL_CDROM - if (BX_HD_THIS s[1].cdrom.cd->insert_cdrom(bx_options.cdromd.Opath->getptr())) { + if (BX_HD_THIS channels[channel].drives[device].cdrom.cd->insert_cdrom(bx_options.atadevice[channel][device].Opath->getptr())) { BX_INFO(( "Media present in CD-ROM drive")); - BX_HD_THIS s[1].cdrom.ready = 1; - BX_HD_THIS s[1].cdrom.capacity = BX_HD_THIS s[1].cdrom.cd->capacity(); - bx_options.cdromd.Ostatus->set(BX_INSERTED); - BX_SELECTED_HD.sense.sense_key = SENSE_UNIT_ATTENTION; - BX_SELECTED_HD.sense.asc = 0; - BX_SELECTED_HD.sense.ascq = 0; - raise_interrupt(); + BX_HD_THIS channels[channel].drives[device].cdrom.ready = 1; + BX_HD_THIS channels[channel].drives[device].cdrom.capacity = BX_HD_THIS channels[channel].drives[device].cdrom.cd->capacity(); + bx_options.atadevice[channel][device].Ostatus->set(BX_INSERTED); + BX_SELECTED_DRIVE(channel).sense.sense_key = SENSE_UNIT_ATTENTION; + BX_SELECTED_DRIVE(channel).sense.asc = 0; + BX_SELECTED_DRIVE(channel).sense.ascq = 0; + raise_interrupt(channel); } else { #endif BX_INFO(( "Could not locate CD-ROM, continuing with media not present")); - BX_HD_THIS s[1].cdrom.ready = 0; - bx_options.cdromd.Ostatus->set(BX_EJECTED); + BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; + bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED); #ifdef LOWLEVEL_CDROM } #endif } - return( BX_HD_THIS s[1].cdrom.ready ); + return( BX_HD_THIS channels[channel].drives[device].cdrom.ready ); } Index: iodev/harddrv.h =================================================================== RCS file: /cvsroot/bochs/bochs/iodev/harddrv.h,v retrieving revision 1.13 diff -u -r1.13 harddrv.h --- iodev/harddrv.h 12 Sep 2002 06:49:04 -0000 1.13 +++ iodev/harddrv.h 22 Sep 2002 20:46:16 -0000 @@ -184,7 +184,6 @@ Boolean err; } status; Bit8u error_register; - // Bit8u drive_select; this field was moved :^( Bit8u head_no; union { Bit8u sector_count; @@ -282,12 +281,8 @@ # define BX_HD_THIS this-> #endif -#define BX_SELECTED_HD BX_HD_THIS s[BX_HD_THIS drive_select] -#define CDROM_SELECTED (BX_HD_THIS s[BX_HD_THIS drive_select].device_type == IDE_CDROM) -#define DEVICE_TYPE_STRING ((CDROM_SELECTED) ? "CD-ROM" : "DISK") - typedef enum { - IDE_DISK, IDE_CDROM + IDE_NONE, IDE_DISK, IDE_CDROM } device_type_t; class bx_hard_drive_c : public logfunctions { @@ -298,8 +293,10 @@ BX_HD_SMF void close_harddrive(void); BX_HD_SMF void init(bx_devices_c *d, bx_cmos_c *cmos); BX_HD_SMF void reset(unsigned type); - BX_HD_SMF unsigned get_cd_media_status(void); - BX_HD_SMF unsigned set_cd_media_status(unsigned status); + BX_HD_SMF Bit32u get_device_handle(Bit8u channel, Bit8u device); + BX_HD_SMF Bit32u get_first_cd_handle(void); + BX_HD_SMF unsigned get_cd_media_status(Bit32u handle); + BX_HD_SMF unsigned set_cd_media_status(Bit32u handle, unsigned status); #if !BX_USE_HD_SMF Bit32u read(Bit32u address, unsigned io_len); @@ -311,36 +308,46 @@ private: - BX_HD_SMF Boolean calculate_logical_address(Bit32u *sector); - BX_HD_SMF void increment_address(); - BX_HD_SMF void identify_drive(unsigned drive); - BX_HD_SMF void identify_ATAPI_drive(unsigned drive); - BX_HD_SMF void command_aborted(unsigned command); - - BX_HD_SMF void init_send_atapi_command(Bit8u command, int req_length, int alloc_length, bool lazy = false); - BX_HD_SMF void ready_to_send_atapi(); - BX_HD_SMF void raise_interrupt(); - BX_HD_SMF void atapi_cmd_error(sense_t sense_key, asc_t asc); - BX_HD_SMF void init_mode_sense_single(const void* src, int size); - BX_HD_SMF void atapi_cmd_nop(); - - struct sStruct { - device_image_t* hard_drive; - device_type_t device_type; - // 512 byte buffer for ID drive command - // These words are stored in native word endian format, as - // they are fetched and returned via a return(), so - // there's no need to keep them in x86 endian format. - Bit16u id_drive[256]; - - controller_t controller; - cdrom_t cdrom; - sense_info_t sense; - atapi_t atapi; - - } s[2]; + BX_HD_SMF Boolean calculate_logical_address(Bit8u channel, Bit32u *sector); + BX_HD_SMF void increment_address(Bit8u channel); + BX_HD_SMF void identify_drive(Bit8u channel); + BX_HD_SMF void identify_ATAPI_drive(Bit8u channel); + BX_HD_SMF void command_aborted(Bit8u channel, unsigned command); + + BX_HD_SMF void init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy = false); + BX_HD_SMF void ready_to_send_atapi(Bit8u channel); + BX_HD_SMF void raise_interrupt(Bit8u channel); + BX_HD_SMF void atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc); + BX_HD_SMF void init_mode_sense_single(Bit8u channel, const void* src, int size); + BX_HD_SMF void atapi_cmd_nop(Bit8u channel); + + // FIXME: + // For each ATA channel we should have one controller struct + // and an array of two drive structs + struct channel_t { + struct drive_t { + device_image_t* hard_drive; + device_type_t device_type; + // 512 byte buffer for ID drive command + // These words are stored in native word endian format, as + // they are fetched and returned via a return(), so + // there's no need to keep them in x86 endian format. + Bit16u id_drive[256]; + + controller_t controller; + cdrom_t cdrom; + sense_info_t sense; + atapi_t atapi; + + Bit8u model_no[41]; + } drives[2]; + unsigned drive_select; + + Bit16u ioaddr1; + Bit16u ioaddr2; + Bit8u irq; - unsigned drive_select; + } channels[BX_MAX_ATA_CHANNEL]; bx_devices_c *devices; };