From 0afccdd6a29e00bdbe9cd281bc456873f550f846 Mon Sep 17 00:00:00 2001 From: Bryce Denney Date: Tue, 15 Oct 2002 17:41:40 +0000 Subject: [PATCH] - this is in cvs now --- bochs/patches/patch.4ata-channels | 6576 ----------------------------- 1 file changed, 6576 deletions(-) delete mode 100644 bochs/patches/patch.4ata-channels diff --git a/bochs/patches/patch.4ata-channels b/bochs/patches/patch.4ata-channels deleted file mode 100644 index 73bbd4a9a..000000000 --- a/bochs/patches/patch.4ata-channels +++ /dev/null @@ -1,6576 +0,0 @@ ----------------------------------------------------------------------- -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; - };