DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/hardware/ide.cpp
00001 /*
00002  * IDE ATA/ATAPI and controller emulation for DOSBox-X
00003  * (C) 2012 Jonathan Campbell
00004 
00005  * [insert open source license here]
00006  */
00007 
00008 /* $Id: ide.cpp,v 1.49 2009-04-10 09:53:04 c2woody Exp $ */
00009 
00010 #include <math.h>
00011 #include <assert.h>
00012 #include "dosbox.h"
00013 #include "inout.h"
00014 #include "pic.h"
00015 #include "mem.h"
00016 #include "cpu.h"
00017 #include "ide.h"
00018 #include "mixer.h"
00019 #include "timer.h"
00020 #include "setup.h"
00021 #include "control.h"
00022 #include "callback.h"
00023 #include "bios_disk.h"
00024 #include "../src/dos/cdrom.h"
00025 
00026 #if defined(_MSC_VER)
00027 # pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
00028 # pragma warning(disable:4305) /* truncation from double to float */
00029 #endif
00030 
00031 #ifdef _MSC_VER
00032 # define MIN(a,b) ((a) < (b) ? (a) : (b))
00033 #else
00034 # define MIN(a,b) std::min(a,b)
00035 #endif
00036 
00037 #if defined(_MSC_VER)
00038 # pragma warning(disable:4065) /* switch statement no case labels */
00039 #endif
00040 
00041 static unsigned char init_ide = 0;
00042 
00043 static const unsigned char IDE_default_IRQs[4] = {
00044     14, /* primary */
00045     15, /* secondary */
00046     11, /* tertiary */
00047     10  /* quaternary */
00048 };
00049 
00050 static const unsigned short IDE_default_bases[4] = {
00051     0x1F0,  /* primary */
00052     0x170,  /* secondary */
00053     0x1E8,  /* tertiary */
00054     0x168   /* quaternary */
00055 };
00056 
00057 static const unsigned short IDE_default_alts[4] = {
00058     0x3F6,  /* primary */
00059     0x376,  /* secondary */
00060     0x3EE,  /* tertiary */
00061     0x36E   /* quaternary */
00062 };
00063 
00064 bool fdc_takes_port_3F7();
00065 
00066 static void ide_altio_w(Bitu port,Bitu val,Bitu iolen);
00067 static Bitu ide_altio_r(Bitu port,Bitu iolen);
00068 static void ide_baseio_w(Bitu port,Bitu val,Bitu iolen);
00069 static Bitu ide_baseio_r(Bitu port,Bitu iolen);
00070 bool GetMSCDEXDrive(unsigned char drive_letter,CDROM_Interface **_cdrom);
00071 
00072 enum IDEDeviceType {
00073     IDE_TYPE_NONE,
00074     IDE_TYPE_HDD=1,
00075     IDE_TYPE_CDROM
00076 };
00077 
00078 enum IDEDeviceState {
00079     IDE_DEV_READY=0,
00080     IDE_DEV_SELECT_WAIT,
00081     IDE_DEV_CONFUSED,
00082     IDE_DEV_BUSY,
00083     IDE_DEV_DATA_READ,
00084     IDE_DEV_DATA_WRITE,
00085     IDE_DEV_ATAPI_PACKET_COMMAND,
00086     IDE_DEV_ATAPI_BUSY
00087 };
00088 
00089 enum {
00090     IDE_STATUS_BUSY=0x80,
00091     IDE_STATUS_DRIVE_READY=0x40,
00092     IDE_STATUS_DRIVE_SEEK_COMPLETE=0x10,
00093     IDE_STATUS_DRQ=0x08,
00094     IDE_STATUS_ERROR=0x01
00095 };
00096 
00097 class IDEController;
00098 
00099 #if 0//unused
00100 static inline bool drivehead_is_lba48(uint8_t val) {
00101     return (val&0xE0) == 0x40;
00102 }
00103 #endif
00104 
00105 static inline bool drivehead_is_lba(uint8_t val) {
00106     return (val&0xE0) == 0xE0;
00107 }
00108 
00109 #if 0//unused
00110 static inline bool drivehead_is_chs(uint8_t val) {
00111     return (val&0xE0) == 0xA0;
00112 }
00113 #endif
00114 
00115 class IDEDevice {
00116 public:
00117     IDEController *controller;
00118     uint16_t feature,count,lba[3];  /* feature = BASE+1  count = BASE+2   lba[3] = BASE+3,+4,+5 */
00119     uint8_t command,drivehead,status; /* command/status = BASE+7  drivehead = BASE+6 */
00120     enum IDEDeviceType type;
00121     bool faked_command; /* if set, DOSBox is sending commands to itself */
00122     bool allow_writing;
00123     bool motor_on;
00124     bool asleep;
00125     IDEDeviceState state;
00126     /* feature: 0x1F1 (Word 00h in ATA specs)
00127          count: 0x1F2 (Word 01h in ATA specs)
00128         lba[3]: 0x1F3 (Word 02h) 0x1F4 (Word 03h) and 0x1F5 (Word 04h)
00129      drivehead: 0x1F6 (copy of last value written)
00130        command: 0x1F7 (Word 05h)
00131         status: 0x1F7 (value read back to IDE controller, including busy and drive ready bits as well as error status)
00132 
00133     In C/H/S modes lba[3] becomes lba[0]=sector lba[1]=cylinder-low lba[2]=cylinder-high and
00134     the code must read the 4-bit head number from drivehead[bits 3:0].
00135 
00136     "drivehead" in this struct is always maintained as a device copy of the controller's
00137     drivehead value. it is only updated on write, and not returned on read.
00138 
00139     "allow_writing" if set allows the DOS program/OS to write the registers. It is
00140     clear during command execution, obviously, so the state of the device is not confused
00141     while executing the command.
00142 
00143     Registers are 16-bit where applicable so future revisions of this code
00144     can support LBA48 commands */
00145 public:
00146     /* tweakable parameters */
00147     double ide_select_delay;    /* time between writing 0x1F6 and drive readiness */
00148     double ide_spinup_delay;    /* time it takes to spin the hard disk motor up to speed */
00149     double ide_spindown_delay;  /* time it takes for hard disk motor to spin down */
00150     double ide_identify_command_delay;
00151 public:
00152     IDEDevice(IDEController *c);
00153     virtual ~IDEDevice();
00154     virtual void host_reset_begin();    /* IDE controller -> upon setting bit 2 of alt (0x3F6) */
00155     virtual void host_reset_complete(); /* IDE controller -> upon setting bit 2 of alt (0x3F6) */
00156     virtual void select(uint8_t ndh,bool switched_to);
00157     virtual void deselect();
00158     virtual void abort_error();
00159     virtual void abort_normal();
00160     virtual void interface_wakeup();
00161     virtual void writecommand(uint8_t cmd);
00162     virtual Bitu data_read(Bitu iolen); /* read from 1F0h data port from IDE device */
00163     virtual void data_write(Bitu v,Bitu iolen);/* write to 1F0h data port to IDE device */
00164     virtual bool command_interruption_ok(uint8_t cmd);
00165     virtual void abort_silent();
00166 };
00167 
00168 class IDEATADevice:public IDEDevice {
00169 public:
00170     IDEATADevice(IDEController *c,unsigned char bios_disk_index);
00171     virtual ~IDEATADevice();
00172     virtual void writecommand(uint8_t cmd);
00173 public:
00174     std::string id_serial;
00175     std::string id_firmware_rev;
00176     std::string id_model;
00177     unsigned char bios_disk_index;
00178     imageDisk *getBIOSdisk();
00179     void update_from_biosdisk();
00180     virtual Bitu data_read(Bitu iolen); /* read from 1F0h data port from IDE device */
00181     virtual void data_write(Bitu v,Bitu iolen);/* write to 1F0h data port to IDE device */
00182     virtual void generate_identify_device();
00183     virtual void prepare_read(Bitu offset,Bitu size);
00184     virtual void prepare_write(Bitu offset,Bitu size);
00185     virtual void io_completion();
00186     virtual bool increment_current_address(Bitu count=1);
00187 public:
00188     Bitu multiple_sector_max,multiple_sector_count;
00189     Bitu heads,sects,cyls,headshr,progress_count;
00190     Bitu phys_heads,phys_sects,phys_cyls;
00191     unsigned char sector[512*128];
00192     Bitu sector_i,sector_total;
00193 };
00194 
00195 enum {
00196     LOAD_NO_DISC=0,
00197     LOAD_INSERT_CD,         /* user is "inserting" the CD */
00198     LOAD_IDLE,          /* disc is stationary, not spinning */
00199     LOAD_DISC_LOADING,      /* disc is "spinning up" */
00200     LOAD_DISC_READIED,      /* disc just "became ready" */
00201     LOAD_READY
00202 };
00203 
00204 class IDEATAPICDROMDevice:public IDEDevice {
00205 public:
00206     IDEATAPICDROMDevice(IDEController *c,unsigned char drive_index);
00207     virtual ~IDEATAPICDROMDevice();
00208     virtual void writecommand(uint8_t cmd);
00209 public:
00210     std::string id_serial;
00211     std::string id_firmware_rev;
00212     std::string id_model;
00213     unsigned char drive_index;
00214     CDROM_Interface *getMSCDEXDrive();
00215     void update_from_cdrom();
00216     virtual Bitu data_read(Bitu iolen); /* read from 1F0h data port from IDE device */
00217     virtual void data_write(Bitu v,Bitu iolen);/* write to 1F0h data port to IDE device */
00218     virtual void generate_identify_device();
00219     virtual void generate_mmc_inquiry();
00220     virtual void prepare_read(Bitu offset,Bitu size);
00221     virtual void prepare_write(Bitu offset,Bitu size);
00222     virtual void set_sense(unsigned char SK,unsigned char ASC=0,unsigned char ASCQ=0,unsigned int len=0);
00223     virtual bool common_spinup_response(bool trigger,bool wait);
00224     virtual void on_mode_select_io_complete();
00225     virtual void atapi_io_completion();
00226     virtual void io_completion();
00227     virtual void atapi_cmd_completion();
00228     virtual void on_atapi_busy_time();
00229     virtual void read_subchannel();
00230     virtual void play_audio_msf();
00231     virtual void pause_resume();
00232     virtual void play_audio10();
00233     virtual void mode_sense();
00234     virtual void read_toc();
00235 public:
00236     bool atapi_to_host;         /* if set, PACKET data transfer is to be read by host */
00237     double spinup_time;
00238     double spindown_timeout;
00239     double cd_insertion_time;
00240     Bitu host_maximum_byte_count;       /* host maximum byte count during PACKET transfer */
00241     std::string id_mmc_vendor_id;
00242     std::string id_mmc_product_id;
00243     std::string id_mmc_product_rev;
00244     Bitu LBA,TransferLength;
00245     int loading_mode;
00246     bool has_changed;
00247 public:
00248     unsigned char sense[256];
00249     Bitu sense_length;
00250     unsigned char atapi_cmd[12];
00251     unsigned char atapi_cmd_i,atapi_cmd_total;
00252     unsigned char sector[512*128];
00253     Bitu sector_i,sector_total;
00254 };
00255 
00256 class IDEController:public Module_base{
00257 public:
00258     int IRQ;
00259     bool int13fakeio;       /* on certain INT 13h calls, force IDE state as if BIOS had carried them out */
00260     bool int13fakev86io;        /* on certain INT 13h calls in virtual 8086 mode, trigger fake CPU I/O traps */
00261     bool enable_pio32;      /* enable 32-bit PIO (if disabled, attempts at 32-bit PIO are handled as if two 16-bit I/O) */
00262     bool ignore_pio32;      /* if 32-bit PIO enabled, but ignored, writes do nothing, reads return 0xFFFFFFFF */
00263     bool register_pnp;
00264     unsigned short alt_io;
00265     unsigned short base_io;
00266     unsigned char interface_index;
00267     IO_ReadHandleObject ReadHandler[8],ReadHandlerAlt[2];
00268     IO_WriteHandleObject WriteHandler[8],WriteHandlerAlt[2];
00269 public:
00270     IDEDevice* device[2];       /* IDE devices (master, slave) */
00271     Bitu select,status,drivehead;   /* which is selected, status register (0x1F7) but ONLY if no device exists at selection, drive/head register (0x1F6) */
00272     bool interrupt_enable;      /* bit 1 of alt (0x3F6) */
00273     bool host_reset;        /* bit 2 of alt */
00274     bool irq_pending;
00275     /* defaults for CD-ROM emulation */
00276     double spinup_time;
00277     double spindown_timeout;
00278     double cd_insertion_time;
00279 public:
00280     IDEController(Section* configuration,unsigned char index);
00281     void register_isapnp();
00282     void install_io_port();
00283     void raise_irq();
00284     void lower_irq();
00285     ~IDEController();
00286 };
00287 
00288 static IDEController* idecontroller[MAX_IDE_CONTROLLERS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
00289 
00290 static void IDE_DelayedCommand(Bitu idx/*which IDE controller*/);
00291 static IDEController* GetIDEController(Bitu idx);
00292 
00293 static void IDE_ATAPI_SpinDown(Bitu idx/*which IDE controller*/) {
00294     IDEController *ctrl = GetIDEController(idx);
00295     if (ctrl == NULL) return;
00296 
00297     for (unsigned int i=0;i < 2;i++) {
00298         IDEDevice *dev = ctrl->device[i];
00299         if (dev == NULL) continue;
00300 
00301         if (dev->type == IDE_TYPE_HDD) {
00302         }
00303         else if (dev->type == IDE_TYPE_CDROM) {
00304             IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
00305 
00306             if (atapi->loading_mode == LOAD_DISC_READIED || atapi->loading_mode == LOAD_READY) {
00307                 atapi->loading_mode = LOAD_IDLE;
00308                 LOG_MSG("ATAPI CD-ROM: spinning down\n");
00309             }
00310         }
00311         else {
00312             LOG_MSG("Unknown ATAPI spinup callback\n");
00313         }
00314     }
00315 }
00316 
00317 static void IDE_ATAPI_SpinUpComplete(Bitu idx/*which IDE controller*/);
00318 
00319 static void IDE_ATAPI_CDInsertion(Bitu idx/*which IDE controller*/) {
00320     IDEController *ctrl = GetIDEController(idx);
00321     if (ctrl == NULL) return;
00322 
00323     for (unsigned int i=0;i < 2;i++) {
00324         IDEDevice *dev = ctrl->device[i];
00325         if (dev == NULL) continue;
00326 
00327         if (dev->type == IDE_TYPE_HDD) {
00328         }
00329         else if (dev->type == IDE_TYPE_CDROM) {
00330             IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
00331 
00332             if (atapi->loading_mode == LOAD_INSERT_CD) {
00333                 atapi->loading_mode = LOAD_DISC_LOADING;
00334                 LOG_MSG("ATAPI CD-ROM: insert CD to loading\n");
00335                 PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,idx);
00336                 PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,idx);
00337                 PIC_AddEvent(IDE_ATAPI_SpinUpComplete,atapi->spinup_time/*ms*/,idx);
00338             }
00339         }
00340         else {
00341             LOG_MSG("Unknown ATAPI spinup callback\n");
00342         }
00343     }
00344 }
00345 
00346 static void IDE_ATAPI_SpinUpComplete(Bitu idx/*which IDE controller*/) {
00347     IDEController *ctrl = GetIDEController(idx);
00348     if (ctrl == NULL) return;
00349 
00350     for (unsigned int i=0;i < 2;i++) {
00351         IDEDevice *dev = ctrl->device[i];
00352         if (dev == NULL) continue;
00353 
00354         if (dev->type == IDE_TYPE_HDD) {
00355         }
00356         else if (dev->type == IDE_TYPE_CDROM) {
00357             IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
00358 
00359             if (atapi->loading_mode == LOAD_DISC_LOADING) {
00360                 atapi->loading_mode = LOAD_DISC_READIED;
00361                 LOG_MSG("ATAPI CD-ROM: spinup complete\n");
00362                 PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,idx);
00363                 PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,idx);
00364                 PIC_AddEvent(IDE_ATAPI_SpinDown,atapi->spindown_timeout/*ms*/,idx);
00365             }
00366         }
00367         else {
00368             LOG_MSG("Unknown ATAPI spinup callback\n");
00369         }
00370     }
00371 }
00372 
00373 /* returns "true" if command should proceed as normal, "false" if sense data was set and command should not proceed.
00374  * this function helps to enforce virtual "spin up" and "ready" delays. */
00375 bool IDEATAPICDROMDevice::common_spinup_response(bool trigger,bool wait) {
00376     if (loading_mode == LOAD_IDLE) {
00377         if (trigger) {
00378             LOG_MSG("ATAPI CD-ROM: triggered to spin up from idle\n");
00379             loading_mode = LOAD_DISC_LOADING;
00380             PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,controller->interface_index);
00381             PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,controller->interface_index);
00382             PIC_AddEvent(IDE_ATAPI_SpinUpComplete,spinup_time/*ms*/,controller->interface_index);
00383         }
00384     }
00385     else if (loading_mode == LOAD_READY) {
00386         if (trigger) {
00387             PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,controller->interface_index);
00388             PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,controller->interface_index);
00389             PIC_AddEvent(IDE_ATAPI_SpinDown,spindown_timeout/*ms*/,controller->interface_index);
00390         }
00391     }
00392 
00393     switch (loading_mode) {
00394         case LOAD_NO_DISC:
00395         case LOAD_INSERT_CD:
00396             set_sense(/*SK=*/0x02,/*ASC=*/0x3A); /* Medium Not Present */
00397             return false;
00398         case LOAD_DISC_LOADING:
00399             if (has_changed && !wait/*if command will block until LOADING complete*/) {
00400                 set_sense(/*SK=*/0x02,/*ASC=*/0x04,/*ASCQ=*/0x01); /* Medium is becoming available */
00401                 return false;
00402             }
00403             break;
00404         case LOAD_DISC_READIED:
00405             loading_mode = LOAD_READY;
00406             if (has_changed) {
00407                 if (trigger) has_changed = false;
00408                 set_sense(/*SK=*/0x02,/*ASC=*/0x28,/*ASCQ=*/0x00); /* Medium is ready (has changed) */
00409                 return false;
00410             }
00411             break;
00412         case LOAD_IDLE:
00413         case LOAD_READY:
00414             break;
00415         default:
00416             abort();
00417     };
00418 
00419     return true;
00420 }
00421 
00422 void IDEATAPICDROMDevice::read_subchannel() {
00423 //  unsigned char Format = atapi_cmd[2] & 0xF;
00424 //  unsigned char Track = atapi_cmd[6];
00425     unsigned char paramList = atapi_cmd[3];
00426     unsigned char attr,track,index;
00427     bool SUBQ = !!(atapi_cmd[2] & 0x40);
00428     bool TIME = !!(atapi_cmd[1] & 2);
00429     unsigned char *write;
00430     unsigned char astat;
00431     bool playing,pause;
00432     TMSF rel,abs;
00433 
00434     CDROM_Interface *cdrom = getMSCDEXDrive();
00435     if (cdrom == NULL) {
00436         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00437         prepare_read(0,8);
00438         return;
00439     }
00440 
00441     if (paramList == 0 || paramList > 3) {
00442         LOG_MSG("ATAPI READ SUBCHANNEL unknown param list\n");
00443         prepare_read(0,8);
00444         return;
00445     }
00446     else if (paramList == 2) {
00447         LOG_MSG("ATAPI READ SUBCHANNEL Media Catalog Number not supported\n");
00448         prepare_read(0,8);
00449         return;
00450     }
00451     else if (paramList == 3) {
00452         LOG_MSG("ATAPI READ SUBCHANNEL ISRC not supported\n");
00453         prepare_read(0,8);
00454         return;
00455     }
00456 
00457     /* get current subchannel position */
00458     if (!cdrom->GetAudioSub(attr,track,index,rel,abs)) {
00459         LOG_MSG("ATAPI READ SUBCHANNEL unable to read current pos\n");
00460         prepare_read(0,8);
00461         return;
00462     }
00463 
00464     if (!cdrom->GetAudioStatus(playing,pause))
00465         playing = pause = false;
00466 
00467     if (playing)
00468         astat = pause ? 0x12 : 0x11;
00469     else
00470         astat = 0x13;
00471 
00472     memset(sector,0,8);
00473     write = sector;
00474     *write++ = 0x00;
00475     *write++ = astat;/* AUDIO STATUS */
00476     *write++ = 0x00;/* SUBCHANNEL DATA LENGTH */
00477     *write++ = 0x00;
00478 
00479     if (SUBQ) {
00480         *write++ = 0x01;    /* subchannel data format code */
00481         *write++ = (attr >> 4) | 0x10;  /* ADR/CONTROL */
00482         *write++ = track;
00483         *write++ = index;
00484         if (TIME) {
00485             *write++ = 0x00;
00486             *write++ = abs.min;
00487             *write++ = abs.sec;
00488             *write++ = abs.fr;
00489             *write++ = 0x00;
00490             *write++ = rel.min;
00491             *write++ = rel.sec;
00492             *write++ = rel.fr;
00493         }
00494         else {
00495             uint32_t sec;
00496 
00497             sec = (abs.min*60u*75u)+(abs.sec*75u)+abs.fr - 150u;
00498             *write++ = (unsigned char)(sec >> 24u);
00499             *write++ = (unsigned char)(sec >> 16u);
00500             *write++ = (unsigned char)(sec >> 8u);
00501             *write++ = (unsigned char)(sec >> 0u);
00502 
00503             sec = (rel.min*60u*75u)+(rel.sec*75u)+rel.fr - 150u;
00504             *write++ = (unsigned char)(sec >> 24u);
00505             *write++ = (unsigned char)(sec >> 16u);
00506             *write++ = (unsigned char)(sec >> 8u);
00507             *write++ = (unsigned char)(sec >> 0u);
00508         }
00509     }
00510 
00511     {
00512         unsigned int x = (unsigned int)(write-sector) - 4;
00513         sector[2] = x >> 8;
00514         sector[3] = x;
00515     }
00516 
00517     prepare_read(0,MIN((unsigned int)(write-sector),(unsigned int)host_maximum_byte_count));
00518 #if 0
00519     LOG_MSG("SUBCH ");
00520     for (size_t i=0;i < sector_total;i++) LOG_MSG("%02x ",sector[i]);
00521     LOG_MSG("\n");
00522 #endif
00523 }
00524 
00525 void IDEATAPICDROMDevice::mode_sense() {
00526     unsigned char PAGE = atapi_cmd[2] & 0x3F;
00527 //  unsigned char SUBPAGE = atapi_cmd[3];
00528     unsigned char *write;
00529     unsigned int x;
00530 
00531     write = sector;
00532 
00533     /* some header. not well documented */
00534     *write++ = 0x00;    /* ?? */
00535     *write++ = 0x00;    /* length */
00536     *write++ = 0x00;    /* ?? */
00537     *write++ = 0x00;
00538     *write++ = 0x00;
00539     *write++ = 0x00;
00540     *write++ = 0x00;
00541     *write++ = 0x00;
00542 
00543     *write++ = PAGE;    /* page code */
00544     *write++ = 0x00;    /* page length (fill in later) */
00545     switch (PAGE) {
00546         case 0x01: /* Read error recovery */
00547             *write++ = 0x00;    /* maximum error correction */
00548             *write++ = 3;       /* read retry count */
00549             *write++ = 0x00;
00550             *write++ = 0x00;
00551             *write++ = 0x00;
00552             *write++ = 0x00;
00553             break;
00554         case 0x0E: /* CD-ROM audio control */
00555             *write++ = 0x04;    /* ?? */
00556             *write++ = 0x00;    /* reserved @+3 */
00557             *write++ = 0x00;    /* reserved @+4 */
00558             *write++ = 0x00;    /* reserved @+5 */
00559             *write++ = 0x00;
00560             *write++ = 75;      /* logical blocks per second */
00561 
00562             *write++ = 0x01;    /* output port 0 selection */
00563             *write++ = 0xD8;    /* output port 0 volume (?) */
00564             *write++ = 0x02;    /* output port 1 selection */
00565             *write++ = 0xD8;    /* output port 1 volume (?) */
00566             *write++ = 0x00;    /* output port 2 selection */
00567             *write++ = 0x00;    /* output port 2 volume (?) */
00568             *write++ = 0x00;    /* output port 3 selection */
00569             *write++ = 0x00;    /* output port 3 volume (?) */
00570             break;
00571         case 0x2A: /* CD-ROM mechanical status */
00572             *write++ = 0x00;    /* reserved @+2 ?? */
00573             *write++ = 0x00;    /* reserved @+3 ?? */
00574             *write++ = 0xF1;    /* multisession=0 mode2form2=1 mode2form=1 audioplay=1 */
00575             *write++ = 0xFF;    /* ISRC=1 UPC=1 C2=1 RWDeinterleave=1 RWSupported=1 CDDAAccurate=1 CDDASupported=1 */
00576             *write++ = 0x29;    /* loading mechanism type=tray  eject=1  prevent jumper=0  lockstate=0  lock=1 */
00577             *write++ = 0x03;    /* separate channel mute=1 separate channel volume levels=1 */
00578 
00579             x = 176 * 8;        /* maximum speed supported: 8X */
00580             *write++ = x>>8;
00581             *write++ = x;
00582 
00583             x = 256;        /* (?) */
00584             *write++ = x>>8;
00585             *write++ = x;
00586 
00587             x = 6 * 256;        /* (?) */
00588             *write++ = x>>8;
00589             *write++ = x;
00590 
00591             x = 176 * 8;        /* current speed supported: 8X */
00592             *write++ = x>>8;
00593             *write++ = x;
00594             break;
00595         default:
00596             memset(write,0,6); write += 6;
00597             LOG_MSG("WARNING: MODE SENSE on page 0x%02x not supported\n",PAGE);
00598             break;
00599     };
00600 
00601     /* fill in page length */
00602     sector[1] = (unsigned int)(write-sector) - 2;
00603     sector[8+1] = (unsigned int)(write-sector) - 2 - 8;
00604 
00605     prepare_read(0,MIN((unsigned int)(write-sector),(unsigned int)host_maximum_byte_count));
00606 #if 0
00607     printf("SENSE ");
00608     for (size_t i=0;i < sector_total;i++) printf("%02x ",sector[i]);
00609     printf("\n");
00610 #endif
00611 }
00612 
00613 void IDEATAPICDROMDevice::pause_resume() {
00614     bool Resume = !!(atapi_cmd[8] & 1);
00615 
00616     CDROM_Interface *cdrom = getMSCDEXDrive();
00617     if (cdrom == NULL) {
00618         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00619         sector_total = 0;
00620         return;
00621     }
00622 
00623     cdrom->PauseAudio(Resume);
00624 }
00625 
00626 void IDEATAPICDROMDevice::play_audio_msf() {
00627     uint32_t start_lba,end_lba;
00628 
00629     CDROM_Interface *cdrom = getMSCDEXDrive();
00630     if (cdrom == NULL) {
00631         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00632         sector_total = 0;
00633         return;
00634     }
00635 
00636     if (atapi_cmd[3] == 0xFF && atapi_cmd[4] == 0xFF && atapi_cmd[5] == 0xFF)
00637         start_lba = 0xFFFFFFFF;
00638     else {
00639         start_lba = (atapi_cmd[3] * 60u * 75u) +
00640             (atapi_cmd[4] * 75u) +
00641             atapi_cmd[5];
00642 
00643         if (start_lba >= 150u) start_lba -= 150u; /* LBA sector 0 == M:S:F sector 0:2:0 */
00644         else end_lba = 0;
00645     }
00646 
00647     if (atapi_cmd[6] == 0xFF && atapi_cmd[7] == 0xFF && atapi_cmd[8] == 0xFF)
00648         end_lba = 0xFFFFFFFF;
00649     else {
00650         end_lba = (atapi_cmd[6] * 60u * 75u) +
00651             (atapi_cmd[7] * 75u) +
00652             atapi_cmd[8];
00653 
00654         if (end_lba >= 150u) end_lba -= 150u; /* LBA sector 0 == M:S:F sector 0:2:0 */
00655         else end_lba = 0;
00656     }
00657 
00658     if (start_lba == end_lba) {
00659         /* The play length field specifies the number of contiguous logical blocks that shall
00660          * be played. A play length of zero indicates that no audio operation shall occur.
00661          * This condition is not an error. */
00662         /* TODO: How do we interpret that? Does that mean audio playback stops? Or does it
00663          * mean we do nothing to the state of audio playback? */
00664         sector_total = 0;
00665         return;
00666     }
00667 
00668     /* LBA 0xFFFFFFFF means start playing wherever the optics of the CD sit */
00669     if (start_lba != 0xFFFFFFFF)
00670         cdrom->PlayAudioSector(start_lba,end_lba - start_lba);
00671     else
00672         cdrom->PauseAudio(true);
00673 
00674     sector_total = 0;
00675 }
00676 
00677 void IDEATAPICDROMDevice::play_audio10() {
00678     uint16_t play_length;
00679     uint32_t start_lba;
00680 
00681     CDROM_Interface *cdrom = getMSCDEXDrive();
00682     if (cdrom == NULL) {
00683         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00684         sector_total = 0;
00685         return;
00686     }
00687 
00688     start_lba = ((uint32_t)atapi_cmd[2] << 24) +
00689         ((uint32_t)atapi_cmd[3] << 16) +
00690         ((uint32_t)atapi_cmd[4] << 8) +
00691         ((uint32_t)atapi_cmd[5] << 0);
00692 
00693     play_length = ((uint16_t)atapi_cmd[7] << 8) +
00694         ((uint16_t)atapi_cmd[8] << 0);
00695 
00696     if (play_length == 0) {
00697         /* The play length field specifies the number of contiguous logical blocks that shall
00698          * be played. A play length of zero indicates that no audio operation shall occur.
00699          * This condition is not an error. */
00700         /* TODO: How do we interpret that? Does that mean audio playback stops? Or does it
00701          * mean we do nothing to the state of audio playback? */
00702         sector_total = 0;
00703         return;
00704     }
00705 
00706     /* LBA 0xFFFFFFFF means start playing wherever the optics of the CD sit */
00707     if (start_lba != 0xFFFFFFFF)
00708         cdrom->PlayAudioSector(start_lba,play_length);
00709     else
00710         cdrom->PauseAudio(true);
00711 
00712     sector_total = 0;
00713 }
00714 
00715 #if 0 /* TODO move to library */
00716 static unsigned char dec2bcd(unsigned char c) {
00717     return ((c / 10) << 4) + (c % 10);
00718 }
00719 #endif
00720 
00721 void IDEATAPICDROMDevice::read_toc() {
00722     /* NTS: The SCSI MMC standards say we're allowed to indicate the return data
00723      *      is longer than it's allocation length. But here's the thing: some MS-DOS
00724      *      CD-ROM drivers will ask for the TOC but only provide enough room for one
00725      *      entry (OAKCDROM.SYS) and if we signal more data than it's buffer, it will
00726      *      reject our response and render the CD-ROM drive inaccessible. So to make
00727      *      this emulation work, we have to cut our response short to the driver's
00728      *      allocation length */
00729     unsigned int AllocationLength = ((unsigned int)atapi_cmd[7] << 8) + atapi_cmd[8];
00730     unsigned char Format = atapi_cmd[2] & 0xF;
00731     unsigned char Track = atapi_cmd[6];
00732     bool TIME = !!(atapi_cmd[1] & 2);
00733     unsigned char *write;
00734     int first,last,track;
00735     TMSF leadOut;
00736 
00737     CDROM_Interface *cdrom = getMSCDEXDrive();
00738     if (cdrom == NULL) {
00739         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00740         prepare_read(0,8);
00741         return;
00742     }
00743 
00744     memset(sector,0,8);
00745 
00746     if (!cdrom->GetAudioTracks(first,last,leadOut)) {
00747         LOG_MSG("WARNING: ATAPI READ TOC failed to get track info\n");
00748         prepare_read(0,8);
00749         return;
00750     }
00751 
00752     /* start 2 bytes out. we'll fill in the data length later */
00753     write = sector + 2;
00754 
00755     if (Format == 1) { /* Read multisession info */
00756         unsigned char attr;
00757         TMSF start;
00758 
00759         *write++ = (unsigned char)1;        /* @+2 first complete session */
00760         *write++ = (unsigned char)1;        /* @+3 last complete session */
00761 
00762         if (!cdrom->GetAudioTrackInfo(first,start,attr)) {
00763             LOG_MSG("WARNING: ATAPI READ TOC unable to read track %u information\n",first);
00764             attr = 0x41; /* ADR=1 CONTROL=4 */
00765             start.min = 0;
00766             start.sec = 0;
00767             start.fr = 0;
00768         }
00769 
00770         LOG_MSG("Track %u attr=0x%02x\n",first,attr);
00771 
00772         *write++ = 0x00;        /* entry+0 RESERVED */
00773         *write++ = (attr >> 4) | 0x10;  /* entry+1 ADR=1 CONTROL=4 (DATA) */
00774         *write++ = (unsigned char)first;/* entry+2 TRACK */
00775         *write++ = 0x00;        /* entry+3 RESERVED */
00776 
00777         /* then, start address of first track in session */
00778         if (TIME) {
00779             *write++ = 0x00;
00780             *write++ = start.min;
00781             *write++ = start.sec;
00782             *write++ = start.fr;
00783         }
00784         else {
00785             uint32_t sec = (start.min*60u*75u)+(start.sec*75u)+start.fr - 150u;
00786             *write++ = (unsigned char)(sec >> 24u);
00787             *write++ = (unsigned char)(sec >> 16u);
00788             *write++ = (unsigned char)(sec >> 8u);
00789             *write++ = (unsigned char)(sec >> 0u);
00790         }
00791     }
00792     else if (Format == 0) { /* Read table of contents */
00793         *write++ = (unsigned char)first;    /* @+2 */
00794         *write++ = (unsigned char)last;     /* @+3 */
00795 
00796         for (track=first;track <= last;track++) {
00797             unsigned char attr;
00798             TMSF start;
00799 
00800             if (!cdrom->GetAudioTrackInfo(track,start,attr)) {
00801                 LOG_MSG("WARNING: ATAPI READ TOC unable to read track %u information\n",track);
00802                 attr = 0x41; /* ADR=1 CONTROL=4 */
00803                 start.min = 0;
00804                 start.sec = 0;
00805                 start.fr = 0;
00806             }
00807 
00808             if (track < Track)
00809                 continue;
00810             if ((write+8) > (sector+AllocationLength))
00811                 break;
00812 
00813             LOG_MSG("Track %u attr=0x%02x\n",track,attr);
00814 
00815             *write++ = 0x00;        /* entry+0 RESERVED */
00816             *write++ = (attr >> 4) | 0x10; /* entry+1 ADR=1 CONTROL=4 (DATA) */
00817             *write++ = (unsigned char)track;/* entry+2 TRACK */
00818             *write++ = 0x00;        /* entry+3 RESERVED */
00819             if (TIME) {
00820                 *write++ = 0x00;
00821                 *write++ = start.min;
00822                 *write++ = start.sec;
00823                 *write++ = start.fr;
00824             }
00825             else {
00826                 uint32_t sec = (start.min*60u*75u)+(start.sec*75u)+start.fr - 150u;
00827                 *write++ = (unsigned char)(sec >> 24u);
00828                 *write++ = (unsigned char)(sec >> 16u);
00829                 *write++ = (unsigned char)(sec >> 8u);
00830                 *write++ = (unsigned char)(sec >> 0u);
00831             }
00832         }
00833 
00834         if ((write+8) <= (sector+AllocationLength)) {
00835             *write++ = 0x00;
00836             *write++ = 0x14;
00837             *write++ = 0xAA;/*TRACK*/
00838             *write++ = 0x00;
00839             if (TIME) {
00840                 *write++ = 0x00;
00841                 *write++ = leadOut.min;
00842                 *write++ = leadOut.sec;
00843                 *write++ = leadOut.fr;
00844             }
00845             else {
00846                 uint32_t sec = (leadOut.min*60u*75u)+(leadOut.sec*75u)+leadOut.fr - 150u;
00847                 *write++ = (unsigned char)(sec >> 24u);
00848                 *write++ = (unsigned char)(sec >> 16u);
00849                 *write++ = (unsigned char)(sec >> 8u);
00850                 *write++ = (unsigned char)(sec >> 0u);
00851             }
00852         }
00853     }
00854     else {
00855         LOG_MSG("WARNING: ATAPI READ TOC Format=%u not supported\n",Format);
00856         prepare_read(0,8);
00857         return;
00858     }
00859 
00860     /* update the TOC data length field */
00861     {
00862         unsigned int x = (unsigned int)(write-sector) - 2;
00863         sector[0] = x >> 8;
00864         sector[1] = x & 0xFF;
00865     }
00866 
00867     prepare_read(0,MIN(MIN((unsigned int)(write-sector),(unsigned int)host_maximum_byte_count),AllocationLength));
00868 }
00869 
00870 /* when the ATAPI command has been accepted, and the timeout has passed */
00871 void IDEATAPICDROMDevice::on_atapi_busy_time() {
00872     /* if the drive is spinning up, then the command waits */
00873     if (loading_mode == LOAD_DISC_LOADING) {
00874         switch (atapi_cmd[0]) {
00875             case 0x00: /* TEST UNIT READY */
00876             case 0x03: /* REQUEST SENSE */
00877                 allow_writing = true;
00878                 break; /* do not delay */
00879             default:
00880                 PIC_AddEvent(IDE_DelayedCommand,100/*ms*/,controller->interface_index);
00881                 return;
00882         }
00883     }
00884     else if (loading_mode == LOAD_DISC_READIED) {
00885         switch (atapi_cmd[0]) {
00886             case 0x00: /* TEST UNIT READY */
00887             case 0x03: /* REQUEST SENSE */
00888                 allow_writing = true;
00889                 break; /* do not delay */
00890             default:
00891                 if (!common_spinup_response(/*spin up*/true,/*wait*/false)) {
00892                     count = 0x03;
00893                     state = IDE_DEV_READY;
00894                     feature = ((sense[2]&0xF) << 4) | (sense[2]&0xF ? 0x04/*abort*/ : 0x00);
00895                     status = IDE_STATUS_DRIVE_READY|(sense[2]&0xF ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
00896                     controller->raise_irq();
00897                     allow_writing = true;
00898                     return;
00899                 }
00900                 break;
00901         }
00902     }
00903 
00904     switch (atapi_cmd[0]) {
00905         case 0x03: /* REQUEST SENSE */
00906             prepare_read(0,MIN((unsigned int)sense_length,(unsigned int)host_maximum_byte_count));
00907             memcpy(sector,sense,sense_length);
00908 
00909             feature = 0x00;
00910             state = IDE_DEV_DATA_READ;
00911             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
00912 
00913             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
00914             lba[2] = sector_total >> 8;
00915             lba[1] = sector_total;
00916 
00917             controller->raise_irq();
00918             allow_writing = true;
00919             break;
00920         case 0x1E: /* PREVENT ALLOW MEDIUM REMOVAL */
00921             count = 0x03;
00922             feature = 0x00;
00923             sector_total = 0x00;
00924             state = IDE_DEV_DATA_READ;
00925             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
00926 
00927             /* Don't care. Do nothing. */
00928 
00929             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
00930             lba[2] = sector_total >> 8;
00931             lba[1] = sector_total;
00932 
00933             controller->raise_irq();
00934             allow_writing = true;
00935             break;
00936         case 0x25: /* READ CAPACITY */ {
00937             const unsigned int secsize = 2048;
00938             int first,last;
00939             TMSF leadOut;
00940 
00941             CDROM_Interface *cdrom = getMSCDEXDrive();
00942 
00943             if (!cdrom->GetAudioTracks(first,last,leadOut))
00944                 LOG_MSG("WARNING: ATAPI READ TOC failed to get track info\n");
00945 
00946             uint32_t sec = (leadOut.min*60u*75u)+(leadOut.sec*75u)+leadOut.fr - 150u;
00947 
00948             prepare_read(0,MIN((unsigned int)8,(unsigned int)host_maximum_byte_count));
00949             sector[0] = sec >> 24u;
00950             sector[1] = sec >> 16u;
00951             sector[2] = sec >> 8u;
00952             sector[3] = sec & 0xFF;
00953             sector[4] = secsize >> 24u;
00954             sector[5] = secsize >> 16u;
00955             sector[6] = secsize >> 8u;
00956             sector[7] = secsize & 0xFF;
00957 //          LOG_MSG("sec=%lu secsize=%lu\n",sec,secsize);
00958 
00959             feature = 0x00;
00960             state = IDE_DEV_DATA_READ;
00961             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
00962 
00963             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
00964             lba[2] = sector_total >> 8;
00965             lba[1] = sector_total;
00966 
00967             controller->raise_irq();
00968             allow_writing = true;
00969             } break;
00970         case 0x2B: /* SEEK */
00971             count = 0x03;
00972             feature = 0x00;
00973             sector_total = 0x00;
00974             state = IDE_DEV_DATA_READ;
00975             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
00976 
00977             /* Don't care. Do nothing. */
00978 
00979             /* Except... Windows 95's CD player expects the SEEK command to interrupt CD audio playback.
00980              * In fact it depends on it to the exclusion of commands explicitly standardized to... you know...
00981              * stop or pause playback. Oh Microsoft, you twits... */
00982             {
00983                 CDROM_Interface *cdrom = getMSCDEXDrive();
00984                 if (cdrom) {
00985                     bool playing,pause;
00986 
00987                     if (!cdrom->GetAudioStatus(playing,pause))
00988                         playing = true;
00989 
00990                     if (playing) {
00991                         LOG_MSG("ATAPI: Interrupting CD audio playback due to SEEK\n");
00992                         cdrom->StopAudio();
00993                     }
00994                 }
00995             }
00996 
00997             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
00998             lba[2] = sector_total >> 8;
00999             lba[1] = sector_total;
01000 
01001             controller->raise_irq();
01002             allow_writing = true;
01003             break;
01004         case 0x12: /* INQUIRY */
01005             /* NTS: the state of atapi_to_host doesn't seem to matter. */
01006             generate_mmc_inquiry();
01007             prepare_read(0,MIN((unsigned int)36,(unsigned int)host_maximum_byte_count));
01008 
01009             feature = 0x00;
01010             state = IDE_DEV_DATA_READ;
01011             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01012 
01013             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01014             lba[2] = sector_total >> 8;
01015             lba[1] = sector_total;
01016 
01017             controller->raise_irq();
01018             allow_writing = true;
01019             break;
01020         case 0x28: /* READ(10) */
01021         case 0xA8: /* READ(12) */
01022             if (TransferLength == 0) {
01023                 /* this is legal. the SCSI MMC standards say so.
01024                    and apparently, MSCDEX.EXE issues READ(10) commands with transfer length == 0
01025                    to test the drive, so we have to emulate this */
01026                 feature = 0x00;
01027                 count = 0x03; /* no more transfer */
01028                 sector_total = 0;/*nothing to transfer */
01029                 state = IDE_DEV_READY;
01030                 status = IDE_STATUS_DRIVE_READY;
01031             }
01032             else {
01033                 /* OK, try to read */
01034                 CDROM_Interface *cdrom = getMSCDEXDrive();
01035                 bool res = (cdrom != NULL ? cdrom->ReadSectorsHost(/*buffer*/sector,false,LBA,TransferLength) : false);
01036                 if (res) {
01037                     prepare_read(0,MIN((unsigned int)(TransferLength*2048),(unsigned int)host_maximum_byte_count));
01038                     feature = 0x00;
01039                     state = IDE_DEV_DATA_READ;
01040                     status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01041                 }
01042                 else {
01043                     feature = 0xF4; /* abort sense=0xF */
01044                     count = 0x03; /* no more transfer */
01045                     sector_total = 0;/*nothing to transfer */
01046                     state = IDE_DEV_READY;
01047                     status = IDE_STATUS_DRIVE_READY|IDE_STATUS_ERROR;
01048                     LOG_MSG("ATAPI: Failed to read %lu sectors at %lu\n",
01049                         (unsigned long)TransferLength,(unsigned long)LBA);
01050                     /* TODO: write sense data */
01051                 }
01052             }
01053 
01054             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01055             lba[2] = sector_total >> 8;
01056             lba[1] = sector_total;
01057 
01058             controller->raise_irq();
01059             allow_writing = true;
01060             break;
01061         case 0x42: /* READ SUB-CHANNEL */
01062             read_subchannel();
01063 
01064             feature = 0x00;
01065             state = IDE_DEV_DATA_READ;
01066             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01067 
01068             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01069             lba[2] = sector_total >> 8;
01070             lba[1] = sector_total;
01071 
01072             controller->raise_irq();
01073             allow_writing = true;
01074             break;
01075         case 0x43: /* READ TOC */
01076             read_toc();
01077 
01078             feature = 0x00;
01079             state = IDE_DEV_DATA_READ;
01080             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01081 
01082             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01083             lba[2] = sector_total >> 8;
01084             lba[1] = sector_total;
01085 
01086             controller->raise_irq();
01087             allow_writing = true;
01088             break;
01089         case 0x45: /* PLAY AUDIO(10) */
01090             play_audio10();
01091 
01092             count = 0x03;
01093             feature = 0x00;
01094             sector_total = 0x00;
01095             state = IDE_DEV_DATA_READ;
01096             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01097 
01098             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01099             lba[2] = sector_total >> 8;
01100             lba[1] = sector_total;
01101 
01102             controller->raise_irq();
01103             allow_writing = true;
01104             break;
01105         case 0x47: /* PLAY AUDIO MSF */
01106             play_audio_msf();
01107 
01108             count = 0x03;
01109             feature = 0x00;
01110             sector_total = 0x00;
01111             state = IDE_DEV_DATA_READ;
01112             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01113 
01114             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01115             lba[2] = sector_total >> 8;
01116             lba[1] = sector_total;
01117 
01118             controller->raise_irq();
01119             allow_writing = true;
01120             break;
01121         case 0x4B: /* PAUSE/RESUME */
01122             pause_resume();
01123 
01124             count = 0x03;
01125             feature = 0x00;
01126             sector_total = 0x00;
01127             state = IDE_DEV_DATA_READ;
01128             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01129 
01130             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01131             lba[2] = sector_total >> 8;
01132             lba[1] = sector_total;
01133 
01134             controller->raise_irq();
01135             allow_writing = true;
01136             break;
01137         case 0x55: /* MODE SELECT(10) */
01138             /* we need the data written first, will act in I/O completion routine */
01139             {
01140                 unsigned int x;
01141 
01142                 x = (unsigned int)lba[1] + ((unsigned int)lba[2] << 8u);
01143 
01144                 /* Windows 95 likes to set 0xFFFF here for whatever reason.
01145                  * Negotiate it down to a maximum of 512 for sanity's sake */
01146                 if (x > 512) x = 512;
01147                 lba[2] = x >> 8u;
01148                 lba[1] = x;
01149 
01150 //              LOG_MSG("MODE SELECT expecting %u bytes\n",x);
01151                 prepare_write(0,(x+1u)&(~1u));
01152             }
01153 
01154             feature = 0x00;
01155             state = IDE_DEV_DATA_WRITE;
01156             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01157             controller->raise_irq();
01158             allow_writing = true;
01159             break;
01160         case 0x5A: /* MODE SENSE(10) */
01161             mode_sense();
01162 
01163             feature = 0x00;
01164             state = IDE_DEV_DATA_READ;
01165             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01166 
01167             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01168             lba[2] = sector_total >> 8;
01169             lba[1] = sector_total;
01170 
01171             controller->raise_irq();
01172             allow_writing = true;
01173             break;
01174         default:
01175             LOG_MSG("Unknown ATAPI command after busy wait. Why?\n");
01176             abort_error();
01177             controller->raise_irq();
01178             allow_writing = true;
01179             break;
01180     };
01181 
01182 }
01183 
01184 void IDEATAPICDROMDevice::set_sense(unsigned char SK,unsigned char ASC,unsigned char ASCQ,unsigned int len) {
01185     if (len < 18) len = 18;
01186     memset(sense,0,len);
01187     sense_length = len;
01188 
01189     sense[0] = 0x70;    /* RESPONSE CODE */
01190     sense[2] = SK&0xF;  /* SENSE KEY */
01191     sense[7] = len - 18;    /* additional sense length */
01192     sense[12] = ASC;
01193     sense[13] = ASCQ;
01194 }
01195 
01196 IDEATAPICDROMDevice::IDEATAPICDROMDevice(IDEController *c,unsigned char drive_index) : IDEDevice(c) {
01197     this->drive_index = drive_index;
01198     sector_i = sector_total = 0;
01199 
01200     memset(sense,0,sizeof(sense));
01201     set_sense(/*SK=*/0);
01202 
01203     /* FIXME: Spinup/down times should be dosbox.conf configurable, if the DOSBox gamers
01204      *        care more about loading times than emulation accuracy. */
01205     cd_insertion_time = 4000; /* a quick user that can switch CDs in 4 seconds */
01206     if (c->cd_insertion_time > 0) cd_insertion_time = c->cd_insertion_time;
01207 
01208     spinup_time = 1000; /* drive takes 1 second to spin up from idle */
01209     if (c->spinup_time > 0) spinup_time = c->spinup_time;
01210 
01211     spindown_timeout = 10000; /* drive spins down automatically after 10 seconds */
01212     if (c->spindown_timeout > 0) spindown_timeout = c->spindown_timeout;
01213 
01214     loading_mode = LOAD_IDLE;
01215     has_changed = false;
01216 
01217     type = IDE_TYPE_CDROM;
01218     id_serial = "123456789";
01219     id_firmware_rev = "0.74-X";
01220     id_model = "DOSBox Virtual CD-ROM";
01221 
01222     /* INQUIRY strings */
01223     id_mmc_vendor_id = "DOSBox";
01224     id_mmc_product_id = "Virtual CD-ROM";
01225     id_mmc_product_rev = "0.74-X";
01226 }
01227 
01228 IDEATAPICDROMDevice::~IDEATAPICDROMDevice() {
01229 }
01230 
01231 void IDEATAPICDROMDevice::on_mode_select_io_complete() {
01232     unsigned int AllocationLength = ((unsigned int)atapi_cmd[7] << 8) + atapi_cmd[8];
01233     unsigned char *scan,*fence;
01234     size_t i;
01235 
01236     /* the first 8 bytes are a mode parameter header.
01237      * It's supposed to provide length, density, etc. or whatever the hell
01238      * it means. Windows 95 seems to send all zeros there, so ignore it.
01239      *
01240      * we care about the bytes following it, which contain page_0 mode
01241      * pages */
01242 
01243     scan = sector + 8;
01244     fence = sector + MIN((unsigned int)sector_total,(unsigned int)AllocationLength);
01245 
01246     while ((scan+2) < fence) {
01247         unsigned char PAGE = *scan++;
01248         unsigned int LEN = (unsigned int)(*scan++);
01249 
01250         if ((scan+LEN) > fence) {
01251             LOG_MSG("ATAPI MODE SELECT warning, page_0 length extends %u bytes past buffer\n",(unsigned int)(scan+LEN-fence));
01252             break;
01253         }
01254 
01255         LOG_MSG("ATAPI MODE SELECT, PAGE 0x%02x len=%u\n",PAGE,LEN);
01256         LOG_MSG("  ");
01257         for (i=0;i < LEN;i++) LOG_MSG("%02x ",scan[i]);
01258         LOG_MSG("\n");
01259 
01260         scan += LEN;
01261     }
01262 }
01263 
01264 void IDEATAPICDROMDevice::atapi_io_completion() {
01265     /* for most ATAPI PACKET commands, the transfer is done and we need to clear
01266        all indication of a possible data transfer */
01267 
01268     if (count == 0x00) { /* the command was expecting data. now it can act on it */
01269         switch (atapi_cmd[0]) {
01270             case 0x55: /* MODE SELECT(10) */
01271                 on_mode_select_io_complete();
01272                 break;
01273         };
01274     }
01275 
01276     count = 0x03; /* no more data (command/data=1, input/output=1) */
01277     status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01278     state = IDE_DEV_READY;
01279     allow_writing = true;
01280 
01281     /* Apparently: real IDE ATAPI controllers fire another IRQ after the transfer.
01282        And there are MS-DOS CD-ROM drivers that assume that. */
01283     controller->raise_irq();
01284 }
01285     
01286 void IDEATAPICDROMDevice::io_completion() {
01287     /* lower DRQ */
01288     status &= ~IDE_STATUS_DRQ;
01289 
01290     /* depending on the command, either continue it or finish up */
01291     switch (command) {
01292         case 0xA0:/*ATAPI PACKET*/
01293             atapi_io_completion();
01294             break;
01295         default: /* most commands: signal drive ready, return to ready state */
01296             /* NTS: Some MS-DOS CD-ROM drivers will loop endlessly if we never set "drive seek complete"
01297                     because they like to hit the device with DEVICE RESET (08h) whether or not it's
01298                 a hard disk or CD-ROM drive */
01299             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01300             state = IDE_DEV_READY;
01301             allow_writing = true;
01302             break;
01303     }
01304 }
01305 
01306 bool IDEATADevice::increment_current_address(Bitu count) {
01307     if (count == 0) return false;
01308 
01309     if (drivehead_is_lba(drivehead)) {
01310         /* 28-bit LBA:
01311          *    drivehead: 27:24
01312          *    lba[2]:    23:16
01313          *    lba[1]:    15:8
01314          *    lba[0]:    7:0 */
01315         do {
01316             if (((++lba[0])&0xFF) == 0x00) {
01317                 lba[0] = 0x00;
01318                 if (((++lba[1])&0xFF) == 0x00) {
01319                     lba[1] = 0x00;
01320                     if (((++lba[2])&0xFF) == 0x00) {
01321                         lba[2] = 0x00;
01322                         if (((++drivehead)&0xF) == 0) {
01323                             drivehead -= 0x10;
01324                             return false;
01325                         }
01326                     }
01327                 }
01328             }
01329         } while ((--count) != 0);
01330     }
01331     else {
01332         /* C/H/S increment with rollover */
01333         do {
01334             /* increment sector */
01335             if (((++lba[0])&0xFF) == ((sects+1)&0xFF)) {
01336                 lba[0] = 1;
01337                 /* increment head */
01338                 if (((++drivehead)&0xF) == (heads&0xF)) {
01339                     drivehead &= 0xF0;
01340                     if (heads == 16) drivehead -= 0x10;
01341                     /* increment cylinder */
01342                     if (((++lba[1])&0xFF) == 0x00) {
01343                         if (((++lba[2])&0xFF) == 0x00) {
01344                             return false;
01345                         }
01346                     }
01347                 }
01348 
01349             }
01350         } while ((--count) != 0);
01351     }
01352 
01353     return true;
01354 }
01355 
01356 void IDEATADevice::io_completion() {
01357     /* lower DRQ */
01358     status &= ~IDE_STATUS_DRQ;
01359 
01360     /* depending on the command, either continue it or finish up */
01361     switch (command) {
01362         case 0x20:/* READ SECTOR */
01363             /* OK, decrement count, increment address */
01364             /* NTS: Remember that count == 0 means the host wanted to transfer 256 sectors */
01365             progress_count++;
01366             if ((count&0xFF) == 1) {
01367                 /* end of the transfer */
01368                 count = 0;
01369                 status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01370                 state = IDE_DEV_READY;
01371                 allow_writing = true;
01372                 return;
01373             }
01374             else if ((count&0xFF) == 0) count = 255;
01375             else count--;
01376 
01377             if (!increment_current_address()) {
01378                 LOG_MSG("READ advance error\n");
01379                 abort_error();
01380                 return;
01381             }
01382 
01383             /* cause another delay, another sector read */
01384             state = IDE_DEV_BUSY;
01385             status = IDE_STATUS_BUSY;
01386             PIC_AddEvent(IDE_DelayedCommand,0.00001/*ms*/,controller->interface_index);
01387             break;
01388         case 0x30:/* WRITE SECTOR */
01389             /* this is where the drive has accepted the sector, lowers DRQ, and begins executing the command */
01390             state = IDE_DEV_BUSY;
01391             status = IDE_STATUS_BUSY;
01392             PIC_AddEvent(IDE_DelayedCommand,((progress_count == 0 && !faked_command) ? 0.1 : 0.00001)/*ms*/,controller->interface_index);
01393             break;
01394         case 0xC4:/* READ MULTIPLE */
01395             /* OK, decrement count, increment address */
01396             /* NTS: Remember that count == 0 means the host wanted to transfer 256 sectors */
01397             for (unsigned int cc=0;cc < multiple_sector_count;cc++) {
01398                 progress_count++;
01399                 if ((count&0xFF) == 1) {
01400                     /* end of the transfer */
01401                     count = 0;
01402                     status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01403                     state = IDE_DEV_READY;
01404                     allow_writing = true;
01405                     return;
01406                 }
01407                 else if ((count&0xFF) == 0) count = 255;
01408                 else count--;
01409 
01410                 if (!increment_current_address()) {
01411                     LOG_MSG("READ advance error\n");
01412                     abort_error();
01413                     return;
01414                 }
01415             }
01416 
01417             /* cause another delay, another sector read */
01418             state = IDE_DEV_BUSY;
01419             status = IDE_STATUS_BUSY;
01420             PIC_AddEvent(IDE_DelayedCommand,0.00001/*ms*/,controller->interface_index);
01421             break;
01422         case 0xC5:/* WRITE MULTIPLE */
01423             /* this is where the drive has accepted the sector, lowers DRQ, and begins executing the command */
01424             state = IDE_DEV_BUSY;
01425             status = IDE_STATUS_BUSY;
01426             PIC_AddEvent(IDE_DelayedCommand,((progress_count == 0 && !faked_command) ? 0.1 : 0.00001)/*ms*/,controller->interface_index);
01427             break;
01428         default: /* most commands: signal drive ready, return to ready state */
01429             /* NTS: Some MS-DOS CD-ROM drivers will loop endlessly if we never set "drive seek complete"
01430                     because they like to hit the device with DEVICE RESET (08h) whether or not it's
01431                 a hard disk or CD-ROM drive */
01432             count = 0;
01433             drivehead &= 0xF0;
01434             lba[0] = 0;
01435             lba[1] = lba[2] = 0;
01436             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01437             state = IDE_DEV_READY;
01438             allow_writing = true;
01439             break;
01440     }
01441 }
01442 
01443 Bitu IDEATAPICDROMDevice::data_read(Bitu iolen) {
01444     Bitu w = ~0u;
01445 
01446     if (state != IDE_DEV_DATA_READ)
01447         return 0xFFFFUL;
01448 
01449     if (!(status & IDE_STATUS_DRQ)) {
01450         LOG_MSG("IDE: Data read when DRQ=0\n");
01451         return 0xFFFFUL;
01452     }
01453 
01454     if (sector_i >= sector_total)
01455         return 0xFFFFUL;
01456 
01457     if (iolen >= 4) {
01458         w = host_readd(sector+sector_i);
01459         sector_i += 4;
01460     }
01461     else if (iolen >= 2) {
01462         w = host_readw(sector+sector_i);
01463         sector_i += 2;
01464     }
01465     /* NTS: Some MS-DOS CD-ROM drivers like OAKCDROM.SYS use byte-wide I/O for the initial identification */
01466     else if (iolen == 1) {
01467         w = sector[sector_i++];
01468     }
01469 
01470     if (sector_i >= sector_total)
01471         io_completion();
01472 
01473     return w;
01474 }
01475 
01476 /* TODO: Your code should also be paying attention to the "transfer length" field
01477          in many of the commands here. Right now it doesn't matter. */
01478 void IDEATAPICDROMDevice::atapi_cmd_completion() {
01479 #if 0
01480     LOG_MSG("ATAPI command %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x to_host=%u\n",
01481         atapi_cmd[ 0],atapi_cmd[ 1],atapi_cmd[ 2],atapi_cmd[ 3],atapi_cmd[ 4],atapi_cmd[ 5],
01482         atapi_cmd[ 6],atapi_cmd[ 7],atapi_cmd[ 8],atapi_cmd[ 9],atapi_cmd[10],atapi_cmd[11],
01483         atapi_to_host);
01484 #endif
01485 
01486     switch (atapi_cmd[0]) {
01487         case 0x00: /* TEST UNIT READY */
01488             if (common_spinup_response(/*spin up*/false,/*wait*/false))
01489                 set_sense(0); /* <- nothing wrong */
01490 
01491             count = 0x03;
01492             state = IDE_DEV_READY;
01493             feature = ((sense[2]&0xF) << 4) | (sense[2]&0xF ? 0x04/*abort*/ : 0x00);
01494             status = IDE_STATUS_DRIVE_READY|(sense[2]&0xF ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01495             controller->raise_irq();
01496             allow_writing = true;
01497             break;
01498         case 0x03: /* REQUEST SENSE */
01499             count = 0x02;
01500             state = IDE_DEV_ATAPI_BUSY;
01501             status = IDE_STATUS_BUSY;
01502             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01503             break;
01504         case 0x1E: /* PREVENT ALLOW MEDIUM REMOVAL */
01505             count = 0x02;
01506             state = IDE_DEV_ATAPI_BUSY;
01507             status = IDE_STATUS_BUSY;
01508             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01509             break;
01510         case 0x25: /* READ CAPACITY */
01511             count = 0x02;
01512             state = IDE_DEV_ATAPI_BUSY;
01513             status = IDE_STATUS_BUSY;
01514             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01515             break;
01516         case 0x2B: /* SEEK */
01517             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01518                 set_sense(0); /* <- nothing wrong */
01519                 count = 0x02;
01520                 state = IDE_DEV_ATAPI_BUSY;
01521                 status = IDE_STATUS_BUSY;
01522                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01523             }
01524             else {
01525                 count = 0x03;
01526                 state = IDE_DEV_READY;
01527                 feature = ((sense[2]&0xF) << 4) | (sense[2]&0xF ? 0x04/*abort*/ : 0x00);
01528                 status = IDE_STATUS_DRIVE_READY|(sense[2]&0xF ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01529                 controller->raise_irq();
01530                 allow_writing = true;
01531             }
01532             break;
01533         case 0x12: /* INQUIRY */
01534             count = 0x02;
01535             state = IDE_DEV_ATAPI_BUSY;
01536             status = IDE_STATUS_BUSY;
01537             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01538             break;
01539         case 0xA8: /* READ(12) */
01540             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01541                 set_sense(0); /* <- nothing wrong */
01542 
01543                 /* FIXME: MSCDEX.EXE appears to test the drive by issuing READ(10) with transfer length == 0.
01544                    This is all well and good but our response seems to cause a temporary 2-3 second
01545                    pause for each attempt. Why? */
01546                 LBA = ((Bitu)atapi_cmd[2] << 24UL) |
01547                     ((Bitu)atapi_cmd[3] << 16UL) |
01548                     ((Bitu)atapi_cmd[4] << 8UL) |
01549                     ((Bitu)atapi_cmd[5] << 0UL);
01550                 TransferLength = ((Bitu)atapi_cmd[6] << 24UL) |
01551                     ((Bitu)atapi_cmd[7] << 16UL) |
01552                     ((Bitu)atapi_cmd[8] << 8UL) |
01553                     ((Bitu)atapi_cmd[9]);
01554 
01555                 /* FIXME: We actually should NOT be capping the transfer length, but instead should
01556                    be breaking the larger transfer into smaller DRQ block transfers like
01557                    most IDE ATAPI drives do. Writing the test IDE code taught me that if you
01558                    go to most drives and request a transfer length of 0xFFFE the drive will
01559                    happily set itself up to transfer that many sectors in one IDE command! */
01560                 /* NTS: In case you're wondering, it's legal to issue READ(10) with transfer length == 0.
01561                    MSCDEX.EXE does it when starting up, for example */
01562                 if ((TransferLength*2048) > sizeof(sector))
01563                     TransferLength = sizeof(sector)/2048;
01564 
01565                 count = 0x02;
01566                 state = IDE_DEV_ATAPI_BUSY;
01567                 status = IDE_STATUS_BUSY;
01568                 /* TODO: Emulate CD-ROM spin-up delay, and seek delay */
01569                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 3)/*ms*/,controller->interface_index);
01570             }
01571             else {
01572                 count = 0x03;
01573                 state = IDE_DEV_READY;
01574                 feature = ((sense[2]&0xF) << 4) | (sense[2]&0xF ? 0x04/*abort*/ : 0x00);
01575                 status = IDE_STATUS_DRIVE_READY|(sense[2]&0xF ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01576                 controller->raise_irq();
01577                 allow_writing = true;
01578             }
01579             break;
01580         case 0x28: /* READ(10) */
01581             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01582                 set_sense(0); /* <- nothing wrong */
01583 
01584                 /* FIXME: MSCDEX.EXE appears to test the drive by issuing READ(10) with transfer length == 0.
01585                    This is all well and good but our response seems to cause a temporary 2-3 second
01586                    pause for each attempt. Why? */
01587                 LBA = ((Bitu)atapi_cmd[2] << 24UL) |
01588                     ((Bitu)atapi_cmd[3] << 16UL) |
01589                     ((Bitu)atapi_cmd[4] << 8UL) |
01590                     ((Bitu)atapi_cmd[5] << 0UL);
01591                 TransferLength = ((Bitu)atapi_cmd[7] << 8) |
01592                     ((Bitu)atapi_cmd[8]);
01593 
01594                 /* FIXME: We actually should NOT be capping the transfer length, but instead should
01595                    be breaking the larger transfer into smaller DRQ block transfers like
01596                    most IDE ATAPI drives do. Writing the test IDE code taught me that if you
01597                    go to most drives and request a transfer length of 0xFFFE the drive will
01598                    happily set itself up to transfer that many sectors in one IDE command! */
01599                 /* NTS: In case you're wondering, it's legal to issue READ(10) with transfer length == 0.
01600                    MSCDEX.EXE does it when starting up, for example */
01601                 if ((TransferLength*2048) > sizeof(sector))
01602                     TransferLength = sizeof(sector)/2048;
01603 
01604                 count = 0x02;
01605                 state = IDE_DEV_ATAPI_BUSY;
01606                 status = IDE_STATUS_BUSY;
01607                 /* TODO: Emulate CD-ROM spin-up delay, and seek delay */
01608                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 3)/*ms*/,controller->interface_index);
01609             }
01610             else {
01611                 count = 0x03;
01612                 state = IDE_DEV_READY;
01613                 feature = ((sense[2]&0xF) << 4) | (sense[2]&0xF ? 0x04/*abort*/ : 0x00);
01614                 status = IDE_STATUS_DRIVE_READY|(sense[2]&0xF ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01615                 controller->raise_irq();
01616                 allow_writing = true;
01617             }
01618             break;
01619         case 0x42: /* READ SUB-CHANNEL */
01620             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01621                 set_sense(0); /* <- nothing wrong */
01622 
01623                 count = 0x02;
01624                 state = IDE_DEV_ATAPI_BUSY;
01625                 status = IDE_STATUS_BUSY;
01626                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01627             }
01628             else {
01629                 count = 0x03;
01630                 state = IDE_DEV_READY;
01631                 feature = ((sense[2]&0xF) << 4) | (sense[2]&0xF ? 0x04/*abort*/ : 0x00);
01632                 status = IDE_STATUS_DRIVE_READY|(sense[2]&0xF ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01633                 controller->raise_irq();
01634                 allow_writing = true;
01635             }
01636             break;
01637         case 0x43: /* READ TOC */
01638             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01639                 set_sense(0); /* <- nothing wrong */
01640 
01641                 count = 0x02;
01642                 state = IDE_DEV_ATAPI_BUSY;
01643                 status = IDE_STATUS_BUSY;
01644                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01645             }
01646             else {
01647                 count = 0x03;
01648                 state = IDE_DEV_READY;
01649                 feature = ((sense[2]&0xF) << 4) | (sense[2]&0xF ? 0x04/*abort*/ : 0x00);
01650                 status = IDE_STATUS_DRIVE_READY|(sense[2]&0xF ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01651                 controller->raise_irq();
01652                 allow_writing = true;
01653             }
01654             break;
01655         case 0x45: /* PLAY AUDIO (1) */
01656         case 0x47: /* PLAY AUDIO MSF */
01657         case 0x4B: /* PAUSE/RESUME */
01658             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01659                 set_sense(0); /* <- nothing wrong */
01660 
01661                 count = 0x02;
01662                 state = IDE_DEV_ATAPI_BUSY;
01663                 status = IDE_STATUS_BUSY;
01664                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01665             }
01666             else {
01667                 count = 0x03;
01668                 state = IDE_DEV_READY;
01669                 feature = ((sense[2]&0xF) << 4) | (sense[2]&0xF ? 0x04/*abort*/ : 0x00);
01670                 status = IDE_STATUS_DRIVE_READY|(sense[2]&0xF ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01671                 controller->raise_irq();
01672                 allow_writing = true;
01673             }
01674             break;
01675         case 0x55: /* MODE SELECT(10) */
01676             count = 0x00;   /* we will be accepting data */
01677             state = IDE_DEV_ATAPI_BUSY;
01678             status = IDE_STATUS_BUSY;
01679             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01680             break;
01681         case 0x5A: /* MODE SENSE(10) */
01682             count = 0x02;
01683             state = IDE_DEV_ATAPI_BUSY;
01684             status = IDE_STATUS_BUSY;
01685             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01686             break;
01687         default:
01688             /* we don't know the command, immediately return an error */
01689             LOG_MSG("Unknown ATAPI command %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
01690                 atapi_cmd[ 0],atapi_cmd[ 1],atapi_cmd[ 2],atapi_cmd[ 3],atapi_cmd[ 4],atapi_cmd[ 5],
01691                 atapi_cmd[ 6],atapi_cmd[ 7],atapi_cmd[ 8],atapi_cmd[ 9],atapi_cmd[10],atapi_cmd[11]);
01692 
01693             abort_error();
01694             count = 0x03; /* no more data (command/data=1, input/output=1) */
01695             feature = 0xF4;
01696             controller->raise_irq();
01697             allow_writing = true;
01698             break;
01699     };
01700 }
01701 
01702 void IDEATAPICDROMDevice::data_write(Bitu v,Bitu iolen) {
01703     if (state == IDE_DEV_ATAPI_PACKET_COMMAND) {
01704         if (atapi_cmd_i < atapi_cmd_total)
01705             atapi_cmd[atapi_cmd_i++] = v;
01706         if (iolen >= 2 && atapi_cmd_i < atapi_cmd_total)
01707             atapi_cmd[atapi_cmd_i++] = v >> 8;
01708         if (iolen >= 4 && atapi_cmd_i < atapi_cmd_total) {
01709             atapi_cmd[atapi_cmd_i++] = v >> 16;
01710             atapi_cmd[atapi_cmd_i++] = v >> 24;
01711         }
01712 
01713         if (atapi_cmd_i >= atapi_cmd_total)
01714             atapi_cmd_completion();
01715     }
01716     else {
01717         if (state != IDE_DEV_DATA_WRITE) {
01718             LOG_MSG("ide atapi warning: data write when device not in data_write state\n");
01719             return;
01720         }
01721         if (!(status & IDE_STATUS_DRQ)) {
01722             LOG_MSG("ide atapi warning: data write with drq=0\n");
01723             return;
01724         }
01725         if ((sector_i+iolen) > sector_total) {
01726             LOG_MSG("ide atapi warning: sector already full %lu / %lu\n",(unsigned long)sector_i,(unsigned long)sector_total);
01727             return;
01728         }
01729 
01730         if (iolen >= 4) {
01731             host_writed(sector+sector_i,v);
01732             sector_i += 4;
01733         }
01734         else if (iolen >= 2) {
01735             host_writew(sector+sector_i,v);
01736             sector_i += 2;
01737         }
01738         else if (iolen == 1) {
01739             sector[sector_i++] = v;
01740         }
01741 
01742         if (sector_i >= sector_total)
01743             io_completion();
01744     }
01745 }
01746 
01747 Bitu IDEATADevice::data_read(Bitu iolen) {
01748     Bitu w = ~0u;
01749 
01750     if (state != IDE_DEV_DATA_READ)
01751         return 0xFFFFUL;
01752 
01753     if (!(status & IDE_STATUS_DRQ)) {
01754         LOG_MSG("IDE: Data read when DRQ=0\n");
01755         return 0xFFFFUL;
01756     }
01757 
01758     if ((sector_i+iolen) > sector_total) {
01759         LOG_MSG("ide ata warning: sector already read %lu / %lu\n",(unsigned long)sector_i,(unsigned long)sector_total);
01760         return 0xFFFFUL;
01761     }
01762 
01763     if (iolen >= 4) {
01764         w = host_readd(sector+sector_i);
01765         sector_i += 4;
01766     }
01767     else if (iolen >= 2) {
01768         w = host_readw(sector+sector_i);
01769         sector_i += 2;
01770     }
01771     /* NTS: Some MS-DOS CD-ROM drivers like OAKCDROM.SYS use byte-wide I/O for the initial identification */
01772     else if (iolen == 1) {
01773         w = sector[sector_i++];
01774     }
01775 
01776     if (sector_i >= sector_total)
01777         io_completion();
01778 
01779     return w;
01780 }
01781 
01782 void IDEATADevice::data_write(Bitu v,Bitu iolen) {
01783     if (state != IDE_DEV_DATA_WRITE) {
01784         LOG_MSG("ide ata warning: data write when device not in data_write state\n");
01785         return;
01786     }
01787     if (!(status & IDE_STATUS_DRQ)) {
01788         LOG_MSG("ide ata warning: data write with drq=0\n");
01789         return;
01790     }
01791     if ((sector_i+iolen) > sector_total) {
01792         LOG_MSG("ide ata warning: sector already full %lu / %lu\n",(unsigned long)sector_i,(unsigned long)sector_total);
01793         return;
01794     }
01795 
01796     if (iolen >= 4) {
01797         host_writed(sector+sector_i,v);
01798         sector_i += 4;
01799     }
01800     else if (iolen >= 2) {
01801         host_writew(sector+sector_i,v);
01802         sector_i += 2;
01803     }
01804     else if (iolen == 1) {
01805         sector[sector_i++] = v;
01806     }
01807 
01808     if (sector_i >= sector_total)
01809         io_completion();
01810 }
01811         
01812 void IDEATAPICDROMDevice::prepare_read(Bitu offset,Bitu size) {
01813     /* I/O must be WORD ALIGNED */
01814     assert((offset&1) == 0);
01815 //  assert((size&1) == 0);
01816 
01817     sector_i = offset;
01818     sector_total = size;
01819     assert(sector_i <= sector_total);
01820     assert(sector_total <= sizeof(sector));
01821 }
01822 
01823 void IDEATAPICDROMDevice::prepare_write(Bitu offset,Bitu size) {
01824     /* I/O must be WORD ALIGNED */
01825     assert((offset&1) == 0);
01826 //  assert((size&1) == 0);
01827 
01828     sector_i = offset;
01829     sector_total = size;
01830     assert(sector_i <= sector_total);
01831     assert(sector_total <= sizeof(sector));
01832 }
01833 
01834 void IDEATADevice::prepare_write(Bitu offset,Bitu size) {
01835     /* I/O must be WORD ALIGNED */
01836     assert((offset&1) == 0);
01837 //  assert((size&1) == 0);
01838 
01839     sector_i = offset;
01840     sector_total = size;
01841     assert(sector_i <= sector_total);
01842     assert(sector_total <= sizeof(sector));
01843 }
01844 
01845 void IDEATADevice::prepare_read(Bitu offset,Bitu size) {
01846     /* I/O must be WORD ALIGNED */
01847     assert((offset&1) == 0);
01848 //  assert((size&1) == 0);
01849 
01850     sector_i = offset;
01851     sector_total = size;
01852     assert(sector_i <= sector_total);
01853     assert(sector_total <= sizeof(sector));
01854 }
01855 
01856 void IDEATAPICDROMDevice::generate_mmc_inquiry() {
01857     Bitu i;
01858 
01859     /* IN RESPONSE TO ATAPI COMMAND 0x12: INQUIRY */
01860     memset(sector,0,36);
01861     sector[0] = (0 << 5) | 5;   /* Peripheral qualifier=0   device type=5 (CDROM) */
01862     sector[1] = 0x80;       /* RMB=1 removable media */
01863     sector[3] = 0x21;
01864     sector[4] = 36 - 5;     /* additional length */
01865 
01866     for (i=0;i < 8 && i < id_mmc_vendor_id.length();i++)
01867         sector[i+8] = (unsigned char)id_mmc_vendor_id[i];
01868     for (;i < 8;i++)
01869         sector[i+8] = ' ';
01870 
01871     for (i=0;i < 16 && i < id_mmc_product_id.length();i++)
01872         sector[i+16] = (unsigned char)id_mmc_product_id[i];
01873     for (;i < 16;i++)
01874         sector[i+16] = ' ';
01875 
01876     for (i=0;i < 4 && i < id_mmc_product_rev.length();i++)
01877         sector[i+32] = (unsigned char)id_mmc_product_rev[i];
01878     for (;i < 4;i++)
01879         sector[i+32] = ' ';
01880 }
01881 
01882 void IDEATAPICDROMDevice::generate_identify_device() {
01883     unsigned char csum;
01884     Bitu i;
01885 
01886     /* IN RESPONSE TO IDENTIFY DEVICE (0xA1)
01887        GENERATE 512-BYTE REPLY */
01888     memset(sector,0,512);
01889 
01890     host_writew(sector+(0*2),0x85C0U);  /* ATAPI device, command set #5 (what the fuck does that mean?), removable, */
01891 
01892     for (i=0;i < 20 && i < id_serial.length();i++)
01893         sector[(i^1)+(10*2)] = (unsigned char)id_serial[i];
01894     for (;i < 20;i++)
01895         sector[(i^1)+(10*2)] = ' ';
01896 
01897     for (i=0;i < 8 && i < id_firmware_rev.length();i++)
01898         sector[(i^1)+(23*2)] = (unsigned char)id_firmware_rev[i];
01899     for (;i < 8;i++)
01900         sector[(i^1)+(23*2)] = ' ';
01901 
01902     for (i=0;i < 40 && i < id_model.length();i++)
01903         sector[(i^1)+(27*2)] = (unsigned char)id_model[i];
01904     for (;i < 40;i++)
01905         sector[(i^1)+(27*2)] = ' ';
01906 
01907     host_writew(sector+(49*2),
01908         0x0800UL|/*IORDY supported*/
01909         0x0200UL|/*must be one*/
01910         0);
01911     host_writew(sector+(50*2),
01912         0x4000UL);
01913     host_writew(sector+(51*2),
01914         0x00F0UL);
01915     host_writew(sector+(52*2),
01916         0x00F0UL);
01917     host_writew(sector+(53*2),
01918         0x0006UL);
01919     host_writew(sector+(64*2),      /* PIO modes supported */
01920         0x0003UL);
01921     host_writew(sector+(67*2),      /* PIO cycle time */
01922         0x0078UL);
01923     host_writew(sector+(68*2),      /* PIO cycle time */
01924         0x0078UL);
01925     host_writew(sector+(80*2),0x007E); /* major version number. Here we say we support ATA-1 through ATA-8 */
01926     host_writew(sector+(81*2),0x0022); /* minor version */
01927     host_writew(sector+(82*2),0x4008); /* command set: NOP, DEVICE RESET[XXXXX], POWER MANAGEMENT */
01928     host_writew(sector+(83*2),0x0000); /* command set: LBA48[XXXX] */
01929     host_writew(sector+(85*2),0x4208); /* commands in 82 enabled */
01930     host_writew(sector+(86*2),0x0000); /* commands in 83 enabled */
01931 
01932     /* ATA-8 integrity checksum */
01933     sector[510] = 0xA5;
01934     csum = 0; for (i=0;i < 511;i++) csum += sector[i];
01935     sector[511] = 0 - csum;
01936 }
01937 
01938 void IDEATADevice::generate_identify_device() {
01939 //  imageDisk *disk = getBIOSdisk();
01940     unsigned char csum;
01941     uint64_t ptotal;
01942     uint64_t total;
01943     Bitu i;
01944 
01945     /* IN RESPONSE TO IDENTIFY DEVICE (0xEC)
01946        GENERATE 512-BYTE REPLY */
01947     memset(sector,0,512);
01948 
01949     /* total disk capacity in sectors */
01950     total = sects * cyls * heads;
01951     ptotal = phys_sects * phys_cyls * phys_heads;
01952 
01953     host_writew(sector+(0*2),0x0040);   /* bit 6: 1=fixed disk */
01954     host_writew(sector+(1*2),phys_cyls);
01955     host_writew(sector+(3*2),phys_heads);
01956     host_writew(sector+(4*2),phys_sects * 512); /* unformatted bytes per track */
01957     host_writew(sector+(5*2),512);      /* unformatted bytes per sector */
01958     host_writew(sector+(6*2),phys_sects);
01959 
01960     for (i=0;i < 20 && i < id_serial.length();i++)
01961         sector[(i^1)+(10*2)] = (unsigned char)id_serial[i];
01962     for (;i < 20;i++)
01963         sector[(i^1)+(10*2)] = ' ';
01964 
01965     host_writew(sector+(20*2),1);       /* ATA-1: single-ported single sector buffer */
01966     host_writew(sector+(21*2),4);       /* ATA-1: ECC bytes on read/write long */
01967 
01968     for (i=0;i < 8 && i < id_firmware_rev.length();i++)
01969         sector[(i^1)+(23*2)] = (unsigned char)id_firmware_rev[i];
01970     for (;i < 8;i++)
01971         sector[(i^1)+(23*2)] = ' ';
01972 
01973     for (i=0;i < 40 && i < id_model.length();i++)
01974         sector[(i^1)+(27*2)] = (unsigned char)id_model[i];
01975     for (;i < 40;i++)
01976         sector[(i^1)+(27*2)] = ' ';
01977 
01978     if (multiple_sector_max != 0)
01979         host_writew(sector+(47*2),0x80|multiple_sector_max); /* <- READ/WRITE MULTIPLE MAX SECTORS */
01980 
01981     host_writew(sector+(48*2),0x0000);  /* :0  0=we do not support doubleword (32-bit) PIO */
01982     host_writew(sector+(49*2),0x0A00);  /* :13 0=Standby timer values managed by device */
01983                         /* :11 1=IORDY supported */
01984                         /* :10 0=IORDY not disabled */
01985                         /* :9  1=LBA supported */
01986                         /* :8  0=DMA not supported */
01987     host_writew(sector+(50*2),0x4000);  /* FIXME: ??? */
01988     host_writew(sector+(51*2),0x00F0);  /* PIO data transfer cycle timing mode */
01989     host_writew(sector+(52*2),0x00F0);  /* DMA data transfer cycle timing mode */
01990     host_writew(sector+(53*2),0x0007);  /* :2  1=the fields in word 88 are valid */
01991                         /* :1  1=the fields in word (70:64) are valid */
01992                         /* :0  1= ??? */
01993     host_writew(sector+(54*2),cyls);    /* current cylinders */
01994     host_writew(sector+(55*2),heads);   /* current heads */
01995     host_writew(sector+(56*2),sects);   /* current sectors per track */
01996     host_writed(sector+(57*2),total);   /* current capacity in sectors */
01997 
01998     if (multiple_sector_count != 0)
01999         host_writew(sector+(59*2),0x0100|multiple_sector_count); /* :8  multiple sector setting is valid */
02000                         /* 7:0 current setting for number of log. sectors per DRQ of READ/WRITE MULTIPLE */
02001 
02002     host_writed(sector+(60*2),ptotal);  /* total user addressable sectors (LBA) */
02003     host_writew(sector+(62*2),0x0000);  /* FIXME: ??? */
02004     host_writew(sector+(63*2),0x0000);  /* :10 0=Multiword DMA mode 2 not selected */
02005                         /* TODO: Basically, we don't do DMA. Fill out this comment */
02006     host_writew(sector+(64*2),0x0003);  /* 7:0 PIO modes supported (FIXME ???) */
02007     host_writew(sector+(65*2),0x0000);  /* FIXME: ??? */
02008     host_writew(sector+(66*2),0x0000);  /* FIXME: ??? */
02009     host_writew(sector+(67*2),0x0078);  /* FIXME: ??? */
02010     host_writew(sector+(68*2),0x0078);  /* FIXME: ??? */
02011     host_writew(sector+(80*2),0x007E);  /* major version number. Here we say we support ATA-1 through ATA-8 */
02012     host_writew(sector+(81*2),0x0022);  /* minor version */
02013     host_writew(sector+(82*2),0x4208);  /* command set: NOP, DEVICE RESET[XXXXX], POWER MANAGEMENT */
02014     host_writew(sector+(83*2),0x4000);  /* command set: LBA48[XXXX] */
02015     host_writew(sector+(84*2),0x4000);  /* FIXME: ??? */
02016     host_writew(sector+(85*2),0x4208);  /* commands in 82 enabled */
02017     host_writew(sector+(86*2),0x4000);  /* commands in 83 enabled */
02018     host_writew(sector+(87*2),0x4000);  /* FIXME: ??? */
02019     host_writew(sector+(88*2),0x0000);  /* FIXME: ??? */
02020     host_writew(sector+(93*3),0x0000);  /* FIXME: ??? */
02021 
02022     /* ATA-8 integrity checksum */
02023     sector[510] = 0xA5;
02024     csum = 0; for (i=0;i < 511;i++) csum += sector[i];
02025     sector[511] = 0 - csum;
02026 }
02027 
02028 IDEATADevice::IDEATADevice(IDEController *c,unsigned char bios_disk_index) : IDEDevice(c) {
02029     this->bios_disk_index = bios_disk_index;
02030     sector_i = sector_total = 0;
02031 
02032     headshr = 0;
02033     type = IDE_TYPE_HDD;
02034     id_serial = "8086";
02035     id_firmware_rev = "8086";
02036     id_model = "DOSBox IDE disk";
02037     multiple_sector_max = sizeof(sector) / 512;
02038     multiple_sector_count = 1;
02039 }
02040 
02041 IDEATADevice::~IDEATADevice() {
02042 }
02043 
02044 imageDisk *IDEATADevice::getBIOSdisk() {
02045     if (bios_disk_index >= (2 + MAX_HDD_IMAGES)) return NULL;
02046     return imageDiskList[bios_disk_index];
02047 }
02048 
02049 CDROM_Interface *IDEATAPICDROMDevice::getMSCDEXDrive() {
02050     CDROM_Interface *cdrom=NULL;
02051 
02052     if (!GetMSCDEXDrive(drive_index,&cdrom))
02053         return NULL;
02054 
02055     return cdrom;
02056 }
02057 
02058 void IDEATAPICDROMDevice::update_from_cdrom() {
02059     CDROM_Interface *cdrom = getMSCDEXDrive();
02060     if (cdrom == NULL) {
02061         LOG_MSG("WARNING: IDE update from CD-ROM failed, disk not available\n");
02062         return;
02063     }
02064 }
02065 
02066 void IDEATADevice::update_from_biosdisk() {
02067     imageDisk *dsk = getBIOSdisk();
02068     if (dsk == NULL) {
02069         LOG_MSG("WARNING: IDE update from BIOS disk failed, disk not available\n");
02070         return;
02071     }
02072 
02073     headshr = 0;
02074     cyls = dsk->cylinders;
02075     heads = dsk->heads;
02076     sects = dsk->sectors;
02077 
02078     /* One additional correction: The disk image is probably using BIOS-style geometry
02079        translation (such as C/H/S 1024/64/63) which is impossible given that the IDE
02080        standard only allows up to 16 heads. So we have to translate the geometry. */
02081     while (heads > 16 && (heads & 1) == 0) {
02082         cyls <<= 1U;
02083         heads >>= 1U;
02084         headshr++;
02085     }
02086 
02087     /* If we can't divide the heads down, then pick a LBA-like mapping that is good enough.
02088      * Note that if what we pick does not evenly map to the INT 13h geometry, and the partition
02089      * contained within is not an LBA type FAT16/FAT32 partition, then Windows 95's IDE driver
02090      * will ignore this device and fall back to using INT 13h. For user convenience we will
02091      * print a warning to reminder the user of exactly that. */
02092     if (heads > 16) {
02093         unsigned long tmp;
02094 
02095         tmp = heads * cyls * sects;
02096         sects = 63;
02097         heads = 16;
02098         cyls = (tmp + ((63 * 16) - 1)) / (63 * 16);
02099         LOG_MSG("WARNING: Unable to reduce heads to 16 and below\n");
02100         LOG_MSG("If at all possible, please consider using INT 13h geometry with a head\n");
02101         LOG_MSG("cound that is easier to map to the BIOS, like 240 heads or 128 heads/track.\n");
02102         LOG_MSG("Some OSes, such as Windows 95, will not enable their 32-bit IDE driver if\n");
02103         LOG_MSG("a clean mapping does not exist between IDE and BIOS geometry.\n");
02104         LOG_MSG("Mapping BIOS DISK C/H/S %u/%u/%u as IDE %u/%u/%u (non-straightforward mapping)\n",
02105             (unsigned int)dsk->cylinders,
02106             (unsigned int)dsk->heads,
02107             (unsigned int)dsk->sectors,
02108             (unsigned int)cyls,
02109             (unsigned int)heads,
02110             (unsigned int)sects);
02111     }
02112     else {
02113         LOG_MSG("Mapping BIOS DISK C/H/S %u/%u/%u as IDE %u/%u/%u\n",
02114             (unsigned int)dsk->cylinders,
02115             (unsigned int)dsk->heads,
02116             (unsigned int)dsk->sectors,
02117             (unsigned int)cyls,
02118             (unsigned int)heads,
02119             (unsigned int)sects);
02120     }
02121 
02122     phys_heads = heads;
02123     phys_sects = sects;
02124     phys_cyls = cyls;
02125 }
02126 
02127 void IDE_Auto(signed char &index,bool &slave) {
02128     IDEController *c;
02129     unsigned int i;
02130 
02131     index = -1;
02132     slave = false;
02133     for (i=0;i < MAX_IDE_CONTROLLERS;i++) {
02134         if ((c=idecontroller[i]) == NULL) continue;
02135         index = (signed char)i;
02136 
02137         if (c->device[0] == NULL) {
02138             slave = false;
02139             break;
02140         }
02141         if (c->device[1] == NULL) {
02142             slave = true;
02143             break;
02144         }
02145     }
02146 }
02147 
02148 /* drive_index = drive letter 0...A to 25...Z */
02149 void IDE_ATAPI_MediaChangeNotify(unsigned char drive_index) {
02150     for (unsigned int ide=0;ide < MAX_IDE_CONTROLLERS;ide++) {
02151         IDEController *c = idecontroller[ide];
02152         if (c == NULL) continue;
02153         for (unsigned int ms=0;ms < 2;ms++) {
02154             IDEDevice *dev = c->device[ms];
02155             if (dev == NULL) continue;
02156             if (dev->type == IDE_TYPE_CDROM) {
02157                 IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
02158                 if (drive_index == atapi->drive_index) {
02159                     LOG_MSG("IDE ATAPI acknowledge media change for drive %c\n",drive_index+'A');
02160                     atapi->has_changed = true;
02161                     atapi->loading_mode = LOAD_INSERT_CD;
02162                     PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,c->interface_index);
02163                     PIC_RemoveSpecificEvents(IDE_ATAPI_SpinUpComplete,c->interface_index);
02164                     PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,c->interface_index);
02165                     PIC_AddEvent(IDE_ATAPI_CDInsertion,atapi->cd_insertion_time/*ms*/,c->interface_index);
02166                 }
02167             }
02168         }
02169     }
02170 }
02171 
02172 /* drive_index = drive letter 0...A to 25...Z */
02173 void IDE_CDROM_Attach(signed char index,bool slave,unsigned char drive_index) {
02174     IDEController *c;
02175     IDEATAPICDROMDevice *dev;
02176 
02177     if (index < 0 || index >= MAX_IDE_CONTROLLERS) return;
02178     c = idecontroller[index];
02179     if (c == NULL) return;
02180 
02181     if (c->device[slave?1:0] != NULL) {
02182         LOG_MSG("IDE: Controller %u %s already taken\n",index,slave?"slave":"master");
02183         return;
02184     }
02185 
02186     if (!GetMSCDEXDrive(drive_index,NULL)) {
02187         LOG_MSG("IDE: Asked to attach CD-ROM that does not exist\n");
02188         return;
02189     }
02190 
02191     dev = new IDEATAPICDROMDevice(c,drive_index);
02192     if (dev == NULL) return;
02193     dev->update_from_cdrom();
02194     c->device[slave?1:0] = (IDEDevice*)dev;
02195 }
02196 
02197 /* drive_index = drive letter 0...A to 25...Z */
02198 void IDE_CDROM_Detach(unsigned char drive_index) {
02199     for (int index = 0; index < MAX_IDE_CONTROLLERS; index++) {
02200         IDEController *c = idecontroller[index];
02201         if (c)
02202         for (int slave = 0; slave < 2; slave++) {
02203             IDEATAPICDROMDevice *dev;
02204             dev = dynamic_cast<IDEATAPICDROMDevice*>(c->device[slave]);
02205             if (dev && dev->drive_index == drive_index) {
02206                 delete dev;
02207                 c->device[slave] = NULL;
02208             }
02209         }
02210     }
02211 }
02212 
02213 /* bios_disk_index = index into BIOS INT 13h disk array: imageDisk *imageDiskList[MAX_DISK_IMAGES]; */
02214 void IDE_Hard_Disk_Attach(signed char index,bool slave,unsigned char bios_disk_index/*not INT13h, the index into DOSBox's BIOS drive emulation*/) {
02215     IDEController *c;
02216     IDEATADevice *dev;
02217 
02218     if (index < 0 || index >= MAX_IDE_CONTROLLERS) return;
02219     c = idecontroller[index];
02220     if (c == NULL) return;
02221 
02222     if (c->device[slave?1:0] != NULL) {
02223         LOG_MSG("IDE: Controller %u %s already taken\n",index,slave?"slave":"master");
02224         return;
02225     }
02226 
02227     if (imageDiskList[bios_disk_index] == NULL) {
02228         LOG_MSG("IDE: Asked to attach bios disk that does not exist\n");
02229         return;
02230     }
02231 
02232     dev = new IDEATADevice(c,bios_disk_index);
02233     if (dev == NULL) return;
02234     dev->update_from_biosdisk();
02235     c->device[slave?1:0] = (IDEDevice*)dev;
02236 }
02237 
02238 /* bios_disk_index = index into BIOS INT 13h disk array: imageDisk *imageDiskList[MAX_DISK_IMAGES]; */
02239 void IDE_Hard_Disk_Detach(unsigned char bios_disk_index) {
02240     for (int index = 0; index < MAX_IDE_CONTROLLERS; index++) {
02241         IDEController *c = idecontroller[index];
02242         if (c)
02243         for (int slave = 0; slave < 2; slave++) {
02244             IDEATADevice *dev;
02245             dev = dynamic_cast<IDEATADevice*>(c->device[slave]);
02246             if (dev && dev->bios_disk_index == bios_disk_index) {
02247                 delete dev;
02248                 c->device[slave] = NULL;
02249             }
02250         }
02251     }
02252 }
02253 static IDEController* GetIDEController(Bitu idx) {
02254     if (idx >= MAX_IDE_CONTROLLERS) return NULL;
02255     return idecontroller[idx];
02256 }
02257 
02258 static IDEDevice* GetIDESelectedDevice(IDEController *ide) {
02259     if (ide == NULL) return NULL;
02260     return ide->device[ide->select];
02261 }
02262 
02263 static bool IDE_CPU_Is_Vm86() {
02264     return (cpu.pmode && ((GETFLAG_IOPL<cpu.cpl) || GETFLAG(VM)));
02265 }
02266 
02267 static void ide_baseio_w(Bitu port,Bitu val,Bitu iolen);
02268 
02269 static Bitu IDE_SelfIO_In(IDEController *ide,Bitu port,Bitu len) {
02270     if (ide->int13fakev86io && IDE_CPU_Is_Vm86()) {
02271         /* Trigger I/O in virtual 8086 mode, where the OS can trap it and act on it.
02272          * Windows 95 uses V86 traps to help "autodetect" what IDE drive and port the
02273          * BIOS uses on INT 13h so that it's internal IDE driver can take over, which
02274          * is the whole reason for this hack. */
02275         return CPU_ForceV86FakeIO_In(port,len);
02276     }
02277     else {
02278         return ide_baseio_r(port,len);
02279     }
02280 }
02281 
02282 static void IDE_SelfIO_Out(IDEController *ide,Bitu port,Bitu val,Bitu len) {
02283     if (ide->int13fakev86io && IDE_CPU_Is_Vm86()) {
02284         /* Trigger I/O in virtual 8086 mode, where the OS can trap it and act on it.
02285          * Windows 95 uses V86 traps to help "autodetect" what IDE drive and port the
02286          * BIOS uses on INT 13h so that it's internal IDE driver can take over, which
02287          * is the whole reason for this hack. */
02288         CPU_ForceV86FakeIO_Out(port,val,len);
02289     }
02290     else {
02291         ide_baseio_w(port,val,len);
02292     }
02293 }
02294 
02295 /* INT 13h extensions */
02296 void IDE_EmuINT13DiskReadByBIOS_LBA(unsigned char disk,uint64_t lba) {
02297     IDEController *ide;
02298     IDEDevice *dev;
02299     Bitu idx,ms;
02300 
02301     if (disk < 0x80) return;
02302     if (lba >= (1ULL << 28ULL)) return; /* this code does not support LBA48 */
02303 
02304     for (idx=0;idx < MAX_IDE_CONTROLLERS;idx++) {
02305         ide = GetIDEController(idx);
02306         if (ide == NULL) continue;
02307         if (!ide->int13fakeio && !ide->int13fakev86io) continue;
02308 
02309         /* TODO: Print a warning message if the IDE controller is busy (debug/warning message) */
02310 
02311         /* TODO: Force IDE state to readiness, abort command, etc. */
02312 
02313         /* for master/slave device... */
02314         for (ms=0;ms < 2;ms++) {
02315             dev = ide->device[ms];
02316             if (dev == NULL) continue;
02317 
02318             /* TODO: Print a warning message if the IDE device is busy or in the middle of a command */
02319 
02320             /* TODO: Forcibly device-reset the IDE device */
02321 
02322             /* Issue I/O to ourself to select drive */
02323             dev->faked_command = true;
02324             IDE_SelfIO_In(ide,ide->base_io+7u,1);
02325             IDE_SelfIO_Out(ide,ide->base_io+6u,0x00+(ms<<4u),1);
02326             dev->faked_command = false;
02327 
02328             if (dev->type == IDE_TYPE_HDD) {
02329                 IDEATADevice *ata = (IDEATADevice*)dev;
02330                 static bool vm86_warned = false;
02331 //              static bool int13_fix_wrap_warned = false;
02332                 bool vm86 = IDE_CPU_Is_Vm86();
02333 
02334                 if ((ata->bios_disk_index-2) == (disk-0x80)) {
02335 //                  imageDisk *dsk = ata->getBIOSdisk();
02336 
02337                     if (ide->int13fakev86io && vm86) {
02338                         dev->faked_command = true;
02339 
02340                         /* we MUST clear interrupts.
02341                          * leaving them enabled causes Win95 (or DOSBox?) to recursively
02342                          * pagefault and DOSBox to crash. In any case it seems Win95's
02343                          * IDE driver assumes the BIOS INT 13h code will do this since
02344                          * it's customary for the BIOS to do it at some point, usually
02345                          * just before reading the sector data. */
02346                         CPU_CLI();
02347 
02348                         /* We're in virtual 8086 mode and we're asked to fake I/O as if
02349                          * executing a BIOS subroutine. Some OS's like Windows 95 rely on
02350                          * executing INT 13h in virtual 8086 mode: on startup, the ESDI
02351                          * driver traps IDE ports and then executes INT 13h to watch what
02352                          * I/O ports it uses. It then uses that information to decide
02353                          * what IDE hard disk and controller corresponds to what DOS
02354                          * drive. So to get 32-bit disk access to work in Windows 95,
02355                          * we have to put on a good show to convince Windows 95 we're
02356                          * a legitimate BIOS INT 13h call doing it's job. */
02357                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02358                         IDE_SelfIO_Out(ide,ide->base_io+6u,(ms<<4u)+0xE0u+(lba>>24u),1); /* drive and head */
02359                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02360                         IDE_SelfIO_Out(ide,ide->base_io+2u,0x01,1);  /* sector count */
02361                         IDE_SelfIO_Out(ide,ide->base_io+3u,lba&0xFF,1);  /* sector number */
02362                         IDE_SelfIO_Out(ide,ide->base_io+4u,(lba>>8u)&0xFF,1); /* cylinder lo */
02363                         IDE_SelfIO_Out(ide,ide->base_io+5u,(lba>>16u)&0xFF,1); /* cylinder hi */
02364                         IDE_SelfIO_Out(ide,ide->base_io+6u,(ms<<4u)+0xE0+(lba>>24u),1); /* drive and head */
02365                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02366                         IDE_SelfIO_Out(ide,ide->base_io+7u,0x20,1);  /* issue READ */
02367 
02368                         do {
02369                             /* TODO: Timeout needed */
02370                             unsigned int i = IDE_SelfIO_In(ide,ide->alt_io,1);
02371                             if ((i&0x80) == 0) break;
02372                         } while (1);
02373                         IDE_SelfIO_In(ide,ide->base_io+7u,1);
02374 
02375                         /* for brevity assume it worked. we're here to bullshit Windows 95 after all */
02376                         for (unsigned int i=0;i < 256;i++)
02377                             IDE_SelfIO_In(ide,ide->base_io+0u,2); /* 16-bit IDE data read */
02378 
02379                         /* one more */
02380                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02381 
02382                         /* assume IRQ happened and clear it */
02383                         if (ide->IRQ >= 8)
02384                             IDE_SelfIO_Out(ide,0xA0,0x60u+(unsigned int)ide->IRQ-8u,1);     /* specific EOI */
02385                         else
02386                             IDE_SelfIO_Out(ide,0x20,0x60u+(unsigned int)ide->IRQ,1);       /* specific EOI */
02387 
02388                         ata->abort_normal();
02389                         dev->faked_command = false;
02390                     }
02391                     else {
02392                         /* hack IDE state as if a BIOS executing IDE disk routines.
02393                          * This is required if we want IDE emulation to work with Windows 3.11 Windows for Workgroups 32-bit disk access (WDCTRL),
02394                          * because the driver "tests" the controller by issuing INT 13h calls then reading back IDE registers to see if
02395                          * they match the C/H/S it requested */
02396                         dev->feature = 0x00;        /* clear error (WDCTRL test phase 5/C/13) */
02397                         dev->count = 0x00;      /* clear sector count (WDCTRL test phase 6/D/14) */
02398                         dev->lba[0] = lba&0xFF;     /* leave sector number the same (WDCTRL test phase 7/E/15) */
02399                         dev->lba[1] = (lba>>8u)&0xFF;    /* leave cylinder the same (WDCTRL test phase 8/F/16) */
02400                         dev->lba[2] = (lba>>16u)&0xFF;   /* ...ditto */
02401                         ide->drivehead = dev->drivehead = 0xE0u | (ms<<4u) | (lba>>24u); /* drive head and master/slave (WDCTRL test phase 9/10/17) */
02402                         dev->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE; /* status (WDCTRL test phase A/11/18) */
02403                         dev->allow_writing = true;
02404 
02405                         if (vm86 && !vm86_warned) {
02406                             LOG_MSG("IDE warning: INT 13h extensions read from virtual 8086 mode.\n");
02407                             LOG_MSG("             If using Windows 95 OSR2, please set int13fakev86io=true for proper 32-bit disk access\n");
02408                             vm86_warned = true;
02409                         }
02410                     }
02411 
02412                     /* break out, we're done */
02413                     idx = MAX_IDE_CONTROLLERS;
02414                     break;
02415                 }
02416             }
02417         }
02418     }
02419 }
02420 
02421 /* this is called after INT 13h AH=0x02 READ DISK to change IDE state to simulate the BIOS in action.
02422  * this is needed for old "32-bit disk drivers" like WDCTRL in Windows 3.11 Windows for Workgroups,
02423  * which issues INT 13h to read-test and then reads IDE registers to see if they match expectations */
02424 void IDE_EmuINT13DiskReadByBIOS(unsigned char disk,unsigned int cyl,unsigned int head,unsigned sect) {
02425     IDEController *ide;
02426     IDEDevice *dev;
02427     Bitu idx,ms;
02428 
02429     if (disk < 0x80) return;
02430 
02431     for (idx=0;idx < MAX_IDE_CONTROLLERS;idx++) {
02432         ide = GetIDEController(idx);
02433         if (ide == NULL) continue;
02434         if (!ide->int13fakeio && !ide->int13fakev86io) continue;
02435 
02436         /* TODO: Print a warning message if the IDE controller is busy (debug/warning message) */
02437 
02438         /* TODO: Force IDE state to readiness, abort command, etc. */
02439 
02440         /* for master/slave device... */
02441         for (ms=0;ms < 2;ms++) {
02442             dev = ide->device[ms];
02443             if (dev == NULL) continue;
02444 
02445             /* TODO: Print a warning message if the IDE device is busy or in the middle of a command */
02446 
02447             /* TODO: Forcibly device-reset the IDE device */
02448 
02449             /* Issue I/O to ourself to select drive */
02450             dev->faked_command = true;
02451             IDE_SelfIO_In(ide,ide->base_io+7u,1);
02452             IDE_SelfIO_Out(ide,ide->base_io+6u,0x00u+(ms<<4u),1);
02453             dev->faked_command = false;
02454 
02455             if (dev->type == IDE_TYPE_HDD) {
02456                 IDEATADevice *ata = (IDEATADevice*)dev;
02457                 static bool vm86_warned = false;
02458                 static bool int13_fix_wrap_warned = false;
02459                 bool vm86 = IDE_CPU_Is_Vm86();
02460 
02461                 if ((ata->bios_disk_index-2) == (disk-0x80)) {
02462                     imageDisk *dsk = ata->getBIOSdisk();
02463 
02464                     /* print warning if INT 13h is being called after the OS changed logical geometry */
02465                     if (ata->sects != ata->phys_sects || ata->heads != ata->phys_heads || ata->cyls != ata->phys_cyls)
02466                         LOG_MSG("INT 13 WARNING: I/O issued on drive attached to IDE emulation with changed logical geometry!\n");
02467 
02468                     /* HACK: src/ints/bios_disk.cpp implementation doesn't correctly
02469                      *       wrap sector numbers across tracks. it fullfills the read
02470                      *       by counting sectors and reading from C,H,S+i which means
02471                      *       that if the OS assumes the ability to read across track
02472                      *       boundaries (as Windows 95 does) we will get invalid
02473                      *       sector numbers, which in turn fouls up our emulation.
02474                      *
02475                      *       Windows 95 OSR2 for example, will happily ask for 63
02476                      *       sectors starting at C/H/S 30/9/42 without regard for
02477                      *       track boundaries. */
02478                     if (sect > dsk->sectors) {
02479                         if (!int13_fix_wrap_warned) {
02480                             LOG_MSG("INT 13h implementation warning: we were given over-large sector number.\n");
02481                             LOG_MSG("This is normally the fault of DOSBox INT 13h emulation that counts sectors\n");
02482                             LOG_MSG("without consideration of track boundaries\n");
02483                             int13_fix_wrap_warned = true;
02484                         }
02485 
02486                         do {
02487                             sect -= dsk->sectors;
02488                             if ((++head) >= dsk->heads) {
02489                                 head -= dsk->heads;
02490                                 cyl++;
02491                             }
02492                         } while (sect > dsk->sectors);
02493                     }
02494 
02495                     /* translate BIOS INT 13h geometry to IDE geometry */
02496                     if (ata->headshr != 0) {
02497                         unsigned long lba;
02498 
02499                         if (dsk == NULL) return;
02500                         lba = (head * dsk->sectors) + (cyl * dsk->sectors * dsk->heads) + sect - 1;
02501                         sect = (lba % ata->sects) + 1;
02502                         head = (lba / ata->sects) % ata->heads;
02503                         cyl = (lba / ata->sects / ata->heads);
02504                     }
02505 
02506                     if (ide->int13fakev86io && vm86) {
02507                         dev->faked_command = true;
02508 
02509                         /* we MUST clear interrupts.
02510                          * leaving them enabled causes Win95 (or DOSBox?) to recursively
02511                          * pagefault and DOSBox to crash. In any case it seems Win95's
02512                          * IDE driver assumes the BIOS INT 13h code will do this since
02513                          * it's customary for the BIOS to do it at some point, usually
02514                          * just before reading the sector data. */
02515                         CPU_CLI();
02516 
02517                         /* We're in virtual 8086 mode and we're asked to fake I/O as if
02518                          * executing a BIOS subroutine. Some OS's like Windows 95 rely on
02519                          * executing INT 13h in virtual 8086 mode: on startup, the ESDI
02520                          * driver traps IDE ports and then executes INT 13h to watch what
02521                          * I/O ports it uses. It then uses that information to decide
02522                          * what IDE hard disk and controller corresponds to what DOS
02523                          * drive. So to get 32-bit disk access to work in Windows 95,
02524                          * we have to put on a good show to convince Windows 95 we're
02525                          * a legitimate BIOS INT 13h call doing it's job. */
02526                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02527                         IDE_SelfIO_Out(ide,ide->base_io+6u,(ms<<4u)+0xA0u+head,1); /* drive and head */
02528                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02529                         IDE_SelfIO_Out(ide,ide->base_io+2u,0x01,1);  /* sector count */
02530                         IDE_SelfIO_Out(ide,ide->base_io+3u,sect,1);  /* sector number */
02531                         IDE_SelfIO_Out(ide,ide->base_io+4u,cyl&0xFF,1);  /* cylinder lo */
02532                         IDE_SelfIO_Out(ide,ide->base_io+5u,(cyl>>8u)&0xFF,1); /* cylinder hi */
02533                         IDE_SelfIO_Out(ide,ide->base_io+6u,(ms<<4u)+0xA0u+head,1); /* drive and head */
02534                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02535                         IDE_SelfIO_Out(ide,ide->base_io+7u,0x20u,1);  /* issue READ */
02536 
02537                         do {
02538                             /* TODO: Timeout needed */
02539                             unsigned int i = IDE_SelfIO_In(ide,ide->alt_io,1);
02540                             if ((i&0x80) == 0) break;
02541                         } while (1);
02542                         IDE_SelfIO_In(ide,ide->base_io+7u,1);
02543 
02544                         /* for brevity assume it worked. we're here to bullshit Windows 95 after all */
02545                         for (unsigned int i=0;i < 256;i++)
02546                             IDE_SelfIO_In(ide,ide->base_io+0,2); /* 16-bit IDE data read */
02547 
02548                         /* one more */
02549                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02550 
02551                         /* assume IRQ happened and clear it */
02552                         if (ide->IRQ >= 8)
02553                             IDE_SelfIO_Out(ide,0xA0,0x60u+(unsigned int)ide->IRQ-8u,1);     /* specific EOI */
02554                         else
02555                             IDE_SelfIO_Out(ide,0x20,0x60u+(unsigned int)ide->IRQ,1);       /* specific EOI */
02556 
02557                         ata->abort_normal();
02558                         dev->faked_command = false;
02559                     }
02560                     else {
02561                         /* hack IDE state as if a BIOS executing IDE disk routines.
02562                          * This is required if we want IDE emulation to work with Windows 3.11 Windows for Workgroups 32-bit disk access (WDCTRL),
02563                          * because the driver "tests" the controller by issuing INT 13h calls then reading back IDE registers to see if
02564                          * they match the C/H/S it requested */
02565                         dev->feature = 0x00;        /* clear error (WDCTRL test phase 5/C/13) */
02566                         dev->count = 0x00;      /* clear sector count (WDCTRL test phase 6/D/14) */
02567                         dev->lba[0] = sect;     /* leave sector number the same (WDCTRL test phase 7/E/15) */
02568                         dev->lba[1] = cyl;      /* leave cylinder the same (WDCTRL test phase 8/F/16) */
02569                         dev->lba[2] = cyl >> 8u;     /* ...ditto */
02570                         ide->drivehead = dev->drivehead = 0xA0u | (ms<<4u) | head; /* drive head and master/slave (WDCTRL test phase 9/10/17) */
02571                         dev->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE; /* status (WDCTRL test phase A/11/18) */
02572                         dev->allow_writing = true;
02573 
02574                         if (vm86 && !vm86_warned) {
02575                             LOG_MSG("IDE warning: INT 13h read from virtual 8086 mode.\n");
02576                             LOG_MSG("             If using Windows 95, please set int13fakev86io=true for proper 32-bit disk access\n");
02577                             vm86_warned = true;
02578                         }
02579                     }
02580 
02581                     /* break out, we're done */
02582                     idx = MAX_IDE_CONTROLLERS;
02583                     break;
02584                 }
02585             }
02586         }
02587     }
02588 }
02589 
02590 /* this is called by src/ints/bios_disk.cpp whenever INT 13h AH=0x00 is called on a hard disk.
02591  * this gives us a chance to update IDE state as if the BIOS had gone through with a full disk reset as requested. */
02592 void IDE_ResetDiskByBIOS(unsigned char disk) {
02593     IDEController *ide;
02594     IDEDevice *dev;
02595     Bitu idx,ms;
02596 
02597     if (disk < 0x80) return;
02598 
02599     for (idx=0;idx < MAX_IDE_CONTROLLERS;idx++) {
02600         ide = GetIDEController(idx);
02601         if (ide == NULL) continue;
02602         if (!ide->int13fakeio && !ide->int13fakev86io) continue;
02603 
02604         /* TODO: Print a warning message if the IDE controller is busy (debug/warning message) */
02605 
02606         /* TODO: Force IDE state to readiness, abort command, etc. */
02607 
02608         /* for master/slave device... */
02609         for (ms=0;ms < 2;ms++) {
02610             dev = ide->device[ms];
02611             if (dev == NULL) continue;
02612 
02613             /* TODO: Print a warning message if the IDE device is busy or in the middle of a command */
02614 
02615             /* TODO: Forcibly device-reset the IDE device */
02616 
02617             /* Issue I/O to ourself to select drive */
02618             IDE_SelfIO_In(ide,ide->base_io+7u,1);
02619             IDE_SelfIO_Out(ide,ide->base_io+6u,0x00+(ms<<4u),1);
02620 
02621             /* TODO: Forcibly device-reset the IDE device */
02622 
02623             if (dev->type == IDE_TYPE_HDD) {
02624                 IDEATADevice *ata = (IDEATADevice*)dev;
02625 
02626                 if ((ata->bios_disk_index-2) == (disk-0x80)) {
02627                     LOG_MSG("IDE %d%c reset by BIOS disk 0x%02x\n",
02628                         (unsigned int)(idx+1),
02629                         ms?'s':'m',
02630                         (unsigned int)disk);
02631 
02632                     if (ide->int13fakev86io && IDE_CPU_Is_Vm86()) {
02633                         /* issue the DEVICE RESET command */
02634                         IDE_SelfIO_In(ide,ide->base_io+7u,1);
02635                         IDE_SelfIO_Out(ide,ide->base_io+7u,0x08,1);
02636 
02637                         IDE_SelfIO_In(ide,ide->base_io+7u,1);
02638 
02639                         /* assume IRQ happened and clear it */
02640                         if (ide->IRQ >= 8)
02641                             IDE_SelfIO_Out(ide,0xA0,0x60u+(unsigned int)ide->IRQ-8u,1);     /* specific EOI */
02642                         else
02643                             IDE_SelfIO_Out(ide,0x20,0x60u+(unsigned int)ide->IRQ,1);       /* specific EOI */
02644                     }
02645                     else {
02646                         /* Windows 3.1 WDCTRL needs this, or else, it will read the
02647                          * status register and see something other than DRIVE_READY|SEEK_COMPLETE */
02648                         dev->writecommand(0x08);
02649 
02650                         /* and then immediately clear the IRQ */
02651                         ide->lower_irq();
02652                     }
02653                 }
02654             }
02655         }
02656     }
02657 }
02658 
02659 static void IDE_DelayedCommand(Bitu idx/*which IDE controller*/) {
02660     IDEDevice *dev = GetIDESelectedDevice(GetIDEController(idx));
02661     if (dev == NULL) return;
02662 
02663     if (dev->type == IDE_TYPE_HDD) {
02664         IDEATADevice *ata = (IDEATADevice*)dev;
02665         uint32_t sectorn = 0;/* FIXME: expand to uint64_t when adding LBA48 emulation */
02666         unsigned int sectcount;
02667         imageDisk *disk;
02668 //      int i;
02669 
02670         switch (dev->command) {
02671             case 0x30:/* WRITE SECTOR */
02672                 disk = ata->getBIOSdisk();
02673                 if (disk == NULL) {
02674                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02675                     ata->abort_error();
02676                     dev->controller->raise_irq();
02677                     return;
02678                 }
02679 
02680                 sectcount = ata->count & 0xFF;
02681                 if (sectcount == 0) sectcount = 256;
02682                 if (drivehead_is_lba(ata->drivehead)) {
02683                     /* LBA */
02684                     sectorn = ((ata->drivehead & 0xFu) << 24u) | (unsigned int)ata->lba[0] |
02685                         ((unsigned int)ata->lba[1] << 8u) |
02686                         ((unsigned int)ata->lba[2] << 16u);
02687                 }
02688                 else {
02689                     /* C/H/S */
02690                     if (ata->lba[0] == 0) {
02691                         LOG_MSG("ATA sector 0 does not exist\n");
02692                         ata->abort_error();
02693                         dev->controller->raise_irq();
02694                         return;
02695                     }
02696                     else if ((unsigned int)(ata->drivehead & 0xFu) >= (unsigned int)ata->heads ||
02697                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02698                         (unsigned int)(ata->lba[1] | (ata->lba[2] << 8u)) >= (unsigned int)ata->cyls) {
02699                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02700                             (unsigned int)(ata->lba[1] | (ata->lba[2] << 8u)),
02701                             (unsigned int)(ata->drivehead&0xFu),
02702                             (unsigned int)(ata->lba[0]),
02703                             (unsigned int)ata->cyls,
02704                             (unsigned int)ata->heads,
02705                             (unsigned int)ata->sects);
02706                         ata->abort_error();
02707                         dev->controller->raise_irq();
02708                         return;
02709                     }
02710 
02711                     sectorn = ((ata->drivehead & 0xF) * ata->sects) +
02712                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) * ata->sects * ata->heads) +
02713                         ((unsigned int)ata->lba[0] - 1u);
02714                 }
02715 
02716                 if (disk->Write_AbsoluteSector(sectorn, ata->sector) != 0) {
02717                     LOG_MSG("Failed to write sector\n");
02718                     ata->abort_error();
02719                     dev->controller->raise_irq();
02720                     return;
02721                 }
02722 
02723                 /* NTS: the way this command works is that the drive writes ONE sector, then fires the IRQ
02724                         and lets the host read it, then reads another sector, fires the IRQ, etc. One
02725                     IRQ signal per sector. We emulate that here by adding another event to trigger this
02726                     call unless the sector count has just dwindled to zero, then we let it stop. */
02727                 if ((ata->count&0xFF) == 1) {
02728                     /* end of the transfer */
02729                     ata->count = 0;
02730                     ata->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02731                     dev->controller->raise_irq();
02732                     ata->state = IDE_DEV_READY;
02733                     ata->allow_writing = true;
02734                     return;
02735                 }
02736                 else if ((ata->count&0xFF) == 0) ata->count = 255;
02737                 else ata->count--;
02738                 ata->progress_count++;
02739 
02740                 if (!ata->increment_current_address()) {
02741                     LOG_MSG("READ advance error\n");
02742                     ata->abort_error();
02743                     return;
02744                 }
02745 
02746                 /* begin another sector */
02747                 dev->state = IDE_DEV_DATA_WRITE;
02748                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02749                 ata->prepare_write(0,512);
02750                 dev->controller->raise_irq();
02751                 break;
02752 
02753             case 0x20:/* READ SECTOR */
02754                 disk = ata->getBIOSdisk();
02755                 if (disk == NULL) {
02756                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02757                     ata->abort_error();
02758                     dev->controller->raise_irq();
02759                     return;
02760                 }
02761 
02762                 sectcount = ata->count & 0xFF;
02763                 if (sectcount == 0) sectcount = 256;
02764                 if (drivehead_is_lba(ata->drivehead)) {
02765                     /* LBA */
02766                     sectorn = (((unsigned int)ata->drivehead & 0xFu) << 24u) | (unsigned int)ata->lba[0] |
02767                         ((unsigned int)ata->lba[1] << 8u) |
02768                         ((unsigned int)ata->lba[2] << 16u);
02769                 }
02770                 else {
02771                     /* C/H/S */
02772                     if (ata->lba[0] == 0) {
02773                         LOG_MSG("WARNING C/H/S access mode and sector==0\n");
02774                         ata->abort_error();
02775                         dev->controller->raise_irq();
02776                         return;
02777                     }
02778                     else if ((unsigned int)(ata->drivehead & 0xF) >= (unsigned int)ata->heads ||
02779                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02780                         (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) >= (unsigned int)ata->cyls) {
02781                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02782                             (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)),
02783                             (unsigned int)(ata->drivehead&0xF),
02784                             (unsigned int)ata->lba[0],
02785                             (unsigned int)ata->cyls,
02786                             (unsigned int)ata->heads,
02787                             (unsigned int)ata->sects);
02788                         ata->abort_error();
02789                         dev->controller->raise_irq();
02790                         return;
02791                     }
02792 
02793                     sectorn = ((ata->drivehead & 0xFu) * ata->sects) +
02794                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) * ata->sects * ata->heads) +
02795                         ((unsigned int)ata->lba[0] - 1u);
02796                 }
02797 
02798                 if (disk->Read_AbsoluteSector(sectorn, ata->sector) != 0) {
02799                     LOG_MSG("ATA read failed\n");
02800                     ata->abort_error();
02801                     dev->controller->raise_irq();
02802                     return;
02803                 }
02804 
02805                 /* NTS: the way this command works is that the drive reads ONE sector, then fires the IRQ
02806                         and lets the host read it, then reads another sector, fires the IRQ, etc. One
02807                     IRQ signal per sector. We emulate that here by adding another event to trigger this
02808                     call unless the sector count has just dwindled to zero, then we let it stop. */
02809                 /* NTS: The sector advance + count decrement is done in the I/O completion function */
02810                 dev->state = IDE_DEV_DATA_READ;
02811                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02812                 ata->prepare_read(0,512);
02813                 dev->controller->raise_irq();
02814                 break;
02815 
02816             case 0x40:/* READ SECTOR VERIFY WITH RETRY */
02817             case 0x41: /* READ SECTOR VERIFY WITHOUT RETRY */
02818                 disk = ata->getBIOSdisk();
02819                 if (disk == NULL) {
02820                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02821                     ata->abort_error();
02822                     dev->controller->raise_irq();
02823                     return;
02824                 }
02825 
02826                 sectcount = ata->count & 0xFF;
02827                 if (sectcount == 0) sectcount = 256;
02828                 if (drivehead_is_lba(ata->drivehead)) {
02829                     /* LBA */
02830                     sectorn = (((unsigned int)ata->drivehead & 0xFu) << 24u) | (unsigned int)ata->lba[0] |
02831                         ((unsigned int)ata->lba[1] << 8u) |
02832                         ((unsigned int)ata->lba[2] << 16u);
02833                 }
02834                 else {
02835                     /* C/H/S */
02836                     if (ata->lba[0] == 0) {
02837                         LOG_MSG("WARNING C/H/S access mode and sector==0\n");
02838                         ata->abort_error();
02839                         dev->controller->raise_irq();
02840                         return;
02841                     }
02842                     else if ((unsigned int)(ata->drivehead & 0xF) >= (unsigned int)ata->heads ||
02843                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02844                         (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) >= (unsigned int)ata->cyls) {
02845                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02846                             (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)),
02847                             (unsigned int)(ata->drivehead&0xFu),
02848                             (unsigned int)ata->lba[0],
02849                             (unsigned int)ata->cyls,
02850                             (unsigned int)ata->heads,
02851                             (unsigned int)ata->sects);
02852                         ata->abort_error();
02853                         dev->controller->raise_irq();
02854                         return;
02855                     }
02856 
02857                     sectorn = (((unsigned int)ata->drivehead & 0xFu) * ata->sects) +
02858                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) * ata->sects * ata->heads) +
02859                         ((unsigned int)ata->lba[0] - 1u);
02860                 }
02861 
02862                 if (disk->Read_AbsoluteSector(sectorn, ata->sector) != 0) {
02863                     LOG_MSG("ATA read failed\n");
02864                     ata->abort_error();
02865                     dev->controller->raise_irq();
02866                     return;
02867                 }
02868 
02869                 if ((ata->count&0xFF) == 1) {
02870                     /* end of the transfer */
02871                     ata->count = 0;
02872                     ata->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02873                     dev->controller->raise_irq();
02874                     ata->state = IDE_DEV_READY;
02875                     ata->allow_writing = true;
02876                     return;
02877                 }
02878                 else if ((ata->count&0xFF) == 0) ata->count = 255;
02879                 else ata->count--;
02880                 ata->progress_count++;
02881 
02882                 if (!ata->increment_current_address()) {
02883                     LOG_MSG("READ advance error\n");
02884                     ata->abort_error();
02885                     return;
02886                 }
02887 
02888                 ata->state = IDE_DEV_BUSY;
02889                 ata->status = IDE_STATUS_BUSY;
02890                 PIC_AddEvent(IDE_DelayedCommand,0.00001/*ms*/,dev->controller->interface_index);
02891                 break;
02892 
02893             case 0xC4:/* READ MULTIPLE */
02894                 disk = ata->getBIOSdisk();
02895                 if (disk == NULL) {
02896                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02897                     ata->abort_error();
02898                     dev->controller->raise_irq();
02899                     return;
02900                 }
02901 
02902                 sectcount = ata->count & 0xFF;
02903                 if (sectcount == 0) sectcount = 256;
02904                 if (drivehead_is_lba(ata->drivehead)) {
02905                     /* LBA */
02906                     sectorn = (((unsigned int)ata->drivehead & 0xFu) << 24u) | (unsigned int)ata->lba[0] |
02907                         ((unsigned int)ata->lba[1] << 8u) |
02908                         ((unsigned int)ata->lba[2] << 16u);
02909                 }
02910                 else {
02911                     /* C/H/S */
02912                     if (ata->lba[0] == 0) {
02913                         LOG_MSG("WARNING C/H/S access mode and sector==0\n");
02914                         ata->abort_error();
02915                         dev->controller->raise_irq();
02916                         return;
02917                     }
02918                     else if ((unsigned int)(ata->drivehead & 0xF) >= (unsigned int)ata->heads ||
02919                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02920                         (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) >= (unsigned int)ata->cyls) {
02921                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02922                             (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)),
02923                             (unsigned int)(ata->drivehead&0xF),
02924                             (unsigned int)ata->lba[0],
02925                             (unsigned int)ata->cyls,
02926                             (unsigned int)ata->heads,
02927                             (unsigned int)ata->sects);
02928                         ata->abort_error();
02929                         dev->controller->raise_irq();
02930                         return;
02931                     }
02932 
02933                     sectorn = ((ata->drivehead & 0xF) * ata->sects) +
02934                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) * ata->sects * ata->heads) +
02935                         ((unsigned int)ata->lba[0] - 1);
02936                 }
02937 
02938                 if ((512*ata->multiple_sector_count) > sizeof(ata->sector))
02939                     E_Exit("SECTOR OVERFLOW");
02940 
02941                 for (unsigned int cc=0;cc < MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount);cc++) {
02942                     /* it would be great if the disk object had a "read multiple sectors" member function */
02943                     if (disk->Read_AbsoluteSector(sectorn+cc, ata->sector+(cc*512)) != 0) {
02944                         LOG_MSG("ATA read failed\n");
02945                         ata->abort_error();
02946                         dev->controller->raise_irq();
02947                         return;
02948                     }
02949                 }
02950 
02951                 /* NTS: the way this command works is that the drive reads ONE sector, then fires the IRQ
02952                         and lets the host read it, then reads another sector, fires the IRQ, etc. One
02953                     IRQ signal per sector. We emulate that here by adding another event to trigger this
02954                     call unless the sector count has just dwindled to zero, then we let it stop. */
02955                 /* NTS: The sector advance + count decrement is done in the I/O completion function */
02956                 dev->state = IDE_DEV_DATA_READ;
02957                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02958                 ata->prepare_read(0,512*MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount));
02959                 dev->controller->raise_irq();
02960                 break;
02961 
02962             case 0xC5:/* WRITE MULTIPLE */
02963                 disk = ata->getBIOSdisk();
02964                 if (disk == NULL) {
02965                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02966                     ata->abort_error();
02967                     dev->controller->raise_irq();
02968                     return;
02969                 }
02970 
02971                 sectcount = ata->count & 0xFF;
02972                 if (sectcount == 0) sectcount = 256;
02973                 if (drivehead_is_lba(ata->drivehead)) {
02974                     /* LBA */
02975                     sectorn = (((unsigned int)ata->drivehead & 0xF) << 24) | (unsigned int)ata->lba[0] |
02976                         ((unsigned int)ata->lba[1] << 8) |
02977                         ((unsigned int)ata->lba[2] << 16);
02978                 }
02979                 else {
02980                     /* C/H/S */
02981                     if (ata->lba[0] == 0) {
02982                         LOG_MSG("ATA sector 0 does not exist\n");
02983                         ata->abort_error();
02984                         dev->controller->raise_irq();
02985                         return;
02986                     }
02987                     else if ((unsigned int)(ata->drivehead & 0xF) >= (unsigned int)ata->heads ||
02988                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02989                         (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8)) >= (unsigned int)ata->cyls) {
02990                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02991                             (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8)),
02992                             (unsigned int)(ata->drivehead&0xF),
02993                             (unsigned int)ata->lba[0],
02994                             (unsigned int)ata->cyls,
02995                             (unsigned int)ata->heads,
02996                             (unsigned int)ata->sects);
02997                         ata->abort_error();
02998                         dev->controller->raise_irq();
02999                         return;
03000                     }
03001 
03002                     sectorn = ((unsigned int)(ata->drivehead & 0xF) * ata->sects) +
03003                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8)) * ata->sects * ata->heads) +
03004                         ((unsigned int)ata->lba[0] - 1);
03005                 }
03006 
03007                 for (unsigned int cc=0;cc < MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount);cc++) {
03008                     /* it would be great if the disk object had a "write multiple sectors" member function */
03009                     if (disk->Write_AbsoluteSector(sectorn+cc, ata->sector+(cc*512)) != 0) {
03010                         LOG_MSG("Failed to write sector\n");
03011                         ata->abort_error();
03012                         dev->controller->raise_irq();
03013                         return;
03014                     }
03015                 }
03016 
03017                 for (unsigned int cc=0;cc < MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount);cc++) {
03018                     if ((ata->count&0xFF) == 1) {
03019                         /* end of the transfer */
03020                         ata->count = 0;
03021                         ata->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03022                         dev->controller->raise_irq();
03023                         ata->state = IDE_DEV_READY;
03024                         ata->allow_writing = true;
03025                         return;
03026                     }
03027                     else if ((ata->count&0xFF) == 0) ata->count = 255;
03028                     else ata->count--;
03029                     ata->progress_count++;
03030 
03031                     if (!ata->increment_current_address()) {
03032                         LOG_MSG("READ advance error\n");
03033                         ata->abort_error();
03034                         return;
03035                     }
03036                 }
03037 
03038                 /* begin another sector */
03039                 sectcount = ata->count & 0xFF;
03040                 if (sectcount == 0) sectcount = 256;
03041                 dev->state = IDE_DEV_DATA_WRITE;
03042                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03043                 ata->prepare_write(0,512*MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount));
03044                 dev->controller->raise_irq();
03045                 break;
03046 
03047             case 0xEC:/*IDENTIFY DEVICE (CONTINUED) */
03048                 dev->state = IDE_DEV_DATA_READ;
03049                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03050                 ata->generate_identify_device();
03051                 ata->prepare_read(0,512);
03052                 dev->count = 0x01;
03053                 dev->lba[0] = 0x00;
03054                 dev->feature = 0x00;
03055                 dev->lba[1] = 0x00;
03056                 dev->lba[2] = 0x00;
03057                 dev->controller->raise_irq();
03058                 break;
03059             default:
03060                 LOG_MSG("Unknown delayed IDE/ATA command\n");
03061                 dev->abort_error();
03062                 dev->controller->raise_irq();
03063                 break;
03064         }
03065     }
03066     else if (dev->type == IDE_TYPE_CDROM) {
03067         IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
03068 
03069         if (dev->state == IDE_DEV_ATAPI_BUSY) {
03070             switch (dev->command) {
03071                 case 0xA0:/*ATAPI PACKET*/
03072                     atapi->on_atapi_busy_time();
03073                     break;
03074                 default:
03075                     LOG_MSG("Unknown delayed IDE/ATAPI busy wait command\n");
03076                     dev->abort_error();
03077                     dev->controller->raise_irq();
03078                     break;
03079             }
03080         }
03081         else {
03082             switch (dev->command) {
03083                 case 0xA0:/*ATAPI PACKET*/
03084                     dev->state = IDE_DEV_ATAPI_PACKET_COMMAND;
03085                     dev->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE|IDE_STATUS_DRQ;
03086                     dev->count = 0x01;  /* input/output == 0, command/data == 1 */
03087                     atapi->atapi_cmd_total = 12; /* NTS: do NOT raise IRQ */
03088                     atapi->atapi_cmd_i = 0;
03089                     break;
03090                 case 0xA1:/*IDENTIFY PACKET DEVICE (CONTINUED) */
03091                     dev->state = IDE_DEV_DATA_READ;
03092                     dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03093                     atapi->generate_identify_device();
03094                     atapi->prepare_read(0,512);
03095                     dev->controller->raise_irq();
03096                     break;
03097                 default:
03098                     LOG_MSG("Unknown delayed IDE/ATAPI command\n");
03099                     dev->abort_error();
03100                     dev->controller->raise_irq();
03101                     break;
03102             }
03103         }
03104     }
03105     else {
03106         LOG_MSG("Unknown delayed command\n");
03107         dev->abort_error();
03108         dev->controller->raise_irq();
03109     }
03110 }
03111 
03112 void IDEController::raise_irq() {
03113     irq_pending = true;
03114     if (IRQ >= 0 && interrupt_enable) PIC_ActivateIRQ((unsigned int)IRQ);
03115 }
03116 
03117 void IDEController::lower_irq() {
03118     irq_pending = false;
03119     if (IRQ >= 0) PIC_DeActivateIRQ((unsigned int)IRQ);
03120 }
03121 
03122 IDEController *match_ide_controller(Bitu port) {
03123     unsigned int i;
03124 
03125     for (i=0;i < MAX_IDE_CONTROLLERS;i++) {
03126         IDEController *ide = idecontroller[i];
03127         if (ide == NULL) continue;
03128         if (ide->base_io != 0U && ide->base_io == (port&0xFFF8U)) return ide;
03129         if (ide->alt_io != 0U && ide->alt_io == (port&0xFFFEU)) return ide;
03130     }
03131 
03132     return NULL;
03133 }
03134 
03135 Bitu IDEDevice::data_read(Bitu iolen) {
03136     (void)iolen;//UNUSED
03137     return 0xAAAAU;
03138 }
03139 
03140 void IDEDevice::data_write(Bitu v,Bitu iolen) {
03141     (void)iolen;//UNUSED
03142     (void)v;//UNUSED
03143 }
03144 
03145 IDEDevice::IDEDevice(IDEController *c) {
03146     type = IDE_TYPE_NONE;
03147     status = 0x00;
03148     controller = c;
03149     asleep = false;
03150     motor_on = true;
03151     allow_writing = true;
03152     state = IDE_DEV_READY;
03153     feature = count = lba[0] = lba[1] = lba[2] = command = drivehead = 0;
03154 
03155     faked_command = false;
03156     ide_select_delay = 0.5; /* 500us */
03157     ide_spinup_delay = 3000; /* 3 seconds */
03158     ide_spindown_delay = 1000; /* 1 second */
03159     ide_identify_command_delay = 0.01; /* 10us */
03160 }
03161 
03162 /* IDE controller -> upon writing bit 2 of alt (0x3F6) */
03163 void IDEDevice::host_reset_complete() {
03164     status = 0x00;
03165     asleep = false;
03166     allow_writing = true;
03167     state = IDE_DEV_READY;
03168 }
03169 
03170 void IDEDevice::host_reset_begin() {
03171     status = 0xFF;
03172     asleep = false;
03173     allow_writing = true;
03174     state = IDE_DEV_BUSY;
03175 }
03176 
03177 IDEDevice::~IDEDevice() {
03178 }
03179 
03180 void IDEDevice::abort_silent() {
03181     assert(controller != NULL);
03182 
03183     /* a command was written while another is in progress */
03184     state = IDE_DEV_READY;
03185     allow_writing = true;
03186     command = 0x00;
03187     status = IDE_STATUS_ERROR | IDE_STATUS_DRIVE_READY | IDE_STATUS_DRIVE_SEEK_COMPLETE;
03188 }
03189 
03190 void IDEDevice::abort_error() {
03191     assert(controller != NULL);
03192     LOG_MSG("IDE abort dh=0x%02x with error on 0x%03x\n",drivehead,controller->base_io);
03193 
03194     /* a command was written while another is in progress */
03195     state = IDE_DEV_READY;
03196     allow_writing = true;
03197     command = 0x00;
03198     status = IDE_STATUS_ERROR | IDE_STATUS_DRIVE_READY | IDE_STATUS_DRIVE_SEEK_COMPLETE;
03199 }
03200 
03201 void IDEDevice::abort_normal() {
03202     /* a command was written while another is in progress */
03203     state = IDE_DEV_READY;
03204     allow_writing = true;
03205     command = 0x00;
03206     status = IDE_STATUS_DRIVE_READY | IDE_STATUS_DRIVE_SEEK_COMPLETE;
03207 }
03208 
03209 void IDEDevice::interface_wakeup() {
03210     if (asleep) {
03211         asleep = false;
03212     }
03213 }
03214 
03215 bool IDEDevice::command_interruption_ok(uint8_t cmd) {
03216     /* apparently this is OK, if the Linux kernel is doing it:
03217      * writing the same command byte as the one in progress, OR, issuing
03218      * Device Reset while another command is waiting for data read/write */
03219     if (cmd == command) return true;
03220     if (state != IDE_DEV_READY && state != IDE_DEV_BUSY && cmd == 0x08) {
03221         LOG_MSG("Device reset while another (%02x) is in progress (state=%u). Aborting current command to begin another\n",command,state);
03222         abort_silent();
03223         return true;
03224     }
03225 
03226     if (state != IDE_DEV_READY) {
03227         LOG_MSG("Command %02x written while another (%02x) is in progress (state=%u). Aborting current command\n",cmd,command,state);
03228         abort_error();
03229         return false;
03230     }
03231 
03232     return true;
03233 }
03234 
03235 void IDEDevice::writecommand(uint8_t cmd) {
03236     if (!command_interruption_ok(cmd))
03237         return;
03238 
03239     /* if the drive is asleep, then writing a command wakes it up */
03240     interface_wakeup();
03241 
03242     /* drive is ready to accept command */
03243     switch (cmd) {
03244         default:
03245             LOG_MSG("Unknown IDE command %02X\n",cmd);
03246             abort_error();
03247             break;
03248     }
03249 }
03250 
03251 void IDEATAPICDROMDevice::writecommand(uint8_t cmd) {
03252     if (!command_interruption_ok(cmd))
03253         return;
03254 
03255     /* if the drive is asleep, then writing a command wakes it up */
03256     interface_wakeup();
03257 
03258     /* drive is ready to accept command */
03259     allow_writing = false;
03260     command = cmd;
03261     switch (cmd) {
03262         case 0x08: /* DEVICE RESET */
03263             status = 0x00;
03264             drivehead &= 0x10; controller->drivehead = drivehead;
03265             count = 0x01;
03266             lba[0] = 0x01;
03267             feature = 0x01;
03268             lba[1] = 0x14;  /* <- magic ATAPI identification */
03269             lba[2] = 0xEB;
03270             /* NTS: Testing suggests that ATAPI devices do NOT trigger an IRQ on receipt of this command */
03271             allow_writing = true;
03272             break;
03273         case 0x20: /* READ SECTOR */
03274             abort_normal();
03275             status = IDE_STATUS_ERROR|IDE_STATUS_DRIVE_READY;
03276             drivehead &= 0x30; controller->drivehead = drivehead;
03277             count = 0x01;
03278             lba[0] = 0x01;
03279             feature = 0x04; /* abort */
03280             lba[1] = 0x14;  /* <- magic ATAPI identification */
03281             lba[2] = 0xEB;
03282             controller->raise_irq();
03283             allow_writing = true;
03284             break;
03285         case 0xA0: /* ATAPI PACKET */
03286             if (feature & 1) {
03287                 /* this code does not support DMA packet commands */
03288                 LOG_MSG("Attempted DMA transfer\n");
03289                 abort_error();
03290                 count = 0x03; /* no more data (command/data=1, input/output=1) */
03291                 feature = 0xF4;
03292                 controller->raise_irq();
03293             }
03294             else {
03295                 state = IDE_DEV_BUSY;
03296                 status = IDE_STATUS_BUSY;
03297                 atapi_to_host = (feature >> 2) & 1; /* 0=to device 1=to host */
03298                 host_maximum_byte_count = ((unsigned int)lba[2] << 8) + (unsigned int)lba[1]; /* LBA field bits 23:8 are byte count */
03299                 if (host_maximum_byte_count == 0) host_maximum_byte_count = 0x10000UL;
03300                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 0.25)/*ms*/,controller->interface_index);
03301             }
03302             break;
03303         case 0xA1: /* IDENTIFY PACKET DEVICE */
03304             state = IDE_DEV_BUSY;
03305             status = IDE_STATUS_BUSY;
03306             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : ide_identify_command_delay),controller->interface_index);
03307             break;
03308         case 0xEC: /* IDENTIFY DEVICE */
03309             /* "devices that implement the PACKET command set shall post command aborted and place PACKET command feature
03310                set in the appropriate fields". We have to do this. Unlike OAKCDROM.SYS Windows 95 appears to autodetect
03311                IDE devices by what they do when they're sent command 0xEC out of the blue---Microsoft didn't write their
03312                IDE drivers to use command 0x08 DEVICE RESET. */
03313             abort_normal();
03314             status = IDE_STATUS_ERROR|IDE_STATUS_DRIVE_READY;
03315             drivehead &= 0x30; controller->drivehead = drivehead;
03316             count = 0x01;
03317             lba[0] = 0x01;
03318             feature = 0x04; /* abort */
03319             lba[1] = 0x14;  /* <- magic ATAPI identification */
03320             lba[2] = 0xEB;
03321             controller->raise_irq();
03322             allow_writing = true;
03323             break;
03324         default:
03325             LOG_MSG("Unknown IDE/ATAPI command %02X\n",cmd);
03326             abort_error();
03327             allow_writing = true;
03328             count = 0x03; /* no more data (command/data=1, input/output=1) */
03329             feature = 0xF4;
03330             controller->raise_irq();
03331             break;
03332     }
03333 }
03334 
03335 void IDEATADevice::writecommand(uint8_t cmd) {
03336     if (!command_interruption_ok(cmd))
03337         return;
03338 
03339     if (!faked_command) {
03340         if (drivehead_is_lba(drivehead)) {
03341             uint64_t n;
03342 
03343             n = ((unsigned int)(drivehead&0xF)<<24)+((unsigned int)lba[2]<<16)+((unsigned int)lba[1]<<8)+(unsigned int)lba[0];
03344             LOG_MSG("IDE ATA command %02x dh=0x%02x count=0x%02x lba=%07llx/%07llx\n",cmd,
03345                 drivehead,count,(unsigned long long)n,
03346                 (unsigned long long)(phys_sects * phys_cyls * phys_heads));
03347         }
03348         else {
03349             LOG_MSG("IDE ATA command %02x dh=0x%02x count=0x%02x chs=%02x/%02x/%02x\n",cmd,
03350                 drivehead,count,((unsigned int)lba[2]<<8)+(unsigned int)lba[1],(unsigned int)(drivehead&0xF),(unsigned int)lba[0]);
03351         }
03352 
03353         LOG(LOG_SB,LOG_NORMAL)("IDE ATA command %02x",cmd);
03354     }
03355 
03356     /* if the drive is asleep, then writing a command wakes it up */
03357     interface_wakeup();
03358 
03359     /* FIXME: OAKCDROM.SYS is sending the hard disk command 0xA0 (ATAPI packet) for some reason. Why? */
03360 
03361     /* drive is ready to accept command */
03362     allow_writing = false;
03363     command = cmd;
03364     switch (cmd) {
03365         case 0x00: /* NOP */
03366             feature = 0x04;
03367             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_ERROR;
03368             controller->raise_irq();
03369             allow_writing = true;
03370             break;
03371         case 0x08: /* DEVICE RESET */
03372             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03373             drivehead &= 0x10; controller->drivehead = drivehead;
03374             count = 0x01; lba[0] = 0x01; feature = 0x00;
03375             lba[1] = lba[2] = 0;
03376             /* NTS: Testing suggests that ATA hard drives DO fire an IRQ at this stage.
03377                     In fact, Windows 95 won't detect hard drives that don't fire an IRQ in desponse */
03378             controller->raise_irq();
03379             allow_writing = true;
03380             break;
03381         case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: /* RECALIBRATE (1xh) */
03382         case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
03383             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03384             /* "if the command is executed in CHS mode, then ... sector number register shall be 1.
03385              *  if executed in LAB mode, then ... sector number register shall be 0" */
03386             if (drivehead_is_lba(drivehead)) lba[0] = 0x00;
03387             else lba[0] = 0x01;
03388             drivehead &= 0x10; controller->drivehead = drivehead;
03389             lba[1] = lba[2] = 0;
03390             feature = 0x00;
03391             controller->raise_irq();
03392             allow_writing = true;
03393             break;
03394         case 0x20: /* READ SECTOR */
03395             progress_count = 0;
03396             state = IDE_DEV_BUSY;
03397             status = IDE_STATUS_BUSY;
03398             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 0.1)/*ms*/,controller->interface_index);
03399             break;
03400         case 0x30: /* WRITE SECTOR */
03401             /* the drive does NOT signal an interrupt. it sets DRQ and waits for a sector
03402              * to be transferred to it before executing the command */
03403             progress_count = 0;
03404             state = IDE_DEV_DATA_WRITE;
03405             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ;
03406             prepare_write(0,512);
03407             break;
03408         case 0x40: /* READ SECTOR VERIFY WITH RETRY */
03409         case 0x41: /* READ SECTOR VERIFY WITHOUT RETRY */
03410             progress_count = 0;
03411             state = IDE_DEV_BUSY;
03412             status = IDE_STATUS_BUSY;
03413             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 0.1)/*ms*/,controller->interface_index);
03414             break;
03415         case 0x91: /* INITIALIZE DEVICE PARAMETERS */
03416             if ((unsigned int)count != (unsigned int)sects || (unsigned int)((drivehead&0xF)+1) != (unsigned int)heads) {
03417                 if (count == 0) {
03418                     LOG_MSG("IDE warning: OS attempted to change geometry to invalid H/S %u/%u\n",
03419                         count,(drivehead&0xF)+1);
03420                     abort_error();
03421                     allow_writing = true;
03422                     return;
03423                 }
03424                 else {
03425                     unsigned int ncyls;
03426 
03427                     ncyls = (phys_cyls * phys_heads * phys_sects);
03428                     ncyls += (count * ((unsigned int)(drivehead&0xF)+1u)) - 1u;
03429                     ncyls /= count * ((unsigned int)(drivehead&0xF)+1u);
03430 
03431                     /* the OS is changing logical disk geometry, so update our head/sector count (needed for Windows ME) */
03432                     LOG_MSG("IDE warning: OS is changing logical geometry from C/H/S %u/%u/%u to logical H/S %u/%u/%u\n",
03433                         (int)cyls,(int)heads,(int)sects,
03434                         (int)ncyls,(int)((drivehead&0xF)+1),(int)count);
03435                     LOG_MSG("             Compatibility issues may occur if the OS tries to use INT 13 at the same time!\n");
03436 
03437                     cyls = ncyls;
03438                     sects = count;
03439                     heads = (drivehead&0xFu)+1u;
03440                 }
03441             }
03442 
03443             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03444             allow_writing = true;
03445             break;
03446         case 0xC4: /* READ MULTIPLE */
03447             progress_count = 0;
03448             state = IDE_DEV_BUSY;
03449             status = IDE_STATUS_BUSY;
03450             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 0.1)/*ms*/,controller->interface_index);
03451             break;
03452         case 0xC5: /* WRITE MULTIPLE */
03453             /* the drive does NOT signal an interrupt. it sets DRQ and waits for a sector
03454              * to be transferred to it before executing the command */
03455             progress_count = 0;
03456             state = IDE_DEV_DATA_WRITE;
03457             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ;
03458             prepare_write(0UL,512UL*MIN((unsigned long)multiple_sector_count,(unsigned long)(count == 0 ? 256 : count)));
03459             break;
03460         case 0xC6: /* SET MULTIPLE MODE */
03461             /* only sector counts 1, 2, 4, 8, 16, 32, 64, and 128 are legal by standard.
03462              * NTS: There's a bug in VirtualBox that makes 0 legal too! */
03463             if (count != 0 && count <= multiple_sector_max && is_power_of_2(count)) {
03464                 multiple_sector_count = count;
03465                 status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03466             }
03467             else {
03468                 feature = 0x04; /* abort error */
03469                 abort_error();
03470             }
03471             controller->raise_irq();
03472             allow_writing = true;
03473             break;
03474         case 0xA0:/*ATAPI PACKET*/
03475             /* We're not an ATAPI packet device!
03476              * Windows 95 seems to issue this at startup to hard drives. Duh. */
03477             /* fall through */
03478         case 0xA1: /* IDENTIFY PACKET DEVICE */
03479             /* We are not an ATAPI packet device.
03480              * Most MS-DOS drivers and Windows 95 like to issue both IDENTIFY ATA and IDENTIFY ATAPI commands.
03481              * I also gather from some contributers on the github comments that people think our "Unknown IDE/ATA command"
03482              * error message is part of some other error in the emulation. Rather than put up with that, we'll just
03483              * silently abort the command with an error. */
03484             abort_normal();
03485             status = IDE_STATUS_ERROR|IDE_STATUS_DRIVE_READY;
03486             drivehead &= 0x30; controller->drivehead = drivehead;
03487             count = 0x01;
03488             lba[0] = 0x01;
03489             feature = 0x04; /* abort */
03490             lba[1] = 0x00;
03491             lba[2] = 0x00;
03492             controller->raise_irq();
03493             allow_writing = true;
03494             break;
03495         case 0xEC: /* IDENTIFY DEVICE */
03496             state = IDE_DEV_BUSY;
03497             status = IDE_STATUS_BUSY;
03498             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : ide_identify_command_delay),controller->interface_index);
03499             break;
03500         default:
03501             LOG_MSG("Unknown IDE/ATA command %02X\n",cmd);
03502             abort_error();
03503             allow_writing = true;
03504             controller->raise_irq();
03505             break;
03506     }
03507 }
03508 
03509 void IDEDevice::deselect() {
03510 }
03511 
03512 /* the hard disk or CD-ROM class override of this member is responsible for checking
03513    the head value and clamping within range if C/H/S mode is selected */
03514 void IDEDevice::select(uint8_t ndh,bool switched_to) {
03515     (void)switched_to;//UNUSED
03516     (void)ndh;//UNUSED
03517     /* NTS: I thought there was some delay between selecting a drive and sending a command.
03518         Apparently I was wrong. */
03519     if (allow_writing) drivehead = ndh;
03520 //  status = (!asleep)?(IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE):0;
03521 //  allow_writing = !asleep;
03522 //  state = IDE_DEV_READY;
03523 }
03524 
03525 IDEController::IDEController(Section* configuration,unsigned char index):Module_base(configuration){
03526     Section_prop * section=static_cast<Section_prop *>(configuration);
03527     int i;
03528 
03529     register_pnp = section->Get_bool("pnp");
03530     int13fakeio = section->Get_bool("int13fakeio");
03531     int13fakev86io = section->Get_bool("int13fakev86io");
03532     enable_pio32 = section->Get_bool("enable pio32");
03533     ignore_pio32 = section->Get_bool("ignore pio32");
03534     spinup_time = section->Get_int("cd-rom spinup time");
03535     spindown_timeout = section->Get_int("cd-rom spindown timeout");
03536     cd_insertion_time = section->Get_int("cd-rom insertion delay");
03537 
03538     status = 0x00;
03539     host_reset = false;
03540     irq_pending = false;
03541     interrupt_enable = true;
03542     interface_index = index;
03543     device[0] = NULL;
03544     device[1] = NULL;
03545     base_io = 0;
03546     select = 0;
03547     alt_io = 0;
03548     IRQ = -1;
03549 
03550     i = section->Get_int("irq");
03551     if (i > 0 && i <= 15) IRQ = i;
03552 
03553     i = section->Get_hex("io");
03554     if (i >= 0x100 && i <= 0x3FF) base_io = (unsigned int)(i & ~7);
03555 
03556     i = section->Get_hex("altio");
03557     if (i >= 0x100 && i <= 0x3FF) alt_io = (unsigned int)(i & ~1);
03558 
03559     if (index < sizeof(IDE_default_IRQs)) {
03560         if (IRQ < 0) IRQ = IDE_default_IRQs[index];
03561         if (alt_io == 0) alt_io = IDE_default_alts[index];
03562         if (base_io == 0) base_io = IDE_default_bases[index];
03563     }
03564     else {
03565         if (IRQ < 0 || alt_io == 0 || base_io == 0)
03566             LOG_MSG("WARNING: IDE interface %u: Insufficient resources assigned by dosbox.conf, and no appropriate default resources for this interface.",index);
03567     }
03568 }
03569 
03570 void IDEController::register_isapnp() {
03571     if (register_pnp && base_io > 0 && alt_io > 0) {
03572         unsigned char tmp[256];
03573         unsigned int i;
03574 
03575         const unsigned char h1[9] = {
03576             ISAPNP_SYSDEV_HEADER(
03577                 ISAPNP_ID('P','N','P',0x0,0x6,0x0,0x0), /* PNP0600 Generic ESDI/IDE/ATA compatible hard disk controller */
03578                 ISAPNP_TYPE(0x01,0x01,0x00),        /* type: Mass Storage Device / IDE / Generic */
03579                 0x0001 | 0x0002)
03580         };
03581 
03582         i = 0;
03583         memcpy(tmp+i,h1,9); i += 9;         /* can't disable, can't configure */
03584         /*----------allocated--------*/
03585         tmp[i+0] = (8 << 3) | 7;            /* IO resource */
03586         tmp[i+1] = 0x01;                /* 16-bit decode */
03587         host_writew(tmp+i+2,base_io);           /* min */
03588         host_writew(tmp+i+4,base_io);           /* max */
03589         tmp[i+6] = 0x08;                /* align */
03590         tmp[i+7] = 0x08;                /* length */
03591         i += 7+1;
03592 
03593         tmp[i+0] = (8 << 3) | 7;            /* IO resource */
03594         tmp[i+1] = 0x01;                /* 16-bit decode */
03595         host_writew(tmp+i+2,alt_io);            /* min */
03596         host_writew(tmp+i+4,alt_io);            /* max */
03597         tmp[i+6] = 0x01;                /* align */
03598         if (alt_io == 0x3F6 && fdc_takes_port_3F7())
03599             tmp[i+7] = 0x01;            /* length 1 (so as not to conflict with floppy controller at 0x3F7) */
03600         else
03601             tmp[i+7] = 0x02;            /* length 2 */
03602         i += 7+1;
03603 
03604         if (IRQ > 0) {
03605             tmp[i+0] = (4 << 3) | 3;        /* IRQ resource */
03606             host_writew(tmp+i+1,1 << IRQ);
03607             tmp[i+3] = 0x09;            /* HTE=1 LTL=1 */
03608             i += 3+1;
03609         }
03610 
03611         tmp[i+0] = 0x79;                /* END TAG */
03612         tmp[i+1] = 0x00;
03613         i += 2;
03614         /*-------------possible-----------*/
03615         tmp[i+0] = 0x79;                /* END TAG */
03616         tmp[i+1] = 0x00;
03617         i += 2;
03618         /*-------------compatible---------*/
03619         tmp[i+0] = 0x79;                /* END TAG */
03620         tmp[i+1] = 0x00;
03621         i += 2;
03622 
03623         if (!ISAPNP_RegisterSysDev(tmp,i))
03624             LOG_MSG("ISAPNP register failed\n");
03625     }
03626 }
03627 
03628 void IDEController::install_io_port(){
03629     unsigned int i;
03630 
03631     if (base_io != 0) {
03632         for (i=0;i < 8;i++) {
03633             WriteHandler[i].Install(base_io+i,ide_baseio_w,IO_MA);
03634             ReadHandler[i].Install(base_io+i,ide_baseio_r,IO_MA);
03635         }
03636     }
03637 
03638     if (alt_io != 0) {
03639         WriteHandlerAlt[0].Install(alt_io,ide_altio_w,IO_MA);
03640         ReadHandlerAlt[0].Install(alt_io,ide_altio_r,IO_MA);
03641 
03642         /* the floppy controller might take port 0x3F7.
03643          * don't claim it if so */
03644         if (alt_io == 0x3F6 && fdc_takes_port_3F7()) {
03645             LOG_MSG("IDE: Not registering port 3F7h, FDC will occupy it.\n");
03646         }
03647         else {
03648             WriteHandlerAlt[1].Install(alt_io+1u,ide_altio_w,IO_MA);
03649             ReadHandlerAlt[1].Install(alt_io+1u,ide_altio_r,IO_MA);
03650         }
03651     }
03652 }
03653 
03654 IDEController::~IDEController() {
03655     unsigned int i;
03656 
03657     for (i=0;i < 2;i++) {
03658         if (device[i] != NULL) {
03659             delete device[i];
03660             device[i] = NULL;
03661         }
03662     }
03663 }
03664 
03665 static void ide_altio_w(Bitu port,Bitu val,Bitu iolen) {
03666     IDEController *ide = match_ide_controller(port);
03667     if (ide == NULL) {
03668         LOG_MSG("WARNING: port read from I/O port not registered to IDE, yet callback triggered\n");
03669         return;
03670     }
03671 
03672     if (!ide->enable_pio32 && iolen == 4) {
03673         ide_altio_w(port,val&0xFFFF,2);
03674         ide_altio_w(port+2u,val>>16u,2);
03675         return;
03676     }
03677     else if (ide->ignore_pio32 && iolen == 4)
03678         return;
03679 
03680     port &= 1;
03681     if (port == 0) {/*3F6*/
03682         ide->interrupt_enable = (val&2u)?0:1;
03683         if (ide->interrupt_enable) {
03684             if (ide->irq_pending) ide->raise_irq();
03685         }
03686         else {
03687             if (ide->IRQ >= 0) PIC_DeActivateIRQ((unsigned int)ide->IRQ);
03688         }
03689 
03690         if ((val&4) && !ide->host_reset) {
03691             if (ide->device[0]) ide->device[0]->host_reset_begin();
03692             if (ide->device[1]) ide->device[1]->host_reset_begin();
03693             ide->host_reset=1;
03694         }
03695         else if (!(val&4) && ide->host_reset) {
03696             if (ide->device[0]) ide->device[0]->host_reset_complete();
03697             if (ide->device[1]) ide->device[1]->host_reset_complete();
03698             ide->host_reset=0;
03699         }
03700     }
03701 }
03702 
03703 static Bitu ide_altio_r(Bitu port,Bitu iolen) {
03704     IDEController *ide = match_ide_controller(port);
03705     IDEDevice *dev;
03706 
03707     if (ide == NULL) {
03708         LOG_MSG("WARNING: port read from I/O port not registered to IDE, yet callback triggered\n");
03709         return ~(0UL);
03710     }
03711 
03712     if (!ide->enable_pio32 && iolen == 4)
03713         return ide_altio_r(port,2) + (ide_altio_r(port+2u,2) << 16u);
03714     else if (ide->ignore_pio32 && iolen == 4)
03715         return ~0ul;
03716 
03717     dev = ide->device[ide->select];
03718     port &= 1;
03719     if (port == 0)/*3F6(R) status, does NOT clear interrupt*/
03720         return (dev != NULL) ? dev->status : ide->status;
03721     else /*3F7(R) Drive Address Register*/
03722         return 0x80u|(ide->select==0?0u:1u)|(ide->select==1?0u:2u)|
03723             ((dev != NULL) ? (((dev->drivehead&0xFu)^0xFu) << 2u) : 0x3Cu);
03724 
03725     return ~(0UL);
03726 }
03727 
03728 static Bitu ide_baseio_r(Bitu port,Bitu iolen) {
03729     IDEController *ide = match_ide_controller(port);
03730     IDEDevice *dev;
03731     Bitu ret = ~0ul;
03732 
03733     if (ide == NULL) {
03734         LOG_MSG("WARNING: port read from I/O port not registered to IDE, yet callback triggered\n");
03735         return ~(0UL);
03736     }
03737 
03738     if (!ide->enable_pio32 && iolen == 4)
03739         return ide_baseio_r(port,2) + (ide_baseio_r(port+2,2) << 16);
03740     else if (ide->ignore_pio32 && iolen == 4)
03741         return ~0ul;
03742 
03743     dev = ide->device[ide->select];
03744     port &= 7;
03745     switch (port) {
03746         case 0: /* 1F0 */
03747             ret = (dev != NULL) ? dev->data_read(iolen) : 0xFFFFFFFFUL;
03748             break;
03749         case 1: /* 1F1 */
03750             ret = (dev != NULL) ? dev->feature : 0x00;
03751             break;
03752         case 2: /* 1F2 */
03753             ret = (dev != NULL) ? dev->count : 0x00;
03754             break;
03755         case 3: /* 1F3 */
03756             ret = (dev != NULL) ? dev->lba[0] : 0x00;
03757             break;
03758         case 4: /* 1F4 */
03759             ret = (dev != NULL) ? dev->lba[1] : 0x00;
03760             break;
03761         case 5: /* 1F5 */
03762             ret = (dev != NULL) ? dev->lba[2] : 0x00;
03763             break;
03764         case 6: /* 1F6 */
03765             ret = ide->drivehead;
03766             break;
03767         case 7: /* 1F7 */
03768             /* if an IDE device exists at selection return it's status, else return our status */
03769             if (dev && dev->status & IDE_STATUS_BUSY) {
03770             }
03771             else if (dev == NULL && ide->status & IDE_STATUS_BUSY) {
03772             }
03773             else {
03774                 ide->lower_irq();
03775             }
03776 
03777             ret = (dev != NULL) ? dev->status : ide->status;
03778             break;
03779     }
03780 
03781     return ret;
03782 }
03783 
03784 static void ide_baseio_w(Bitu port,Bitu val,Bitu iolen) {
03785     IDEController *ide = match_ide_controller(port);
03786     IDEDevice *dev;
03787 
03788     if (ide == NULL) {
03789         LOG_MSG("WARNING: port read from I/O port not registered to IDE, yet callback triggered\n");
03790         return;
03791     }
03792 
03793     if (!ide->enable_pio32 && iolen == 4) {
03794         ide_baseio_w(port,val&0xFFFF,2);
03795         ide_baseio_w(port+2,val>>16,2);
03796         return;
03797     }
03798     else if (ide->ignore_pio32 && iolen == 4)
03799         return;
03800 
03801     dev = ide->device[ide->select];
03802     port &= 7;
03803 
03804     /* ignore I/O writes if the controller is busy */
03805     if (dev) {
03806         if (dev->status & IDE_STATUS_BUSY) {
03807             if (port == 6 && ((val>>4)&1) == ide->select) {
03808                 /* some MS-DOS drivers like ATAPICD.SYS are just very pedantic about writing to port +6 to ensure the right drive is selected */
03809                 return;
03810             }
03811             else {
03812                 LOG_MSG("W-%03X %02X BUSY DROP [DEV]\n",(int)(port+ide->base_io),(int)val);
03813                 return;
03814             }
03815         }
03816     }
03817     else if (ide->status & IDE_STATUS_BUSY) {
03818         if (port == 6 && ((val>>4)&1) == ide->select) {
03819             /* some MS-DOS drivers like ATAPICD.SYS are just very pedantic about writing to port +6 to ensure the right drive is selected */
03820             return;
03821         }
03822         else {
03823             LOG_MSG("W-%03X %02X BUSY DROP [IDE]\n",(int)(port+ide->base_io),(int)val);
03824             return;
03825         }
03826     }
03827 
03828 #if 0
03829     if (ide == idecontroller[1])
03830         LOG_MSG("IDE: baseio write port %u val %02x\n",(unsigned int)port,(unsigned int)val);
03831 #endif
03832 
03833     if (port >= 1 && port <= 5 && dev && !dev->allow_writing) {
03834         LOG_MSG("IDE WARNING: Write to port %u val %02x when device not ready to accept writing\n",
03835             (unsigned int)port,(unsigned int)val);
03836     }
03837 
03838     switch (port) {
03839         case 0: /* 1F0 */
03840             if (dev) dev->data_write(val,iolen); /* <- TODO: what about 32-bit PIO modes? */
03841             break;
03842         case 1: /* 1F1 */
03843             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
03844                 dev->feature = val;
03845             break;
03846         case 2: /* 1F2 */
03847             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
03848                 dev->count = val;
03849             break;
03850         case 3: /* 1F3 */
03851             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
03852                 dev->lba[0] = val;
03853             break;
03854         case 4: /* 1F4 */
03855             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
03856                 dev->lba[1] = val;
03857             break;
03858         case 5: /* 1F5 */
03859             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
03860                 dev->lba[2] = val;
03861             break;
03862         case 6: /* 1F6 */
03863             if (((val>>4)&1) != ide->select) {
03864                 ide->lower_irq();
03865                 /* update select pointer if bit 4 changes.
03866                    also emulate IDE busy state when changing drives */
03867                 if (dev) dev->deselect();
03868                 ide->select = (val>>4)&1;
03869                 dev = ide->device[ide->select];
03870                 if (dev) dev->select(val,1);
03871                 else ide->status = 0; /* NTS: if there is no drive there you're supposed to not have anything set */
03872             }
03873             else if (dev) {
03874                 dev->select(val,0);
03875             }
03876             else {
03877                 ide->status = 0; /* NTS: if there is no drive there you're supposed to not have anything set */
03878             }
03879 
03880             ide->drivehead = val;
03881             break;
03882         case 7: /* 1F7 */
03883             if (dev) dev->writecommand(val);
03884             break;
03885     }
03886 }
03887 
03888 static void IDE_Destroy(Section* sec) {
03889     (void)sec;//UNUSED
03890     for (unsigned int i=0;i < MAX_IDE_CONTROLLERS;i++) {
03891         if (idecontroller[i] != NULL) {
03892             delete idecontroller[i];
03893             idecontroller[i] = NULL;
03894         }
03895     }
03896 
03897     init_ide = 0;
03898 }
03899 
03900 static void IDE_Init(Section* sec,unsigned char ide_interface) {
03901     Section_prop *section=static_cast<Section_prop *>(sec);
03902     IDEController *ide;
03903 
03904     assert(ide_interface < MAX_IDE_CONTROLLERS);
03905 
03906     if (!section->Get_bool("enable"))
03907         return;
03908 
03909     if (!init_ide) {
03910         AddExitFunction(AddExitFunctionFuncPair(IDE_Destroy));
03911         init_ide = 1;
03912     }
03913 
03914     LOG(LOG_MISC,LOG_DEBUG)("Initializing IDE controller %u",ide_interface);
03915 
03916     if (idecontroller[ide_interface] != NULL) {
03917         delete idecontroller[ide_interface];
03918         idecontroller[ide_interface] = NULL;
03919     }
03920 
03921     ide = idecontroller[ide_interface] = new IDEController(sec,ide_interface);
03922     ide->install_io_port();
03923 
03924     PIC_SetIRQMask((unsigned int)ide->IRQ,false);
03925 }
03926 
03927 void IDE_Primary_Init(Section *sec) {
03928     IDE_Init(sec,0);
03929 }
03930 
03931 void IDE_Secondary_Init(Section *sec) {
03932     IDE_Init(sec,1);
03933 }
03934 
03935 void IDE_Tertiary_Init(Section *sec) {
03936     IDE_Init(sec,2);
03937 }
03938 
03939 void IDE_Quaternary_Init(Section *sec) {
03940     IDE_Init(sec,3);
03941 }
03942 
03943 void IDE_Quinternary_Init(Section *sec) {
03944     IDE_Init(sec,4);
03945 }
03946 
03947 void IDE_Sexternary_Init(Section *sec) {
03948     IDE_Init(sec,5);
03949 }
03950 
03951 void IDE_Septernary_Init(Section *sec) {
03952     IDE_Init(sec,6);
03953 }
03954 
03955 void IDE_Octernary_Init(Section *sec) {
03956     IDE_Init(sec,7);
03957 }
03958 
03959 const char *ide_names[MAX_IDE_CONTROLLERS] = {
03960     "ide, primary",
03961     "ide, secondary",
03962     "ide, tertiary",
03963     "ide, quaternary",
03964     "ide, quinternary",
03965     "ide, sexternary",
03966     "ide, septernary",
03967     "ide, octernary"
03968 };
03969 void (*ide_inits[MAX_IDE_CONTROLLERS])(Section *) = {
03970     &IDE_Primary_Init,
03971     &IDE_Secondary_Init,
03972     &IDE_Tertiary_Init,
03973     &IDE_Quaternary_Init,
03974     &IDE_Quinternary_Init,
03975     &IDE_Sexternary_Init,
03976     &IDE_Septernary_Init,
03977     &IDE_Octernary_Init
03978 };
03979 
03980 void IDE_OnReset(Section *sec) {
03981     (void)sec;//UNUSED
03982     if (IS_PC98_ARCH) return;
03983 
03984     for (size_t i=0;i < MAX_IDE_CONTROLLERS;i++) ide_inits[i](control->GetSection(ide_names[i]));
03985 }
03986 
03987 void IDE_Init() {
03988     LOG(LOG_MISC,LOG_DEBUG)("Initializing IDE controllers");
03989 
03990     AddVMEventFunction(VM_EVENT_RESET,AddVMEventFunctionFuncPair(IDE_OnReset));
03991 }
03992 
03993 void BIOS_Post_register_IDE() {
03994     for (size_t i=0;i < MAX_IDE_CONTROLLERS;i++) {
03995         if (idecontroller[i] != NULL)
03996             idecontroller[i]->register_isapnp();
03997     }
03998 }
03999