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