00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00221 #ifdef DEBUG_IDE_LOCKS
00222 #define DEBUG_LOCKS
00223 #endif
00224 #include "StdAfx.h"
00225 #include "AliM1543C_ide.h"
00226 #include "System.h"
00227
00228 #include <math.h>
00229
00230 #include "gui/scancodes.h"
00231 #include "gui/keymap.h"
00232
00233 #include "AliM1543C.h"
00234 #include "Disk.h"
00235
00236 #define PAUSE(msg) \
00237 do \
00238 { \
00239 printf("Debug Pause: "); \
00240 printf(msg); \
00241 getc(stdin); \
00242 } while(0);
00243
00244 u32 AliM1543C_ide_cfg_data[64] = {
00245 0x522910b9,
00246 0x02800000,
00247 0x0101fac1,
00248 0x00000000,
00249 0x000001f1,
00250 0x000003f5,
00251 0x00000171,
00252 0x00000375,
00253 0x0000f001,
00254 0x00000000,
00255 0x00000000,
00256 0x00000000,
00257 0x00000000,
00258 0x00000000,
00259 0x00000000,
00260 0x040201ff,
00261 0, 0,
00262 0x4a000000,
00263 0x1aba0000,
00264 0,
00265 0x44445555,
00266 0, 0, 0, 0, 0, 0, 0, 0,
00267 0x00000021,
00268 0,
00269 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00271 };
00272
00273 u32 AliM1543C_ide_cfg_mask[64] = {
00274 0x00000000,
00275 0x00000105,
00276 0x00000000,
00277 0x0000ffff,
00278 0xfffffff8,
00279 0xfffffffc,
00280 0xfffffff8,
00281 0xfffffffc,
00282 0xfffffff0,
00283 0x00000000,
00284 0x00000000,
00285 0x00000000,
00286 0x00000000,
00287 0x00000000,
00288 0x00000000,
00289 0x000000ff,
00290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00293 };
00294
00298 CAliM1543C_ide::CAliM1543C_ide(CConfigurator* cfg, CSystem* c, int pcibus,
00299 int pcidev) : CDiskController(cfg, c, pcibus, pcidev, 2, 2)
00300 {
00301 if(theIDE != 0)
00302 FAILURE(Configuration, "More than one IDE controller");
00303 theIDE = this;
00304
00305
00306 CSCSIBus* a = new CSCSIBus(cfg, c);
00307 CSCSIBus* b = new CSCSIBus(cfg, c);
00308 scsi_register(0, a, 7);
00309 scsi_register(1, b, 7);
00310 }
00311
00315 void CAliM1543C_ide::init()
00316 {
00317 add_function(0, AliM1543C_ide_cfg_data, AliM1543C_ide_cfg_mask);
00318
00319 add_legacy_io(PRI_COMMAND, 0x1f0, 8);
00320 add_legacy_io(PRI_CONTROL, 0x3f6, 2);
00321 add_legacy_io(SEC_COMMAND, 0x170, 8);
00322 add_legacy_io(SEC_CONTROL, 0x376, 2);
00323 add_legacy_io(PRI_BUSMASTER, 0xf000, 8);
00324 add_legacy_io(SEC_BUSMASTER, 0xf008, 8);
00325
00326 usedma = myCfg->get_bool_value("dma", true);
00327 if(!usedma)
00328 {
00329 printf("IDE: DMA Transfers turned off.\n");
00330 }
00331
00332 ResetPCI();
00333
00334
00335 StopThread = false;
00336 mtRegisters[0] = new CRWMutex("ide0-registers");
00337 mtRegisters[1] = new CRWMutex("ide1-registers");
00338 mtBusMaster[0] = new CRWMutex("ide0-busmaster");
00339 mtBusMaster[1] = new CRWMutex("ide1-busmaster");
00340
00341 for(int i = 0; i < 2; i++)
00342 {
00343 semController[i] = new Poco::Semaphore(0, 1);
00344 semBusMaster[i] = new Poco::Semaphore(0, 1);
00345 thrController[i] = 0;
00346 }
00347
00348 printf("%%IDE-I-INIT: New IDE emulator initialized.\n");
00349 }
00350
00351 void CAliM1543C_ide::start_threads()
00352 {
00353 char buffer[5];
00354 for(int i = 0; i < 2; i++)
00355 {
00356 if(!thrController[i])
00357 {
00358 sprintf(buffer, "ide%d", i);
00359 thrController[i] = new Poco::Thread(buffer);
00360 printf(" %s", thrController[i]->getName().c_str());
00361 StopThread = false;
00362 thrController[i]->start(*this);
00363 }
00364 }
00365 }
00366
00367 void CAliM1543C_ide::stop_threads()
00368 {
00369 StopThread = true;
00370 for(int i = 0; i < 2; i++)
00371 {
00372 if(thrController[i])
00373 {
00374 printf(" %s", thrController[i]->getName().c_str());
00375 semController[i]->set();
00376 thrController[i]->join();
00377 delete thrController[i];
00378 thrController[i] = 0;
00379 }
00380 }
00381 }
00382
00383 CAliM1543C_ide::~CAliM1543C_ide()
00384 {
00385 stop_threads();
00386 }
00387
00388 void CAliM1543C_ide::ResetPCI()
00389 {
00390 int i;
00391
00392 int j;
00393 CPCIDevice::ResetPCI();
00394
00395 for(i = 0; i < 2; i++)
00396 {
00397 CONTROLLER(i).bm_status = 0;
00398 CONTROLLER(i).selected = 0;
00399 for(j = 0; j < 2; j++)
00400 {
00401 REGISTERS(i, j).error = 0;
00402 COMMAND(i, j).command_in_progress = 0;
00403 COMMAND(i, j).command_cycle = 0;
00404 STATUS(i, j).busy = false;
00405 STATUS(i, j).drive_ready = false;
00406 STATUS(i, j).drq = false;
00407 STATUS(i, j).err = false;
00408 STATUS(i, j).index_pulse = false;
00409 STATUS(i, j).index_pulse_count = 0;
00410 STATUS(i, j).seek_complete = false;
00411 PER_DRIVE(i, j).multiple_size = 1;
00412 set_signature(i, j);
00413 }
00414 }
00415 }
00416
00417 void CAliM1543C_ide::register_disk(class CDisk* dsk, int bus, int dev)
00418 {
00419 CDiskController::register_disk(dsk, bus, dev);
00420 if(dsk->cdrom())
00421 {
00422 dsk->scsi_register(0, scsi_bus[bus], dev);
00423 dsk->set_atapi_mode();
00424 }
00425 }
00426
00427 static u32 ide_magic1 = 0xB222654D;
00428 static u32 ide_magic2 = 0xD456222C;
00429
00433 int CAliM1543C_ide::SaveState(FILE* f)
00434 {
00435 long ss = sizeof(state);
00436 int res;
00437
00438 if(res = CPCIDevice::SaveState(f))
00439 return res;
00440
00441 fwrite(&ide_magic1, sizeof(u32), 1, f);
00442 fwrite(&ss, sizeof(long), 1, f);
00443 fwrite(&state, sizeof(state), 1, f);
00444 fwrite(&ide_magic2, sizeof(u32), 1, f);
00445 printf("%s: %d bytes saved.\n", devid_string, (int) ss);
00446 return 0;
00447 }
00448
00452 int CAliM1543C_ide::RestoreState(FILE* f)
00453 {
00454 long ss;
00455 u32 m1;
00456 u32 m2;
00457 int res;
00458 size_t r;
00459
00460 if(res = CPCIDevice::RestoreState(f))
00461 return res;
00462
00463 r = fread(&m1, sizeof(u32), 1, f);
00464 if(r != 1)
00465 {
00466 printf("%s: unexpected end of file!\n", devid_string);
00467 return -1;
00468 }
00469
00470 if(m1 != ide_magic1)
00471 {
00472 printf("%s: MAGIC 1 does not match!\n", devid_string);
00473 return -1;
00474 }
00475
00476 fread(&ss, sizeof(long), 1, f);
00477 if(r != 1)
00478 {
00479 printf("%s: unexpected end of file!\n", devid_string);
00480 return -1;
00481 }
00482
00483 if(ss != sizeof(state))
00484 {
00485 printf("%s: STRUCT SIZE does not match!\n", devid_string);
00486 return -1;
00487 }
00488
00489 fread(&state, sizeof(state), 1, f);
00490 if(r != 1)
00491 {
00492 printf("%s: unexpected end of file!\n", devid_string);
00493 return -1;
00494 }
00495
00496 r = fread(&m2, sizeof(u32), 1, f);
00497 if(r != 1)
00498 {
00499 printf("%s: unexpected end of file!\n", devid_string);
00500 return -1;
00501 }
00502
00503 if(m2 != ide_magic2)
00504 {
00505 printf("%s: MAGIC 1 does not match!\n", devid_string);
00506 return -1;
00507 }
00508
00509 printf("%s: %d bytes restored.\n", devid_string, (int) ss);
00510 return 0;
00511 }
00512
00513
00514
00515
00516 u32 CAliM1543C_ide::ReadMem_Legacy(int index, u32 address, int dsize)
00517 {
00518 int channel = 0;
00519 switch(index)
00520 {
00521 case SEC_COMMAND:
00522 channel = 1;
00523
00524 case PRI_COMMAND:
00525 return ide_command_read(channel, address, dsize);
00526
00527 case SEC_CONTROL:
00528 channel = 1;
00529
00530 case PRI_CONTROL:
00531 return ide_control_read(channel, address);
00532
00533 case SEC_BUSMASTER:
00534 channel = 1;
00535
00536 case PRI_BUSMASTER:
00537 return ide_busmaster_read(channel, address, dsize);
00538 }
00539
00540 return 0;
00541 }
00542
00543 void CAliM1543C_ide::WriteMem_Legacy(int index, u32 address, int dsize, u32 data)
00544 {
00545 int channel = 0;
00546 switch(index)
00547 {
00548 case SEC_COMMAND:
00549 channel = 1;
00550
00551 case PRI_COMMAND:
00552 ide_command_write(channel, address, dsize, data);
00553 break;
00554
00555 case SEC_CONTROL:
00556 channel = 1;
00557
00558 case PRI_CONTROL:
00559 ide_control_write(channel, address, data);
00560 break;
00561
00562 case SEC_BUSMASTER:
00563 channel = 1;
00564
00565 case PRI_BUSMASTER:
00566 ide_busmaster_write(channel, address, dsize, data);
00567 break;
00568 }
00569 }
00570
00571 u32 CAliM1543C_ide::ReadMem_Bar(int func, int bar, u32 address, int dsize)
00572 {
00573 int channel = 0;
00574 switch(bar)
00575 {
00576 case BAR_SEC_COMMAND:
00577 channel = 1;
00578
00579 case BAR_PRI_COMMAND:
00580 return ide_command_read(channel, address, dsize);
00581
00582 case BAR_SEC_CONTROL:
00583 channel = 1;
00584
00585 case BAR_PRI_CONTROL:
00586
00587
00588 return ide_control_read(channel, address - 2);
00589
00590 case BAR_BUSMASTER:
00591 if(address < 8)
00592 return ide_busmaster_read(0, address, dsize);
00593 else
00594 return ide_busmaster_read(1, address - 8, dsize);
00595 }
00596
00597 return 0;
00598 }
00599
00600 void CAliM1543C_ide::WriteMem_Bar(int func, int bar, u32 address, int dsize,
00601 u32 data)
00602 {
00603 int channel = 0;
00604 switch(bar)
00605 {
00606 case BAR_SEC_COMMAND:
00607 channel = 1;
00608
00609 case BAR_PRI_COMMAND:
00610 ide_command_write(channel, address, dsize, data);
00611 return;
00612
00613 case BAR_SEC_CONTROL:
00614 channel = 1;
00615
00616 case BAR_PRI_CONTROL:
00617
00618 ide_control_write(channel, address - 2, data);
00619 return;
00620
00621 case BAR_BUSMASTER:
00622 if(address < 8)
00623 return ide_busmaster_write(0, address, data, dsize);
00624 else
00625 return ide_busmaster_write(1, address - 8, data, dsize);
00626 }
00627 }
00628
00629
00630
00631
00632 u32 CAliM1543C_ide::ide_command_read(int index, u32 address, int dsize)
00633 {
00634 u32 data = 0;
00635 if(!get_disk(index, 0) && !get_disk(index, 1))
00636 {
00637
00638
00639
00640 return 0xffffffff;
00641 }
00642
00643 switch(address)
00644 {
00645 case REG_COMMAND_DATA:
00646 if(!SEL_STATUS(index).drq)
00647 {
00648 #ifdef DEBUG_IDE_REG_COMMAND
00649 printf("Reading from data buffer when data is not ready.\n");
00650 ide_status(index);
00651 PAUSE("WTF");
00652 #endif
00653 break;
00654 }
00655
00656 data = 0;
00657
00658 switch(dsize)
00659 {
00660 case 32:
00661 data = CONTROLLER(index).data[CONTROLLER(index).data_ptr++];
00662 data |= CONTROLLER(index).data[CONTROLLER(index).data_ptr++] << 16;
00663 break;
00664
00665 case 16:
00666 data = CONTROLLER(index).data[CONTROLLER(index).data_ptr++];
00667 }
00668
00669 if(CONTROLLER(index).data_ptr >= CONTROLLER(index).data_size)
00670 {
00671
00672
00673 SEL_STATUS(index).drq = false;
00674 if(SEL_COMMAND(index).command_in_progress)
00675 {
00676 SEL_STATUS(index).busy = true;
00677 SEL_STATUS(index).drive_ready = false;
00678 UPDATE_ALT_STATUS(index);
00679 semController[index]->set();
00680 #if defined(DEBUG_IDE_MULTIPLE) || defined(DEBUG_IDE_PACKET)
00681 printf("Command still in progress, waking up controller.\n");
00682 printf("-- Packet Phase: %d\n", SEL_COMMAND(index).packet_phase);
00683 ide_status(index);
00684 #endif
00685 }
00686 }
00687
00688 if(CONTROLLER(index).data_ptr > IDE_BUFFER_SIZE)
00689 {
00690 printf("%%IDE-W-OVERFLOW: data pointer past end of buffer, setting to 0.\n");
00691 CONTROLLER(index).data_ptr = 0;
00692 SEL_STATUS(index).drq = false;
00693 UPDATE_ALT_STATUS(index);
00694 }
00695 break;
00696
00697 case REG_COMMAND_ERROR:
00698 data = SEL_REGISTERS(index).error;
00699 break;
00700
00701 case REG_COMMAND_SECTOR_COUNT:
00702 data = SEL_REGISTERS(index).sector_count;
00703 break;
00704
00705 case REG_COMMAND_SECTOR_NO:
00706 data = SEL_REGISTERS(index).sector_no;
00707 break;
00708
00709 case REG_COMMAND_CYL_LOW:
00710 data = SEL_REGISTERS(index).cylinder_no & 0xff;
00711 break;
00712
00713 case REG_COMMAND_CYL_HI:
00714 data = (SEL_REGISTERS(index).cylinder_no >> 8) & 0xff;
00715 break;
00716
00717 case REG_COMMAND_DRIVE:
00718 data = 0x80 | (SEL_REGISTERS(index).lba_mode ? 0x40 : 0x00) | 0x20
00719 | (CONTROLLER(index).selected ? 0x10 : 0x00) | (SEL_REGISTERS(index).head_no & 0x0f);
00720 break;
00721
00722 case REG_COMMAND_STATUS:
00723
00724
00725 data = get_status(index);
00726 theAli->pic_deassert(1, 6 + index);
00727 #ifdef DEBUG_IDE_INTERRUPT
00728 printf("%%IDE-I-INTERRUPT: Interrupt Acknowledged on %d.\n",index);
00729 #endif
00730 break;
00731 }
00732
00733 #ifdef DEBUG_IDE_REG_COMMAND
00734 if(address != 0)
00735 {
00736 printf("%%IDE-I-REGCMD: Read from command register %d (%s) on controller %d, value: %x\n",
00737 address, register_names[address], index, data);
00738 }
00739 #endif
00740 return data;
00741 }
00742
00743 void CAliM1543C_ide::ide_command_write(int index, u32 address, int dsize,
00744 u32 data)
00745 {
00746 #ifdef DEBUG_IDE_REG_COMMAND
00747 if(address != 0)
00748 {
00749 printf("%%IDE-I-REGCMD: Write to command register %d (%s) on controller %d, value: %x\n",
00750 address, register_names[address], index, data);
00751 }
00752
00753 SEL_STATUS(index).debug_status_update = true;
00754 #endif
00755 switch(address)
00756 {
00757 case REG_COMMAND_DATA:
00758 if(!SEL_STATUS(index).drq)
00759 {
00760 #ifdef DEBUG_IDE_REG_COMMAND
00761 printf("%%IDE-I-DATA: Unrequested data written to data port: %x\n", data);
00762 ide_status(index);
00763 #endif
00764 break;
00765 }
00766
00767 switch(dsize)
00768 {
00769 case 32:
00770 CONTROLLER(index).data[CONTROLLER(index).data_ptr++] = data & 0xffff;
00771 CONTROLLER(index).data[CONTROLLER(index).data_ptr++] =
00772 (
00773 data >>
00774 16
00775 ) & 0xffff;
00776 break;
00777
00778 case 16:
00779 CONTROLLER(index).data[CONTROLLER(index).data_ptr++] = data & 0xffff;
00780 }
00781
00782 if(CONTROLLER(index).data_ptr >= CONTROLLER(index).data_size)
00783 {
00784
00785
00786 SEL_STATUS(index).drq = false;
00787 SEL_STATUS(index).busy = true;
00788 UPDATE_ALT_STATUS(index);
00789 semController[index]->set();
00790 }
00791
00792 if(CONTROLLER(index).data_ptr > IDE_BUFFER_SIZE)
00793 {
00794 printf("%%IDE-W-OVERFLOW: data pointer overflow, setting to 0.\n");
00795 CONTROLLER(index).data_ptr = 0;
00796 SEL_STATUS(index).drq = false;
00797 UPDATE_ALT_STATUS(index);
00798 }
00799 break;
00800
00801 case REG_COMMAND_FEATURES:
00802 REGISTERS(index, 0).features = data;
00803 REGISTERS(index, 1).features = data;
00804 break;
00805
00806 case REG_COMMAND_SECTOR_COUNT:
00807 REGISTERS(index, 0).sector_count = REGISTERS(index, 1).sector_count = data & 0xff;
00808 break;
00809
00810 case REG_COMMAND_SECTOR_NO:
00811 REGISTERS(index, 0).sector_no = REGISTERS(index, 1).sector_no = data & 0xff;
00812 break;
00813
00814 case REG_COMMAND_CYL_LOW:
00815 REGISTERS(index, 0).cylinder_no = REGISTERS(index, 1).cylinder_no =
00816 (REGISTERS(index, 1).cylinder_no & 0xff00) |
00817 (data & 0xff);
00818 break;
00819
00820 case REG_COMMAND_CYL_HI:
00821 REGISTERS(index, 0).cylinder_no = REGISTERS(index, 1).cylinder_no =
00822 (REGISTERS(index, 1).cylinder_no & 0xff) |
00823 ((data << 8) & 0xff00);
00824 break;
00825
00826 case REG_COMMAND_DRIVE:
00827 if(((data >> 4) & 1) != CONTROLLER(index).selected)
00828 #ifdef DEBUG_IDE
00829 printf("Setting selected device on %d to: %d. val=%02x\n", index,
00830 (data >> 4) & 1, data);
00831 #endif
00832 CONTROLLER(index).selected = (data >> 4) & 1;
00833 REGISTERS(index, 0).head_no = REGISTERS(index, 1).head_no = data & 0x0f;
00834 REGISTERS(index, 0).lba_mode = REGISTERS(index, 1).lba_mode =
00835 (
00836 data >>
00837 6
00838 ) & 1;
00839
00840 break;
00841
00842 case REG_COMMAND_COMMAND:
00843 theAli->pic_deassert(1, 6 + index);
00844 if(!SEL_DISK(index))
00845 {
00846 #ifdef DEBUG_IDE
00847 printf("%%IDE-I-NODEV: Command to non-existing device %d.%d. cmd=%x\n",
00848 index, CONTROLLER(index).selected, data);
00849 #endif
00850 }
00851
00852 if(SEL_COMMAND(index).command_in_progress == true)
00853 {
00854
00855
00856 #ifdef DEBUG_IDE
00857 printf("%%IDE-W-CIP: Command is already in progress.\n");
00858 PAUSE("dang it!");
00859 #endif
00860 }
00861
00862 if((data & 0xf0) == 0x10)
00863 data = 0x10;
00864
00865 SEL_COMMAND(index).command_in_progress = false;
00866 SEL_COMMAND(index).current_command = data;
00867 #ifdef DEBUG_IDE_CMD
00868 printf("%%IDE-I-CMD: Command %02x issued on controller %d, disk %d.\n",data,index, CONTROLLER(index).selected);
00869 #endif
00870 SEL_COMMAND(index).command_cycle = 0;
00871 SEL_STATUS(index).drq = false;
00872 UPDATE_ALT_STATUS(index);
00873 CONTROLLER(index).data_ptr = 0;
00874
00875 if(data != 0x00)
00876 {
00877 SEL_STATUS(index).busy = true;
00878 UPDATE_ALT_STATUS(index);
00879 SEL_COMMAND(index).command_in_progress = true;
00880 SEL_COMMAND(index).packet_phase = PACKET_NONE;
00881 semController[index]->set();
00882 }
00883 else
00884 {
00885
00886
00887
00888 if(SEL_DISK(index))
00889 command_aborted(index, data);
00890 }
00891 break;
00892 }
00893 }
00894
00895 u32 CAliM1543C_ide::ide_control_read(int index, u32 address)
00896 {
00897 u32 data = 0;
00898 switch(address)
00899 {
00900 case 0:
00901 {
00902 SCOPED_READ_LOCK(mtRegisters[index]);
00903 data = SEL_STATUS(index).alt_status;
00904 }
00905 #ifdef DEBUG_IDE_REG_CONTROL
00906 static u32 last_data = 0;
00907 if(last_data != data)
00908 {
00909 printf("%%IDE-I-READCTRL: alternate status on IDE control %d: 0x%02x\n",
00910 index, data);
00911 }
00912
00913 last_data = data;
00914 #endif
00915 break;
00916
00917 case 1:
00918
00919
00920 data |= (CONTROLLER(index).selected == 0) ? 1 : 2;
00921 data |= (SEL_REGISTERS(index).head_no) << 2;
00922 data = (~data) & 0xff;
00923 #ifdef DEBUG_IDE_REG_CONTROL
00924 printf("%%IDE-I-READCTRL: drive address port on IDE control %d: 0x%02x\n",
00925 index, data);
00926 #endif
00927 break;
00928 }
00929
00930 return data;
00931 }
00932
00936 void CAliM1543C_ide::ide_control_write(int index, u32 address, u32 data)
00937 {
00938 bool prev_reset;
00939 #ifdef DEBUG_IDE_REG_CONTROL
00940 printf("%%IDE-I-WRITCTRL: write port %d on IDE control %d: 0x%02x\n",
00941 (u32) (address), index, data);
00942 #endif
00943 switch(address)
00944 {
00945 case 0:
00946 prev_reset = CONTROLLER(index).reset;
00947 CONTROLLER(index).reset = (data >> 2) & 1;
00948 CONTROLLER(index).disable_irq = (data >> 1) & 1;
00949
00950 if(!prev_reset && CONTROLLER(index).reset)
00951 {
00952 #ifdef DEBUG_IDE_REG_CONTROL
00953 printf("IDE reset on index %d started.\n", index);
00954 #endif
00955 STATUS(index, 0).busy = true;
00956 STATUS(index, 0).drive_ready = false;
00957 STATUS(index, 0).seek_complete = true;
00958 STATUS(index, 0).drq = false;
00959 STATUS(index, 0).err = false;
00960 COMMAND(index, 0).current_command = 0;
00961 COMMAND(index, 0).command_in_progress = false;
00962 STATUS(index, 1).busy = true;
00963 STATUS(index, 1).drive_ready = false;
00964 STATUS(index, 1).seek_complete = true;
00965 STATUS(index, 1).drq = false;
00966 STATUS(index, 1).err = false;
00967 COMMAND(index, 1).current_command = 0;
00968 COMMAND(index, 1).command_in_progress = false;
00969
00970 CONTROLLER(index).reset_in_progress = true;
00971 SEL_REGISTERS(index).error = 0x01;
00972 COMMAND(index, 0).current_command = 0;
00973 CONTROLLER(index).disable_irq = false;
00974 }
00975 else if(prev_reset && !CONTROLLER(index).reset)
00976 {
00977 #ifdef DEBUG_IDE_REG_CONTROL
00978 printf("IDE reset on index %d ended.\n", index);
00979 #endif
00980 STATUS(index, 0).busy = false;
00981 STATUS(index, 0).drive_ready = true;
00982 STATUS(index, 1).busy = false;
00983 STATUS(index, 1).drive_ready = true;
00984 CONTROLLER(index).reset_in_progress = false;
00985
00986 set_signature(index, 0);
00987 set_signature(index, 1);
00988 }
00989 break;
00990
00991 case 1:
00992
00993
00994 break;
00995 }
00996 }
00997
01001 u32 CAliM1543C_ide::ide_busmaster_read(int index, u32 address, int dsize)
01002 {
01003 u32 data = 0;
01004 switch(dsize)
01005 {
01006 case 8:
01007 data = CONTROLLER(index).busmaster[address];
01008 break;
01009
01010 case 32:
01011 data = *(u32 *) (&CONTROLLER(index).busmaster[address]);
01012 break;
01013
01014 default:
01015 FAILURE(InvalidArgument, "16-bit read from busmaster");
01016 break;
01017 }
01018
01019 #ifdef DEBUG_IDE_BUSMASTER
01020 printf("%%IDE-I-READBUSM: read port %d on IDE bus master %d: 0x%02x, %d bytes\n",
01021 (u32) (address), index, data, dsize / 8);
01022 #endif
01023 return data;
01024 }
01025
01029 void CAliM1543C_ide::ide_busmaster_write(int index, u32 address, u32 data,
01030 int dsize)
01031 {
01032 #ifdef DEBUG_IDE_BUSMASTER
01033 if(!(dsize == 8 && (address >= 4 && address <= 7)))
01034 {
01035 printf("%%IDE-I-WRITBUSM: write port %d on IDE bus master %d: 0x%02x, %d bytes\n",
01036 (u32) (address), index, data, dsize / 8);
01037 }
01038 #endif
01039
01040 u32 prd_address;
01041
01042
01043 switch(dsize)
01044 {
01045 case 32:
01046 ide_busmaster_write(index, address, data & 0xff, 8);
01047 ide_busmaster_write(index, address + 1, (data >> 8) & 0xff, 8);
01048 ide_busmaster_write(index, address + 2, (data >> 16) & 0xff, 8);
01049 ide_busmaster_write(index, address + 3, (data >> 24) & 0xff, 8);
01050 return;
01051
01052 case 16:
01053 ide_busmaster_write(index, address, data & 0xff, 8);
01054 ide_busmaster_write(index, address + 1, (data >> 8) & 0xff, 8);
01055 return;
01056 }
01057
01058 switch(address)
01059 {
01060 case 0:
01061 #ifdef DEBUG_IDE_BUSMASTER
01062 printf("%%IDE-I-BUSM: Bus master command got data: %x (%s,%s)\n", data,
01063 (data & 0x08 ? "write" : "read"), (data & 0x01 ? "start" : "stop"));
01064 #endif
01065
01066
01067 CONTROLLER(index).busmaster[0] = data & 0x09;
01068 if(data & 0x01)
01069 {
01070
01071
01072 CONTROLLER(index).busmaster[2] |= 0x01;
01073 semBusMaster[index]->set();
01074 }
01075 else
01076 {
01077
01078
01079 CONTROLLER(index).busmaster[2] &= 0xfe;
01080 }
01081 break;
01082
01083 case 2:
01084
01085
01086
01087
01088
01089
01090
01091 CONTROLLER(index).busmaster[2] = data & 0x67;
01092 if(data & 0x04)
01093 CONTROLLER(index).busmaster[2] &= ~0x04;
01094 if(data & 0x02)
01095 CONTROLLER(index).busmaster[2] &= ~0x02;
01096 if(data & 0x01)
01097 CONTROLLER(index).busmaster[2] &= ~0x01;
01098 break;
01099
01100 case 4:
01101 case 5:
01102 case 6:
01103 CONTROLLER(index).busmaster[address] = data;
01104 break;
01105
01106 case 7:
01107 CONTROLLER(index).busmaster[address] = data;
01108 prd_address = endian_32(*(u32 *) (&CONTROLLER(index).busmaster[4]));
01109 #ifdef DEBUG_IDE_BUSMASTER
01110 printf("%%IDE-I-PRD: Virtual address: %"LL "x \n",
01111 endian_32(*(u32 *) (&CONTROLLER(index).busmaster[4])));
01112 printf("-IDE-I-PRD: Physical address: %"LL "x \n", prd_address);
01113 u32 base, control;
01114 do
01115 {
01116 do_pci_read(prd_address, &base, 4, 1);
01117 do_pci_read(prd_address + 4, &control, 4, 1);
01118 printf("-IDE-I-PRD: base: %x, control: %x \n", base, control);
01119 prd_address += 8;
01120 } while(base & 0x80 == 0);
01121 #endif
01122 break;
01123
01124 default:
01125 break;
01126 }
01127 }
01128
01129 void CAliM1543C_ide::set_signature(int index, int id)
01130 {
01131
01132
01133 REGISTERS(index, id).head_no = 0;
01134 REGISTERS(index, id).sector_count = 1;
01135 REGISTERS(index, id).sector_no = 1;
01136 if(get_disk(index, id))
01137 {
01138 if(!get_disk(index, id)->cdrom())
01139 {
01140 REGISTERS(index, id).cylinder_no = 0;
01141 CONTROLLER(index).selected = 0;
01142 }
01143 else
01144 {
01145 REGISTERS(index, id).cylinder_no = 0xeb14;
01146 }
01147 }
01148 else
01149 {
01150 REGISTERS(index, id).cylinder_no = 0xffff;
01151 }
01152 }
01153
01154 void CAliM1543C_ide::raise_interrupt(int index)
01155 {
01156 if(!CONTROLLER(index).disable_irq)
01157 {
01158 #ifdef DEBUG_IDE_INTERRUPT
01159 printf("%%IDE-I-INTERRUPT: Interrupt raised on controller %d.\n", index);
01160 #endif
01161
01162 #if !defined(IDE_YIELD_INTERRUPTS)
01163 {
01164 SCOPED_WRITE_LOCK(mtBusMaster[index]);
01165 CONTROLLER(index).busmaster[2] |= 0x04;
01166 }
01167 UPDATE_ALT_STATUS(index);
01168 theAli->pic_interrupt(1, 6 + index);
01169 #else
01170 CONTROLLER(index).interrupt_pending=true;
01171 #endif
01172 }
01173 }
01174
01175 u8 CAliM1543C_ide::get_status(int index)
01176 {
01177 u8 data;
01178 if(!SEL_DISK(index))
01179 {
01180 #ifdef DEBUG_IDE_REG_COMMAND
01181 printf("%%IDE-I-STATUS: Read status for nonexiting device %d.%d\n", index,
01182 CONTROLLER(index).selected);
01183 #endif
01184 return 0;
01185 }
01186
01187 data = (SEL_STATUS(index).busy ? 0x80 : 0x00) |
01188 (SEL_STATUS(index).drive_ready ? 0x40 : 0x00) |
01189 (SEL_STATUS(index).fault ? 0x20 : 0x00) |
01190 (SEL_STATUS(index).seek_complete ? 0x10 : 0x00) |
01191 (SEL_STATUS(index).drq ? 0x08 : 0x00) |
01192 (SEL_STATUS(index).index_pulse ? 0x02 : 0x00) |
01193 (SEL_STATUS(index).err ? 0x01 : 0x00);
01194 SEL_STATUS(index).index_pulse_count++;
01195 SEL_STATUS(index).index_pulse = false;
01196 if(SEL_STATUS(index).index_pulse_count >= 10)
01197 {
01198 SEL_STATUS(index).index_pulse_count = 0;
01199 SEL_STATUS(index).index_pulse = true;
01200 }
01201
01202 #ifdef DEBUG_IDE_REG_COMMAND
01203 if((SEL_STATUS(index).debug_last_status & 0xfd) != (data & 0xfd)
01204 || SEL_STATUS(index).debug_status_update)
01205 {
01206 printf("%%IDE-I-STATUS: Controller %d status: %x = %s %s %s %s %s %s %s\n",
01207 index, data, SEL_STATUS(index).busy ? "busy" : "",
01208 SEL_STATUS(index).drive_ready ? "drdy" : "",
01209 SEL_STATUS(index).fault ? "fault" : "",
01210 SEL_STATUS(index).seek_complete ? "seek_complete" : "",
01211 SEL_STATUS(index).drq ? "drq" : "",
01212 SEL_STATUS(index).index_pulse ? "pulse" : "",
01213 SEL_STATUS(index).err ? "error" : "");
01214 SEL_STATUS(index).debug_status_update = false;
01215 }
01216
01217 SEL_STATUS(index).debug_last_status = data;
01218 #endif
01219 return data;
01220 }
01221
01222 void CAliM1543C_ide::identify_drive(int index, bool packet)
01223 {
01224 char serial_number[21];
01225 char model_number[41];
01226 char rev_number[9];
01227 size_t i;
01228
01229
01230 for(i = 0; i < 256; i++)
01231 CONTROLLER(index).data[i] = 0;
01232
01233 CONTROLLER(index).data_ptr = 0;
01234 CONTROLLER(index).data_size = 256;
01235
01236
01237 if(!packet)
01238 {
01239
01240
01241 CONTROLLER(index).data[0] = SEL_DISK(index)->cdrom() ? 0x0080 : 0x0040;
01242 }
01243 else
01244 {
01245
01246
01247
01248 CONTROLLER(index).data[0] = 0x8580;
01249 }
01250
01251
01252 if(SEL_DISK(index)->get_cylinders() > 16383)
01253 CONTROLLER(index).data[1] = 16383;
01254 else
01255 CONTROLLER(index).data[1] = (u16) (SEL_DISK(index)->get_cylinders());
01256
01257
01258 CONTROLLER(index).data[3] = (u16) (SEL_DISK(index)->get_heads());
01259
01260
01261 CONTROLLER(index).data[6] = (u16) (SEL_DISK(index)->get_sectors());
01262
01263
01264 strcpy(serial_number, " ");
01265 i = strlen(SEL_DISK(index)->get_serial());
01266 i = (i > 20) ? 20 : i;
01267 memcpy(model_number, SEL_DISK(index)->get_serial(), i);
01268 for(i = 0; i < 10; i++)
01269 CONTROLLER(index).data[10 + i] =
01270 (
01271 serial_number[i * 2] <<
01272 8
01273 ) |
01274 serial_number[i * 2 + 1];
01275
01276
01277 strcpy(rev_number, " ");
01278 i = strlen(SEL_DISK(index)->get_rev());
01279 i = (i > 8) ? 8 : i;
01280 memcpy(model_number, SEL_DISK(index)->get_rev(), i);
01281 for(i = 0; i < 4; i++)
01282 CONTROLLER(index).data[23 + i] =
01283 (
01284 rev_number[i * 2] <<
01285 8
01286 ) |
01287 rev_number[i * 2 + 1];
01288
01289
01290 strcpy(model_number, " ");
01291 i = strlen(SEL_DISK(index)->get_model());
01292 i = (i > 40) ? 40 : i;
01293 memcpy(model_number, SEL_DISK(index)->get_model(), i);
01294 for(i = 0; i < 20; i++)
01295 CONTROLLER(index).data[i + 27] =
01296 (
01297 model_number[i * 2] <<
01298 8
01299 ) |
01300 model_number[i * 2 + 1];
01301
01302
01303 CONTROLLER(index).data[47] = 0x8000 | MAX_MULTIPLE_SECTORS;
01304
01305
01306 if(!packet)
01307 {
01308 CONTROLLER(index).data[49] = 0x0300;
01309 }
01310 else
01311 {
01312 CONTROLLER(index).data[49] = 0x0b00;
01313 }
01314
01315
01316 CONTROLLER(index).data[50] = 0x4000;
01317
01318
01319 CONTROLLER(index).data[51] = 0x0300;
01320
01321
01322 CONTROLLER(index).data[53] = 7;
01323
01324
01325 CONTROLLER(index).data[54] = (u16) (SEL_DISK(index)->get_cylinders());
01326 CONTROLLER(index).data[55] = (u16) (SEL_DISK(index)->get_heads());
01327 CONTROLLER(index).data[56] = (u16) (SEL_DISK(index)->get_sectors());
01328 CONTROLLER(index).data[57] = (u16)
01329 (SEL_DISK(index)->get_chs_size() >> 0) & 0xFFFF;
01330 CONTROLLER(index).data[58] = (u16)
01331 (SEL_DISK(index)->get_chs_size() >> 16) & 0xFFFF;
01332
01333
01334 if(SEL_PER_DRIVE(index).multiple_size != 0)
01335 {
01336 CONTROLLER(index).data[59] = 0x0100 | SEL_PER_DRIVE(index).multiple_size;
01337 }
01338 else
01339 {
01340 CONTROLLER(index).data[59] = 0x0000;
01341 }
01342
01343
01344 CONTROLLER(index).data[60] = (u16)
01345 (SEL_DISK(index)->get_lba_size() >> 0) & 0xFFFF;
01346 CONTROLLER(index).data[61] = (u16)
01347 (SEL_DISK(index)->get_lba_size() >> 16) & 0xFFFF;
01348
01349
01350
01351 if(usedma)
01352 CONTROLLER(index).data[63] = CONTROLLER(index).dma_mode << 8 | 0x01;
01353 else
01354 CONTROLLER(index).data[63] = CONTROLLER(index).dma_mode << 8 | 0x00;
01355
01356
01357 CONTROLLER(index).data[64] = 0x0002;
01358
01359
01360 CONTROLLER(index).data[65] = 480;
01361 CONTROLLER(index).data[66] = 480;
01362 CONTROLLER(index).data[67] = 120;
01363 CONTROLLER(index).data[68] = 120;
01364 if(packet)
01365 {
01366
01367
01368 CONTROLLER(index).data[71] = 120;
01369
01370
01371 CONTROLLER(index).data[72] = 120;
01372 }
01373
01374
01375 CONTROLLER(index).data[75] = 0;
01376
01377
01378 CONTROLLER(index).data[80] = 0x001e;
01379
01380
01381 CONTROLLER(index).data[81] = 0x0017;
01382
01383
01384 CONTROLLER(index).data[82] = SEL_DISK(index)->cdrom() ? 0x4014 : 0x4000;
01385
01386
01387 CONTROLLER(index).data[83] = 0x4000;
01388 CONTROLLER(index).data[84] = 0x4000;
01389
01390
01391 CONTROLLER(index).data[85] = SEL_DISK(index)->cdrom() ? 0x4014 : 0x4000;
01392 CONTROLLER(index).data[86] = 0x4000;
01393 CONTROLLER(index).data[87] = 0x4000;
01394
01395
01396
01397 CONTROLLER(index).data[88] = 0x0000;
01398 }
01399
01400 void CAliM1543C_ide::command_aborted(int index, u8 command)
01401 {
01402 printf("ide%d.%d aborting on command 0x%02x \n", index,
01403 CONTROLLER(index).selected, command);
01404 SEL_STATUS(index).busy = false;
01405 SEL_STATUS(index).drive_ready = true;
01406 SEL_STATUS(index).err = true;
01407 SEL_STATUS(index).drq = false;
01408 SEL_REGISTERS(index).error |= 0x04;
01409 CONTROLLER(index).data_ptr = 0;
01410 SEL_COMMAND(index).command_in_progress = false;
01411 UPDATE_ALT_STATUS(index);
01412 raise_interrupt(index);
01413 }
01414
01415 CAliM1543C_ide* theIDE = 0;
01416
01417 void CAliM1543C_ide::ide_status(int index)
01418 {
01419 printf("IDE %d.%d: [busy: %d, drdy: %d, flt: %d, drq: %d, err: %d]\n"
01420 " [c: %d, h: %d, s: %d, #: %d, f: %x, lba: %d]\n"
01421 " [ptr: %d, size: %d, error: %d, cmd: %x, in progress: %d]\n"
01422 " [cycle: %d, pkt phase: %d, pkt cmd: %x, dma: %d]\n"
01423 " [bm-cmd: %x bm-stat: %x]\n", index,
01424 CONTROLLER(index).selected, SEL_STATUS(index).busy,
01425 SEL_STATUS(index).drive_ready, SEL_STATUS(index).fault,
01426 SEL_STATUS(index).drq, SEL_STATUS(index).err,
01427 SEL_REGISTERS(index).cylinder_no, SEL_REGISTERS(index).head_no,
01428 SEL_REGISTERS(index).sector_no, SEL_REGISTERS(index).sector_count,
01429 SEL_REGISTERS(index).features, (SEL_REGISTERS(index).head_no << 24) | (
01430 SEL_REGISTERS(index).cylinder_no << 8) |
01431 SEL_REGISTERS(index).sector_no, CONTROLLER(index).data_ptr,
01432 CONTROLLER(index).data_size, SEL_REGISTERS(index).error,
01433 SEL_COMMAND(index).current_command & 0xff,
01434 SEL_COMMAND(index).command_in_progress,
01435 SEL_COMMAND(index).command_cycle, SEL_COMMAND(index).packet_phase,
01436 SEL_COMMAND(index).packet_command[0], SEL_COMMAND(index).packet_dma,
01437 CONTROLLER(index).busmaster[0], CONTROLLER(index).busmaster[2]);
01438 }
01439
01443 void CAliM1543C_ide::check_state()
01444 {
01445 if(thrController[0] && !thrController[0]->isRunning())
01446 FAILURE(Thread, "IDE 0 thread has died");
01447 if(thrController[1] && !thrController[1]->isRunning())
01448 FAILURE(Thread, "IDE 1 thread has died");
01449 }
01450
01451 void CAliM1543C_ide::execute(int index)
01452 {
01453 if(SEL_DISK(index) == NULL && SEL_COMMAND(index).current_command != 0x90)
01454 {
01455
01456
01457
01458
01459 SEL_COMMAND(index).command_in_progress = false;
01460 }
01461 else
01462 {
01463 #ifdef DEBUG_IDE_COMMAND
01464 printf("%%IDE-I-COMMAND: Processing command on controller %d.\n", index);
01465 ide_status(index);
01466 #endif
01467 switch(SEL_COMMAND(index).current_command)
01468 {
01469 case 0x00:
01470 SEL_REGISTERS(index).error = 0x04;
01471 SEL_STATUS(index).busy = false;
01472 SEL_STATUS(index).drive_ready = true;
01473 SEL_STATUS(index).fault = true;
01474 SEL_STATUS(index).drq = false;
01475 SEL_STATUS(index).err = true;
01476 SEL_COMMAND(index).command_in_progress = false;
01477 raise_interrupt(index);
01478 printf("got nop on %d.%d\n", index, CONTROLLER(index).selected);
01479
01480
01481 break;
01482
01483 case 0x08:
01484 if(SEL_DISK(index)->cdrom() || 1)
01485 {
01486
01487
01488
01489
01490 SEL_COMMAND(index).command_in_progress = false;
01491 if(CONTROLLER(index).selected == 0)
01492 {
01493 REGISTERS(index, 0).error = 0x01;
01494 REGISTERS(index, 1).error = 0x01;
01495 }
01496 else
01497 {
01498 REGISTERS(index, 1).error = 0x01;
01499 }
01500
01501 set_signature(index, CONTROLLER(index).selected);
01502
01503
01504 SEL_STATUS(index).drq = false;
01505 SEL_STATUS(index).bit_2 = false;
01506 SEL_STATUS(index).err = false;
01507 if(SEL_DISK(index)->cdrom())
01508 {
01509 SEL_STATUS(index).fault = false;
01510 SEL_STATUS(index).drive_ready = false;
01511 }
01512 else
01513 {
01514 SEL_STATUS(index).drive_ready = true;
01515 }
01516
01517 SEL_STATUS(index).busy = false;
01518
01519
01520
01521 }
01522 else
01523 {
01524 command_aborted(index, SEL_COMMAND(index).current_command);
01525 }
01526 break;
01527
01528 case 0x10:
01529 SEL_STATUS(index).busy = false;
01530 SEL_STATUS(index).drive_ready = true;
01531 SEL_STATUS(index).seek_complete = true;
01532 SEL_STATUS(index).fault = false;
01533 SEL_STATUS(index).drq = false;
01534 SEL_STATUS(index).err = false;
01535 SEL_REGISTERS(index).cylinder_no = 0;
01536 SEL_COMMAND(index).command_in_progress = false;
01537 raise_interrupt(index);
01538 break;
01539
01540 case 0x20:
01541 case 0x21:
01542 if(SEL_COMMAND(index).command_cycle == 0)
01543 {
01544
01545
01546 if(SEL_REGISTERS(index).sector_count == 0)
01547 SEL_REGISTERS(index).sector_count = 256;
01548 }
01549
01550 if(!SEL_STATUS(index).drq)
01551 {
01552
01553
01554 if(!SEL_REGISTERS(index).lba_mode)
01555 {
01556 FAILURE(NotImplemented, "Non-LBA disk read");
01557 }
01558 else
01559 {
01560 u32 lba = (SEL_REGISTERS(index).head_no << 24) |
01561 (
01562 SEL_REGISTERS(index).cylinder_no <<
01563 8
01564 ) |
01565 SEL_REGISTERS(index).sector_no;
01566
01567 SEL_DISK(index)->seek_block(lba);
01568 SEL_DISK(index)->read_blocks(&(CONTROLLER(index).data[0]), 1);
01569 #if defined(ES40_BIG_ENDIAN)
01570 for(int i = 0; i < SEL_DISK(index)->get_block_size() / sizeof(u16);
01571 i++)
01572 CONTROLLER(index).data[i] = endian_16(CONTROLLER(index).data[i]);
01573 #endif
01574 SEL_STATUS(index).busy = false;
01575 SEL_STATUS(index).drive_ready = true;
01576 SEL_STATUS(index).fault = false;
01577 SEL_STATUS(index).drq = true;
01578 SEL_STATUS(index).err = false;
01579 CONTROLLER(index).data_ptr = 0;
01580 CONTROLLER(index).data_size = 256;
01581
01582
01583 SEL_REGISTERS(index).sector_count--;
01584 if(SEL_REGISTERS(index).sector_count == 0)
01585 {
01586 SEL_COMMAND(index).command_in_progress = false;
01587 if(SEL_DISK(index)->cdrom())
01588 set_signature(index, CONTROLLER(index).selected);
01589 }
01590 else
01591 {
01592
01593
01594
01595 SEL_REGISTERS(index).sector_no++;
01596 if(SEL_REGISTERS(index).sector_no > 255)
01597 {
01598 SEL_REGISTERS(index).sector_no = 0;
01599 SEL_REGISTERS(index).cylinder_no++;
01600 if(SEL_REGISTERS(index).cylinder_no > 65535)
01601 {
01602 SEL_REGISTERS(index).cylinder_no = 0;
01603 SEL_REGISTERS(index).head_no++;
01604 }
01605 }
01606 }
01607 }
01608
01609 raise_interrupt(index);
01610 }
01611 break;
01612
01613 case 0x30:
01614 case 0x31:
01615 if(SEL_COMMAND(index).command_cycle == 0)
01616 {
01617
01618
01619 if(SEL_DISK(index)->cdrom() || SEL_DISK(index)->ro())
01620 {
01621 printf("%%IDE-W-RO: Write attempt to read-only disk %d.%d.\n", index,
01622 CONTROLLER(index).selected);
01623 command_aborted(index, SEL_COMMAND(index).current_command);
01624 }
01625 else
01626 {
01627 SEL_STATUS(index).drq = true;
01628 SEL_STATUS(index).busy = false;
01629 CONTROLLER(index).data_size = 256;
01630 if(SEL_REGISTERS(index).sector_count == 0)
01631 SEL_REGISTERS(index).sector_count = 256;
01632 }
01633 }
01634 else
01635 {
01636
01637
01638 if(!SEL_STATUS(index).drq)
01639 {
01640
01641
01642 if(!SEL_REGISTERS(index).lba_mode)
01643 {
01644 FAILURE(NotImplemented, "Non-LBA disk write");
01645 }
01646 else
01647 {
01648 u32 lba = (SEL_REGISTERS(index).head_no << 24) |
01649 (
01650 SEL_REGISTERS(index).cylinder_no <<
01651 8
01652 ) |
01653 SEL_REGISTERS(index).sector_no;
01654
01655 #if defined(ES40_BIG_ENDIAN)
01656 {
01657 u16 data[IDE_BUFFER_SIZE];
01658
01659 SEL_DISK(index)->seek_block(lba);
01660 for(int i = 0; i < SEL_DISK(index)->get_block_size() / sizeof(u16);
01661 i++)
01662 data[i] = endian_16(CONTROLLER(index).data[i]);
01663 SEL_DISK(index)->write_blocks(&(data[0]), 1);
01664 }
01665
01666 #else
01667 SEL_DISK(index)->seek_block(lba);
01668 SEL_DISK(index)->write_blocks(&(CONTROLLER(index).data[0]), 1);
01669 #endif
01670 SEL_STATUS(index).busy = false;
01671 SEL_STATUS(index).drive_ready = true;
01672 SEL_STATUS(index).fault = false;
01673 SEL_STATUS(index).drq = true;
01674 SEL_STATUS(index).err = false;
01675 CONTROLLER(index).data_ptr = 0;
01676
01677
01678 SEL_REGISTERS(index).sector_count--;
01679 if(SEL_REGISTERS(index).sector_count == 0)
01680 {
01681
01682
01683 SEL_STATUS(index).drq = false;
01684 SEL_COMMAND(index).command_in_progress = false;
01685 }
01686 else
01687 {
01688
01689
01690
01691 SEL_REGISTERS(index).sector_no++;
01692 if(SEL_REGISTERS(index).sector_no > 255)
01693 {
01694 SEL_REGISTERS(index).sector_no = 0;
01695 SEL_REGISTERS(index).cylinder_no++;
01696 if(SEL_REGISTERS(index).cylinder_no > 65535)
01697 {
01698 SEL_REGISTERS(index).cylinder_no = 0;
01699 SEL_REGISTERS(index).head_no++;
01700 }
01701 }
01702 }
01703 }
01704
01705 raise_interrupt(index);
01706 }
01707 }
01708 break;
01709
01710
01711
01712
01713
01714 case 0x70:
01715 if(SEL_DISK(index)->cdrom())
01716 {
01717 command_aborted(index, SEL_COMMAND(index).current_command);
01718 }
01719 else
01720 {
01721 SEL_STATUS(index).busy = false;
01722 SEL_STATUS(index).drive_ready = true;
01723 SEL_STATUS(index).seek_complete = true;
01724 SEL_STATUS(index).fault = false;
01725 SEL_STATUS(index).drq = false;
01726 SEL_STATUS(index).err = false;
01727 SEL_COMMAND(index).command_in_progress = false;
01728 raise_interrupt(index);
01729 }
01730 break;
01731
01732
01733
01734
01735 case 0x91:
01736 SEL_COMMAND(index).command_in_progress = false;
01737 if(SEL_DISK(index)->cdrom())
01738 {
01739 command_aborted(index, SEL_COMMAND(index).current_command);
01740 }
01741 else
01742 {
01743 #ifdef DEBUG_IDE
01744 printf("Original c: %d, h: %d, s: %d\n",
01745 SEL_DISK(index)->get_cylinders(), SEL_DISK(index)->get_heads(),
01746 SEL_DISK(index)->get_sectors());
01747 printf("Requested c: %d, h: %d, s: %d\n",
01748 SEL_REGISTERS(index).cylinder_no, SEL_REGISTERS(index).head_no + 1,
01749 SEL_REGISTERS(index).sector_count);
01750 #endif
01751 if(SEL_DISK(index)->get_heads() == (SEL_REGISTERS(index).head_no + 1)
01752 && SEL_DISK(index)->get_sectors() == SEL_REGISTERS(index).sector_count)
01753 {
01754
01755
01756 SEL_STATUS(index).busy = false;
01757 SEL_STATUS(index).drive_ready = true;
01758 SEL_STATUS(index).fault = false;
01759 SEL_STATUS(index).drq = false;
01760 SEL_STATUS(index).err = false;
01761 raise_interrupt(index);
01762 }
01763 else
01764 {
01765 #ifdef DEBUG_IDE
01766 PAUSE("INIT DEV PARAMS -- geometry not supported!");
01767 #endif
01768 SEL_STATUS(index).busy = false;
01769 SEL_STATUS(index).drive_ready = true;
01770 SEL_STATUS(index).fault = false;
01771 SEL_STATUS(index).drq = false;
01772 SEL_STATUS(index).err = true;
01773 SEL_REGISTERS(index).error = 0x04;
01774 raise_interrupt(index);
01775 }
01776 }
01777 break;
01778
01779 case 0xa0:
01780
01781
01782
01783
01784
01785 if(!SEL_DISK(index)->cdrom())
01786 {
01787 command_aborted(index, SEL_COMMAND(index).current_command);
01788 }
01789 else
01790 {
01791 if(SEL_REGISTERS(index).features & 0x02)
01792 {
01793
01794
01795 PAUSE("overlapping not supported");
01796 command_aborted(index, SEL_COMMAND(index).current_command);
01797 }
01798 else
01799 {
01800 if(SEL_COMMAND(index).packet_phase == PACKET_NONE)
01801 {
01802
01803
01804 if(!scsi_arbitrate(index))
01805 FAILURE(IllegalState, "ATAPI SCSI bus busy");
01806 if(!scsi_select(index, CONTROLLER(index).selected))
01807 FAILURE(IllegalState, "ATAPI device not responding to selection");
01808 SEL_REGISTERS(index).REASON = IR_CD;
01809 SEL_STATUS(index).busy = false;
01810 SEL_STATUS(index).drq = true;
01811 SEL_STATUS(index).DMRD = false;
01812 SEL_STATUS(index).SERV = false;
01813 CONTROLLER(index).data_ptr = 0;
01814 CONTROLLER(index).data_size = 6;
01815 SEL_COMMAND(index).packet_dma =
01816 (SEL_REGISTERS(index).features & 0x01) ? true : false;
01817 SEL_COMMAND(index).packet_phase = PACKET_DP1;
01818
01819
01820
01821
01822 break;
01823 }
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833 #ifdef DEBUG_IDE_PACKET
01834 printf("Entering Packet state machine %d\n", index);
01835 ide_status(index);
01836 #endif
01837
01838 bool yield = false;
01839 do
01840 {
01841 #ifdef DEBUG_IDE_PACKET
01842 printf("PACKET STATE: %s (%d)\n",
01843 packet_states[SEL_COMMAND(index).packet_phase],
01844 SEL_COMMAND(index).packet_phase);
01845 #endif
01846 switch(SEL_COMMAND(index).packet_phase)
01847 {
01848 case PACKET_DP1:
01849
01850 if(scsi_get_phase(index) != SCSI_PHASE_COMMAND)
01851 FAILURE(IllegalState, "SCSI command phase expected");
01852
01853 memcpy(scsi_xfer_ptr(index, 12), CONTROLLER(index).data, 12);
01854 memcpy(SEL_COMMAND(index).packet_command, CONTROLLER(index).data,
01855 12);
01856 scsi_xfer_done(index);
01857
01858 SEL_COMMAND(index).packet_phase = PACKET_DP2;
01859 SEL_COMMAND(index).packet_buffersize = SEL_REGISTERS(index).cylinder_no;
01860 SEL_STATUS(index).busy = true;
01861 break;
01862
01863 case PACKET_DP2:
01864 SEL_STATUS(index).busy = true;
01865 SEL_STATUS(index).drq = false;
01866
01867 if(SEL_COMMAND(index).command_in_progress)
01868 {
01869 switch(scsi_get_phase(index))
01870 {
01871 case SCSI_PHASE_DATA_IN:
01872 {
01873 size_t num_bytes = scsi_expected_xfer(index);
01874 void* data_ptr = scsi_xfer_ptr(index, num_bytes);
01875 memcpy(CONTROLLER(index).data, data_ptr, num_bytes);
01876 scsi_xfer_done(index);
01877 SEL_COMMAND(index).packet_phase = PACKET_DP34;
01878 SEL_REGISTERS(index).BYTE_COUNT = (int) num_bytes;
01879 CONTROLLER(index).data_size = (int) num_bytes / 2;
01880 CONTROLLER(index).data_ptr = 0;
01881 }
01882 break;
01883
01884 case SCSI_PHASE_DATA_OUT:
01885 FAILURE(NotImplemented,
01886 "ATAPI for now does not support write operations");
01887 break;
01888
01889 case SCSI_PHASE_STATUS:
01890 scsi_xfer_ptr(index, scsi_expected_xfer(index));
01891 scsi_xfer_done(index);
01892 if(scsi_get_phase(index) != SCSI_PHASE_FREE)
01893 FAILURE(IllegalState, "SCSI bus free phase expected");
01894 SEL_COMMAND(index).packet_phase = PACKET_DI;
01895 break;
01896
01897 default:
01898 FAILURE(IllegalState, "Unexpected SCSI phase");
01899 }
01900 }
01901 else
01902 {
01903
01904
01905 #if defined(DEBUG_IDE_PACKET)
01906 printf("Transition into idle state from DP2.\n");
01907 #endif
01908 SEL_COMMAND(index).packet_phase = PACKET_DI;
01909 }
01910 break;
01911
01912 case PACKET_DP34:
01913 if(SEL_COMMAND(index).packet_dma)
01914 {
01915
01916
01917 #ifdef DEBUG_IDE_PACKET
01918 printf("Sending ATAPI data back via DMA.\n");
01919 #endif
01920
01921 u8 status = do_dma_transfer(index,
01922 (u8 *) (&CONTROLLER(index).data[0]),
01923 SEL_REGISTERS(index).BYTE_COUNT,
01924 false);
01925 if(scsi_get_phase(index) != SCSI_PHASE_STATUS)
01926 FAILURE(IllegalState, "SCSI status phase expected");
01927 scsi_xfer_ptr(index, scsi_expected_xfer(index));
01928 scsi_xfer_done(index);
01929 if(scsi_get_phase(index) != SCSI_PHASE_FREE)
01930 FAILURE(IllegalState, "SCSI bus free phase expected");
01931 SEL_STATUS(index).drq = true;
01932 SEL_STATUS(index).busy = false;
01933 SEL_COMMAND(index).packet_phase = PACKET_DI;
01934 }
01935 else
01936 {
01937
01938
01939 #ifdef DEBUG_IDE_PACKET
01940 printf("Sending ATAPI data back via PIO.\n");
01941 #endif
01942 #if 0
01943 if((!SEL_STATUS(index).drq) && (CONTROLLER(index).data_ptr == 0))
01944 {
01945
01946
01947
01948 SEL_STATUS(index).drq = true;
01949 SEL_STATUS(index).busy = false;
01950 SEL_REGISTERS(index).REASON = IR_IO;
01951 raise_interrupt(index);
01952 yield = true;
01953 }
01954 else
01955 {
01956 if(!SEL_STATUS(index).drq)
01957 {
01958
01959
01960
01961
01962 if(scsi_get_phase(index) != SCSI_PHASE_STATUS)
01963 FAILURE(IllegalState, "SCSI status phase expected");
01964 scsi_xfer_ptr(index, scsi_expected_xfer(index));
01965 scsi_xfer_done(index);
01966 if(scsi_get_phase(index) != SCSI_PHASE_FREE)
01967 FAILURE(IllegalState, "SCSI bus free phase expected");
01968 #ifdef DEBUG_IDE_PACKET
01969 printf("Finished transferring!\n");
01970 #endif
01971 SEL_COMMAND(index).packet_phase = PACKET_DI;
01972 yield = false;
01973 }
01974 }
01975
01976 #else
01977
01978
01979 SEL_STATUS(index).drq = true;
01980 SEL_STATUS(index).busy = false;
01981 SEL_REGISTERS(index).REASON = IR_IO;
01982 if(scsi_get_phase(index) != SCSI_PHASE_STATUS)
01983 FAILURE(IllegalState, "SCSI status phase expected");
01984 scsi_xfer_ptr(index, scsi_expected_xfer(index));
01985 scsi_xfer_done(index);
01986 if(scsi_get_phase(index) != SCSI_PHASE_FREE)
01987 FAILURE(IllegalState, "SCSI Bus free phase expected");
01988 #ifdef DEBUG_IDE_PACKET
01989 printf("Finished Transferring\n");
01990 #endif
01991 raise_interrupt(index);
01992 SEL_COMMAND(index).packet_phase = PACKET_DI;
01993 yield = true;
01994 #endif
01995 }
01996 break;
01997
01998 case PACKET_DI:
01999
02000
02001 SEL_REGISTERS(index).REASON = IR_CD | IR_IO;
02002 SEL_STATUS(index).busy = false;
02003 SEL_STATUS(index).drive_ready = true;
02004 SEL_STATUS(index).SERV = false;
02005 SEL_STATUS(index).CHK = false;
02006 SEL_STATUS(index).drq = false;
02007 raise_interrupt(index);
02008 SEL_COMMAND(index).command_in_progress = false;
02009 yield = true;
02010 break;
02011
02012 default:
02013 FAILURE(InvalidArgument, "Unknown packet phase");
02014 }
02015 } while(!yield);
02016 #ifdef DEBUG_IDE_PACKET
02017 printf("Drop out of packet state machine %d\n", index);
02018 ide_status(index);
02019 #endif
02020 }
02021 }
02022 break;
02023
02024 case 0xa1:
02025 if(SEL_DISK(index)->cdrom())
02026 {
02027 identify_drive(index, true);
02028 SEL_STATUS(index).busy = false;
02029 SEL_STATUS(index).drive_ready = true;
02030 SEL_STATUS(index).seek_complete = true;
02031 SEL_STATUS(index).fault = false;
02032 SEL_STATUS(index).drq = true;
02033 SEL_STATUS(index).err = false;
02034 SEL_COMMAND(index).command_in_progress = false;
02035 raise_interrupt(index);
02036 }
02037 else
02038 {
02039 command_aborted(index, SEL_COMMAND(index).current_command);
02040 }
02041 break;
02042
02043 case 0xc4:
02044 if(SEL_DISK(index)->cdrom())
02045 {
02046 command_aborted(index, SEL_COMMAND(index).current_command);
02047 }
02048 else
02049 {
02050 if(SEL_COMMAND(index).command_cycle == 0)
02051 {
02052
02053
02054 if(SEL_REGISTERS(index).sector_count == 0)
02055 SEL_REGISTERS(index).sector_count = 256;
02056 SEL_STATUS(index).drq = false;
02057 }
02058
02059 if(!SEL_STATUS(index).drq)
02060 {
02061
02062
02063 if(!SEL_REGISTERS(index).lba_mode)
02064 {
02065 FAILURE(NotImplemented, "Non-LBA disk read");
02066 }
02067 else
02068 {
02069 u32 lba = (SEL_REGISTERS(index).head_no << 24) |
02070 (
02071 SEL_REGISTERS(index).cylinder_no <<
02072 8
02073 ) |
02074 SEL_REGISTERS(index).sector_no;
02075
02076 if(SEL_REGISTERS(index).sector_count >= SEL_PER_DRIVE(index
02077 ).multiple_size)
02078 {
02079
02080
02081 CONTROLLER(index).data_size = 256 * SEL_PER_DRIVE(index).multiple_size;
02082 SEL_REGISTERS(index).sector_count -= SEL_PER_DRIVE(index).multiple_size;
02083 }
02084 else
02085 {
02086
02087
02088 CONTROLLER(index).data_size = 256 * SEL_REGISTERS(index).sector_count;
02089 SEL_REGISTERS(index).sector_count = 0;
02090 }
02091
02092 #ifdef DEBUG_IDE_MULTIPLE
02093 printf("IDE %d.%d: Reading %d sectors, %d sectors left.\n", index,
02094 CONTROLLER(index).selected, CONTROLLER(index).data_size / 256,
02095 SEL_REGISTERS(index).sector_count);
02096 #endif
02097 SEL_DISK(index)->seek_block(lba);
02098 SEL_DISK(index)->read_blocks(&(CONTROLLER(index).data[0]),
02099 CONTROLLER(index).data_size / 256);
02100 #if defined(ES40_BIG_ENDIAN)
02101 for(int i = 0; i < 256; i++)
02102 CONTROLLER(index).data[i] = endian_16(CONTROLLER(index).data[i]);
02103 #endif
02104 SEL_STATUS(index).busy = false;
02105 SEL_STATUS(index).drive_ready = true;
02106 SEL_STATUS(index).fault = false;
02107 SEL_STATUS(index).drq = true;
02108 SEL_STATUS(index).err = false;
02109 CONTROLLER(index).data_ptr = 0;
02110
02111
02112 if(SEL_REGISTERS(index).sector_count == 0)
02113 {
02114 SEL_COMMAND(index).command_in_progress = false;
02115 if(SEL_DISK(index)->cdrom())
02116 set_signature(index, CONTROLLER(index).selected);
02117 }
02118 else
02119 {
02120
02121
02122
02123 SEL_REGISTERS(index).sector_no += CONTROLLER(index).data_size * 256;
02124 if(SEL_REGISTERS(index).sector_no > 255)
02125 {
02126 SEL_REGISTERS(index).sector_no = 0;
02127 SEL_REGISTERS(index).cylinder_no++;
02128 if(SEL_REGISTERS(index).cylinder_no > 65535)
02129 {
02130 SEL_REGISTERS(index).cylinder_no = 0;
02131 SEL_REGISTERS(index).head_no++;
02132 }
02133 }
02134 }
02135 }
02136
02137 raise_interrupt(index);
02138 }
02139 }
02140 break;
02141
02142 case 0xc5:
02143 if(SEL_DISK(index)->cdrom())
02144 {
02145 command_aborted(index, SEL_COMMAND(index).current_command);
02146 }
02147 else
02148 {
02149 if(SEL_COMMAND(index).command_cycle == 0)
02150 {
02151
02152
02153 if(SEL_DISK(index)->ro())
02154 {
02155 printf("%%IDE-W-RO: Write attempt to read-only disk %d.%d.\n",
02156 index, CONTROLLER(index).selected);
02157 command_aborted(index, SEL_COMMAND(index).current_command);
02158 }
02159 else
02160 {
02161 SEL_STATUS(index).drq = true;
02162 SEL_STATUS(index).busy = false;
02163 if(SEL_REGISTERS(index).sector_count == 0)
02164 SEL_REGISTERS(index).sector_count = 256;
02165 if(SEL_REGISTERS(index).sector_count >= SEL_PER_DRIVE(index
02166 ).multiple_size)
02167 {
02168 CONTROLLER(index).data_size = 256 * SEL_PER_DRIVE(index).multiple_size;
02169 SEL_REGISTERS(index).sector_count -= SEL_PER_DRIVE(index).multiple_size;
02170 }
02171 else
02172 {
02173 CONTROLLER(index).data_size = 256 * SEL_REGISTERS(index).sector_count;
02174 SEL_REGISTERS(index).sector_count = 0;
02175 }
02176 }
02177 }
02178 else
02179 {
02180
02181
02182 if(!SEL_STATUS(index).drq)
02183 {
02184
02185
02186 if(!SEL_REGISTERS(index).lba_mode)
02187 {
02188 FAILURE(NotImplemented, "Non-LBA disk write");
02189 }
02190 else
02191 {
02192 u32 lba = (SEL_REGISTERS(index).head_no << 24) |
02193 (
02194 SEL_REGISTERS(index).cylinder_no <<
02195 8
02196 ) |
02197 SEL_REGISTERS(index).sector_no;
02198
02199 #if defined(ES40_BIG_ENDIAN)
02200 {
02201 u16 data[IDE_BUFFER_SIZE];
02202
02203 SEL_DISK(index)->seek_block(lba);
02204 for(int i = 0; i < CONTROLLER(index).data_size; i++)
02205 data[i] = endian_16(CONTROLLER(index).data[i]);
02206 SEL_DISK(index)->write_blocks(&(data[0]),
02207 CONTROLLER(index).data_size / 256);
02208 }
02209
02210 #else
02211 SEL_DISK(index)->seek_block(lba);
02212 SEL_DISK(index)->write_blocks(&(CONTROLLER(index).data[0]),
02213 CONTROLLER(index).data_size / 256);
02214 #endif
02215 SEL_STATUS(index).busy = false;
02216 SEL_STATUS(index).drive_ready = true;
02217 SEL_STATUS(index).fault = false;
02218 SEL_STATUS(index).drq = true;
02219 SEL_STATUS(index).err = false;
02220 CONTROLLER(index).data_ptr = 0;
02221
02222 if(SEL_REGISTERS(index).sector_count == 0)
02223 {
02224
02225
02226 SEL_STATUS(index).drq = false;
02227 SEL_COMMAND(index).command_in_progress = false;
02228 }
02229 else
02230 {
02231
02232
02233 if(SEL_REGISTERS(index).sector_count >= SEL_PER_DRIVE(index
02234 ).multiple_size)
02235 {
02236 CONTROLLER(index).data_size = 256 * SEL_PER_DRIVE(index).multiple_size;
02237 SEL_REGISTERS(index).sector_count -= SEL_PER_DRIVE(index).multiple_size;
02238 }
02239 else
02240 {
02241 CONTROLLER(index).data_size = 256 * SEL_REGISTERS(index).sector_count;
02242 SEL_REGISTERS(index).sector_count = 0;
02243 }
02244
02245
02246
02247 SEL_REGISTERS(index).sector_no++;
02248 if(SEL_REGISTERS(index).sector_no > 255)
02249 {
02250 SEL_REGISTERS(index).sector_no = 0;
02251 SEL_REGISTERS(index).cylinder_no++;
02252 if(SEL_REGISTERS(index).cylinder_no > 65535)
02253 {
02254 SEL_REGISTERS(index).cylinder_no = 0;
02255 SEL_REGISTERS(index).head_no++;
02256 }
02257 }
02258 }
02259 }
02260
02261 raise_interrupt(index);
02262 }
02263 }
02264 }
02265 break;
02266
02267 case 0xc6:
02268 if(SEL_DISK(index)->cdrom())
02269 {
02270 command_aborted(index, SEL_COMMAND(index).current_command);
02271 }
02272 else
02273 {
02274 SEL_PER_DRIVE(index).multiple_size = SEL_REGISTERS(index).sector_count;
02275 printf("Set multiple mode: sector_count = %d\n",
02276 SEL_REGISTERS(index).sector_count);
02277 SEL_STATUS(index).busy = false;
02278 SEL_STATUS(index).drive_ready = true;
02279 SEL_STATUS(index).fault = false;
02280 SEL_STATUS(index).drq = false;
02281 SEL_STATUS(index).err = false;
02282 SEL_COMMAND(index).command_in_progress = false;
02283 raise_interrupt(index);
02284 }
02285 break;
02286
02287 case 0xc8:
02288 case 0xc9:
02289 if(SEL_DISK(index)->cdrom())
02290 {
02291 command_aborted(index, SEL_COMMAND(index).current_command);
02292 SEL_COMMAND(index).command_in_progress = false;
02293 }
02294 else
02295 {
02296 if(SEL_REGISTERS(index).sector_count == 0)
02297 SEL_REGISTERS(index).sector_count = 256;
02298
02299 #ifdef DEBUG_IDE_DMA
02300 printf("%%IDE-I-DMA: Read %d sectors = %d bytes.\n",
02301 SEL_REGISTERS(index).sector_count,
02302 SEL_REGISTERS(index).sector_count * 512);
02303 #endif
02304
02305 u32 lba = (SEL_REGISTERS(index).head_no << 24) |
02306 (
02307 SEL_REGISTERS(index).cylinder_no <<
02308 8
02309 ) |
02310 SEL_REGISTERS(index).sector_no;
02311
02312 SEL_DISK(index)->seek_block(lba);
02313
02314 SEL_DISK(index)->read_blocks(&(CONTROLLER(index).data[0]),
02315 SEL_REGISTERS(index).sector_count);
02316
02317 u8* ptr = (u8 *) (&CONTROLLER(index).data[0]);
02318 u8 status = do_dma_transfer(index, ptr,
02319 SEL_REGISTERS(index).sector_count * 512,
02320 false);
02321 SEL_COMMAND(index).command_in_progress = false;
02322 SEL_STATUS(index).drive_ready = true;
02323 SEL_STATUS(index).seek_complete = true;
02324 SEL_STATUS(index).fault = false;
02325 SEL_STATUS(index).drq = false;
02326 SEL_STATUS(index).err = false;
02327 SEL_STATUS(index).busy = false;
02328 }
02329 break;
02330
02331 case 0xca:
02332 case 0xcb:
02333 if(SEL_DISK(index)->cdrom() || SEL_DISK(index)->ro())
02334 {
02335 command_aborted(index, SEL_COMMAND(index).current_command);
02336 SEL_COMMAND(index).command_in_progress = false;
02337 }
02338 else
02339 {
02340 if(SEL_DISK(index)->ro())
02341 {
02342 printf("%%IDE-W-RO: DMA Write attempt to read-only disk %d.%d.\n",
02343 index, CONTROLLER(index).selected);
02344 command_aborted(index, SEL_COMMAND(index).current_command);
02345 }
02346 else
02347 {
02348 if(SEL_REGISTERS(index).sector_count == 0)
02349 SEL_REGISTERS(index).sector_count = 256;
02350
02351 #ifdef DEBUG_IDE_DMA
02352 printf("%%IDE-I-DMA: Write %d sectors = %d bytes.\n",
02353 SEL_REGISTERS(index).sector_count,
02354 SEL_REGISTERS(index).sector_count * 512);
02355 #endif
02356
02357 u8* ptr = (u8 *) (&CONTROLLER(index).data[0]);
02358 u8 status = do_dma_transfer(index, ptr,
02359 SEL_REGISTERS(index).sector_count * 512,
02360 true);
02361 u32 lba = (SEL_REGISTERS(index).head_no << 24) |
02362 (
02363 SEL_REGISTERS(index).cylinder_no <<
02364 8
02365 ) |
02366 SEL_REGISTERS(index).sector_no;
02367
02368 SEL_DISK(index)->seek_block(lba);
02369 SEL_DISK(index)->write_blocks(&(CONTROLLER(index).data[0]),
02370 SEL_REGISTERS(index).sector_count);
02371 SEL_COMMAND(index).command_in_progress = false;
02372 SEL_STATUS(index).drive_ready = true;
02373 SEL_STATUS(index).seek_complete = true;
02374 SEL_STATUS(index).fault = false;
02375 SEL_STATUS(index).drq = false;
02376 SEL_STATUS(index).err = false;
02377 SEL_STATUS(index).busy = false;
02378 }
02379 }
02380 break;
02381
02382 #if 0
02383
02384 case 0xe5:
02385 ide_status(index);
02386 command_aborted(index, SEL_COMMAND(index).current_command);
02387 SEL_COMMAND(index).command_in_progress = false;
02388
02389
02390 break;
02391 #endif
02392
02393 case 0xec:
02394 if(!SEL_DISK(index)->cdrom())
02395 {
02396 identify_drive(index, false);
02397 SEL_STATUS(index).busy = false;
02398 SEL_STATUS(index).drive_ready = true;
02399 SEL_STATUS(index).seek_complete = true;
02400 SEL_STATUS(index).fault = false;
02401 SEL_STATUS(index).drq = true;
02402 SEL_STATUS(index).err = false;
02403 SEL_COMMAND(index).command_in_progress = false;
02404 raise_interrupt(index);
02405 }
02406 else
02407 {
02408 set_signature(index, CONTROLLER(index).selected);
02409
02410
02411
02412 command_aborted(index, 0xec);
02413 }
02414 break;
02415
02416 case 0xef:
02417 SEL_COMMAND(index).command_in_progress = false;
02418 switch(SEL_REGISTERS(index).features)
02419 {
02420 case 0x03:
02421 if(SEL_REGISTERS(index).sector_count < 16)
02422 {
02423
02424
02425 SEL_STATUS(index).busy = false;
02426 SEL_STATUS(index).drive_ready = true;
02427 SEL_STATUS(index).seek_complete = true;
02428 SEL_STATUS(index).fault = false;
02429 SEL_STATUS(index).drq = false;
02430 SEL_STATUS(index).err = false;
02431 raise_interrupt(index);
02432 break;
02433 }
02434 else
02435 {
02436
02437
02438 switch(SEL_REGISTERS(index).sector_count)
02439 {
02440 case 0x20:
02441 case 0x21:
02442 case 0x22:
02443
02444
02445 CONTROLLER(index).dma_mode = SEL_REGISTERS(index).sector_count & 0x03;
02446 SEL_STATUS(index).busy = false;
02447 SEL_STATUS(index).drive_ready = true;
02448 SEL_STATUS(index).seek_complete = true;
02449 SEL_STATUS(index).fault = false;
02450 SEL_STATUS(index).drq = false;
02451 SEL_STATUS(index).err = false;
02452 raise_interrupt(index);
02453 break;
02454
02455 case 0x40:
02456 case 0x41:
02457 case 0x42:
02458
02459
02460 command_aborted(index, SEL_COMMAND(index).current_command);
02461 break;
02462 }
02463 break;
02464 }
02465
02466 default:
02467 printf("%%IDE-I-FEAT: Unhandled set feature subcommand %x\n",
02468 SEL_REGISTERS(index).features);
02469 command_aborted(index, SEL_COMMAND(index).current_command);
02470 break;
02471 }
02472 break;
02473
02474
02475
02476
02477 case 0xe0:
02478 case 0xe1:
02479 case 0xe2:
02480 case 0xe3:
02481 case 0xe6:
02482 case 0xe7:
02483 case 0xea:
02484 SEL_STATUS(index).busy = false;
02485 SEL_STATUS(index).drive_ready = true;
02486 SEL_STATUS(index).drq = false;
02487 SEL_STATUS(index).err = false;
02488 SEL_COMMAND(index).command_in_progress = false;
02489 raise_interrupt(index);
02490 break;
02491
02492 default:
02493 ide_status(index);
02494 FAILURE_1(NotImplemented, "Unknown IDE command %x",
02495 SEL_COMMAND(index).current_command);
02496 break;
02497 }
02498
02499 #ifdef DEBUG_IDE_COMMAND
02500 if(SEL_COMMAND(index).command_in_progress == false)
02501 {
02502 printf("%%IDE-I-COMMAND: Command has completed on controller %d.\n", index);
02503 ide_status(index);
02504 printf("==================================================\n");
02505 }
02506 else
02507 {
02508 printf("%%IDE-I-COMMAND: controller %d is yielding to host.\n", index);
02509 ide_status(index);
02510 printf("--------------------------------------------------\n");
02511 }
02512 #endif
02513 }
02514
02515 SEL_COMMAND(index).command_cycle++;
02516 }
02517
02518 int CAliM1543C_ide::do_dma_transfer(int index, u8* buffer, u32 buffersize,
02519 bool direction)
02520 {
02521 u8 xfer;
02522 size_t xfersize = 0;
02523 u8 status = 0;
02524 u8 count = 0;
02525 u32 prd;
02526 semBusMaster[index]->wait();
02527 {
02528 SCOPED_READ_LOCK(mtBusMaster[index]);
02529 prd = endian_32(*(u32 *) (&CONTROLLER(index).busmaster[4]));
02530 }
02531 do
02532 {
02533 u32 base;
02534 do_pci_read(prd, &base, 4, 1);
02535
02536 u16 size_16;
02537 do_pci_read(prd + 4, &size_16, 2, 1);
02538
02539 size_t size = size_16 ? size_16 : 65536;
02540 do_pci_read(prd + 7, &xfer, 1, 1);
02541
02542 #ifdef DEBUG_IDE_DMA
02543 printf("-IDE-I-DMA: Transfer %d bytes to/from %lx (%x)\n", size, base, xfer);
02544 #endif
02545 if(xfersize + size > buffersize)
02546 {
02547
02548
02549 size = buffersize - xfersize;
02550 status = 2;
02551 #ifdef DEBUG_IDE_DMA
02552 printf("-IDE-I-DMA: Actual transfer size: %d bytes\n", size);
02553 #endif
02554 }
02555
02556
02557 if(!direction)
02558 {
02559 do_pci_write(base, buffer, 1, size);
02560 buffer += size;
02561 }
02562 else
02563 {
02564 do_pci_read(base, buffer, 1, size);
02565 buffer += size;
02566 }
02567
02568 xfersize += size;
02569 prd += 8;
02570 if(xfer == 0x80 && xfersize < buffersize)
02571 {
02572
02573
02574 status = 1;
02575 }
02576
02577 if(count++ > 32)
02578 {
02579 FAILURE(InvalidArgument, "Too many PRD nodes?");
02580 }
02581
02582 if(buffersize == xfersize && xfer != 0x80)
02583 {
02584
02585
02586 status = 2;
02587 }
02588 } while(xfer != 0x80 && status == 0);
02589
02590 switch(status)
02591 {
02592 case 0:
02593 {
02594 SCOPED_WRITE_LOCK(mtBusMaster[index]);
02595 CONTROLLER(index).busmaster[2] &= 0xfe;
02596 }
02597
02598 raise_interrupt(index);
02599 break;
02600
02601 case 1:
02602 {
02603 SCOPED_WRITE_LOCK(mtBusMaster[index]);
02604 CONTROLLER(index).busmaster[2] &= 0xfe;
02605 }
02606
02607
02608 break;
02609
02610 case 2:
02611
02612 raise_interrupt(index);
02613 break;
02614 }
02615
02616 return status;
02617 }
02618
02622 void CAliM1543C_ide::run()
02623 {
02624 int index = (thrController[0] == Poco::Thread::current()) ? 0 : 1;
02625 try
02626 {
02627 for(;;)
02628 {
02629 semController[index]->wait();
02630 if(StopThread)
02631 return;
02632 {
02633 #ifdef DEBUG_IDE_THREADS
02634 printf("Thread %d: \n", index);
02635 ide_status(index);
02636 #endif
02637 if(SEL_COMMAND(index).command_in_progress)
02638 execute(index);
02639 UPDATE_ALT_STATUS(index);
02640
02641 #ifdef IDE_YIELD_INTERRUPTS
02642 if(CONTROLLER(index).interrupt_pending) {
02643 {
02644 SCOPED_WRITE_LOCK(mtBusMaster[index]);
02645 CONTROLLER(index).busmaster[2] |= 0x04;
02646 }
02647 theAli->pic_interrupt(1, 6 + index);
02648 }
02649 #endif
02650
02651 }
02652 }
02653 }
02654
02655 catch(Poco::Exception & e)
02656 {
02657 printf("Exception in IDE thread: %s.\n", e.displayText().c_str());
02658
02659
02660 }
02661 }