AliM1543C_ide.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
00020  * 02110-1301, USA.
00021  *
00022  * Although this is not required, the author would appreciate being
00023  * notified of, and receiving any modifications you may make to the
00024  * source code that might serve the general public.
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   /*00*/ 0x522910b9,  // CFID: vendor + device
00246   /*04*/ 0x02800000,  // CFCS: command + status
00247   /*08*/ 0x0101fac1,  // CFRV: class + revision
00248   /*0c*/ 0x00000000,  // CFLT: latency timer + cache line size
00249   /*10*/ 0x000001f1,  // BAR0:
00250   /*14*/ 0x000003f5,  // BAR1:
00251   /*18*/ 0x00000171,  // BAR2:
00252   /*1c*/ 0x00000375,  // BAR3:
00253   /*20*/ 0x0000f001,  // BAR4:
00254   /*24*/ 0x00000000,  // BAR5:
00255   /*28*/ 0x00000000,  // CCIC: CardBus
00256   /*2c*/ 0x00000000,  // CSID: subsystem + vendor
00257   /*30*/ 0x00000000,  // BAR6: expansion rom base
00258   /*34*/ 0x00000000,  // CCAP: capabilities pointer
00259   /*38*/ 0x00000000,
00260   /*3c*/ 0x040201ff,  // CFIT: interrupt configuration
00261   0, 0,
00262   /*48*/ 0x4a000000,  // UDMA test
00263   /*4c*/ 0x1aba0000,  // reserved
00264   0,
00265   /*54*/ 0x44445555,  // udma setting + fifo treshold
00266   0, 0, 0, 0, 0, 0, 0, 0,
00267   /*78*/ 0x00000021,  // ide clock
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   /*00*/ 0x00000000,  // CFID: vendor + device
00275   /*04*/ 0x00000105,  // CFCS: command + status
00276   /*08*/ 0x00000000,  // CFRV: class + revision
00277   /*0c*/ 0x0000ffff,  // CFLT: latency timer + cache line size
00278   /*10*/ 0xfffffff8,  // BAR0
00279   /*14*/ 0xfffffffc,  // BAR1: CBMA
00280   /*18*/ 0xfffffff8,  // BAR2:
00281   /*1c*/ 0xfffffffc,  // BAR3:
00282   /*20*/ 0xfffffff0,  // BAR4:
00283   /*24*/ 0x00000000,  // BAR5:
00284   /*28*/ 0x00000000,  // CCIC: CardBus
00285   /*2c*/ 0x00000000,  // CSID: subsystem + vendor
00286   /*30*/ 0x00000000,  // BAR6: expansion rom base
00287   /*34*/ 0x00000000,  // CCAP: capabilities pointer
00288   /*38*/ 0x00000000,
00289   /*3c*/ 0x000000ff,  // CFIT: interrupt configuration
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   // create scsi busses
00306   CSCSIBus*   a = new CSCSIBus(cfg, c);
00307   CSCSIBus*   b = new CSCSIBus(cfg, c);
00308   scsi_register(0, a, 7); // scsi id 7 by default
00309   scsi_register(1, b, 7); // scsi id 7 by default
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   // start controller threads
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); // disk controller
00344     semBusMaster[i] = new Poco::Semaphore(0, 1);  // bus master
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  * Region read/write redirection
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     // we have to offset by two because the BAR starts at 3f4 vs 3f6
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     // we have to offset by two because the BAR starts at 3f4 vs 3f6
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  * Register read/write handlers
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     // no disks are present, so the data lines actually float to
00639     // a high state, which is logical 1.
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       // there's no more to take.
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();  // wake up the controller.
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  // 512 byte sector size
00719     | (CONTROLLER(index).selected ? 0x10 : 0x00) | (SEL_REGISTERS(index).head_no & 0x0f);
00720     break;
00721 
00722   case REG_COMMAND_STATUS:
00723 
00724     // get the status and clear the interrupt.
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       // we don't want any more.
00786       SEL_STATUS(index).drq = false;
00787       SEL_STATUS(index).busy = true;
00788       UPDATE_ALT_STATUS(index);
00789       semController[index]->set();      // wake the controller up.
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); // interrupt is cleared on write.
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       // we're already working, why is another command being issued?
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();      // wake up the controller.
00882     }
00883     else
00884     {
00885 
00886       // this is a nop, so we cancel everything that's pending and
00887       // pretend that this operation got done super fast!
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     // 3x7h drive address register. (floppy?)
00920     data |= (CONTROLLER(index).selected == 0) ? 1 : 2;
00921     data |= (SEL_REGISTERS(index).head_no) << 2;
00922     data = (~data) & 0xff;  // negate everything
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;  // no error
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     // floppy?
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   //  u32 base, control;
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: // command register
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     // bits 7:4 & 2:1 are reserved and must return zero on read.
01067     CONTROLLER(index).busmaster[0] = data & 0x09;
01068     if(data & 0x01)
01069     {
01070 
01071       // set the status register
01072       CONTROLLER(index).busmaster[2] |= 0x01;
01073       semBusMaster[index]->set(); // wake up the controller for busmastering
01074     }
01075     else
01076     {
01077 
01078       // clear the status register
01079       CONTROLLER(index).busmaster[2] &= 0xfe;
01080     }
01081     break;
01082 
01083   case 2:           // status
01084     // bit 7 = simplex only (0=both channels are independent)
01085     // bit 6 = drive 1 dma capable.
01086     // bit 5 = drive 0 dma capable.
01087     // bit 4,3 = reserved
01088     // bit 2 = interrupt (write 1 to reset)
01089     // bit 1 = error (write 1 to reset)
01090     // bit 0 = busmaster active.
01091     CONTROLLER(index).busmaster[2] = data & 0x67;
01092     if(data & 0x04) // interrupt
01093       CONTROLLER(index).busmaster[2] &= ~0x04;
01094     if(data & 0x02) // error
01095       CONTROLLER(index).busmaster[2] &= ~0x02;
01096     if(data & 0x01) // busy
01097       CONTROLLER(index).busmaster[2] &= ~0x01;
01098     break;
01099 
01100   case 4:           // descriptor table pointer register(s)
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   // Device signature
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;     // XXX: This may not be correct.
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   // clear the block.
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   // The data here was taken from T13/1153D revision 18
01237   if(!packet)
01238   {
01239 
01240     // flags:  0x0080 = removable, 0x0040 = fixed.
01241     CONTROLLER(index).data[0] = SEL_DISK(index)->cdrom() ? 0x0080 : 0x0040;
01242   }
01243   else
01244   {
01245 
01246     // flags: 15-14: 10=atapi, 11=reserved; 12-8: packet set; 7:
01247     // removable 6-5: timing info, 4-2: command, 1-0: 00= 12 byte packet
01248     CONTROLLER(index).data[0] = 0x8580;
01249   }
01250 
01251   // logical cylinders
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   // logical heads
01258   CONTROLLER(index).data[3] = (u16) (SEL_DISK(index)->get_heads());
01259 
01260   // logical sectors per logical track
01261   CONTROLLER(index).data[6] = (u16) (SEL_DISK(index)->get_sectors());
01262 
01263   // serial number
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   // firmware revision
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   // model number
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   // read/write multiple (15-8 = 0x80, 7-0 = # sectors)
01303   CONTROLLER(index).data[47] = 0x8000 | MAX_MULTIPLE_SECTORS;
01304 
01305   // capabilities
01306   if(!packet)
01307   {
01308     CONTROLLER(index).data[49] = 0x0300;
01309   }
01310   else
01311   {
01312     CONTROLLER(index).data[49] = 0x0b00;  // dma, iordy
01313   }
01314 
01315   // capabilities (2)
01316   CONTROLLER(index).data[50] = 0x4000;
01317 
01318   // pio data transfer number (bits 15-8)
01319   CONTROLLER(index).data[51] = 0x0300;
01320 
01321   // validity:  bit 2 = #88 valid, 1 = 64-70 valid, 0 = 54-58 valid
01322   CONTROLLER(index).data[53] = 7;
01323 
01324   // geometry
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   // multiple sector setting (valid, 1 sector per interrupt)
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   // lba capacity
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   // multiword dma capability (10-8: modes selected, 2-0, modes
01350   // supported)
01351   if(usedma)
01352     CONTROLLER(index).data[63] = CONTROLLER(index).dma_mode << 8 | 0x01;  // dma 0 supported
01353   else
01354     CONTROLLER(index).data[63] = CONTROLLER(index).dma_mode << 8 | 0x00;  // dma not supported
01355 
01356   // pio modes supported (bit 0 = mode 3, bit 1 = mode 4)
01357   CONTROLLER(index).data[64] = 0x0002;
01358 
01359   // minimum cycle times
01360   CONTROLLER(index).data[65] = 480;   // mode 0
01361   CONTROLLER(index).data[66] = 480;   // mode 0
01362   CONTROLLER(index).data[67] = 120;   // pio4
01363   CONTROLLER(index).data[68] = 120;   // pio4
01364   if(packet)
01365   {
01366 
01367     // packet to bus release time
01368     CONTROLLER(index).data[71] = 120;
01369 
01370     // service to bus release time
01371     CONTROLLER(index).data[72] = 120;
01372   }
01373 
01374   // queue depth (we don't do queing)
01375   CONTROLLER(index).data[75] = 0;
01376 
01377   // ata version supported (bits/version: 1,2,3,4)
01378   CONTROLLER(index).data[80] = 0x001e;
01379 
01380   // atapi revision supported (ata/atapi-4 T13 1153D revision 17)
01381   CONTROLLER(index).data[81] = 0x0017;
01382 
01383   // command set supported (cdrom = nop,packet,removable; disk=nop)
01384   CONTROLLER(index).data[82] = SEL_DISK(index)->cdrom() ? 0x4014 : 0x4000;
01385 
01386   // command sets supported(no additional command sets)
01387   CONTROLLER(index).data[83] = 0x4000;
01388   CONTROLLER(index).data[84] = 0x4000;
01389 
01390   // command sets enabled.
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   // ultra dma modes supported (10-8: modes selected, 2-0, modes
01396   // supported)
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; // command ABORTED
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     // this device doesn't exist (and its not execute device
01457     // diagnostic)
01458     // so we'll just timeout
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:  // nop
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       // FAILURE("This isn't possible, but you're seeing it.");
01481       break;
01482 
01483     case 0x08:  // device reset
01484       if(SEL_DISK(index)->cdrom() || 1)
01485       {
01486 
01487         // the spec says that non-packet devices must not respond
01488         // to device reset.  However, by allowing it, Tru64
01489         // recognizes the device properly.
01490         SEL_COMMAND(index).command_in_progress = false;
01491         if(CONTROLLER(index).selected == 0)
01492         {
01493           REGISTERS(index, 0).error = 0x01;       // device passed.
01494           REGISTERS(index, 1).error = 0x01;       // slave not present or passed
01495         }
01496         else
01497         {
01498           REGISTERS(index, 1).error = 0x01;       // slave passed
01499         }
01500 
01501         set_signature(index, CONTROLLER(index).selected);
01502 
01503         // step "k", page 216 (232)
01504         SEL_STATUS(index).drq = false;            // bit 3
01505         SEL_STATUS(index).bit_2 = false;          // bit 2
01506         SEL_STATUS(index).err = false;            // bit 0
01507         if(SEL_DISK(index)->cdrom())
01508         {
01509           SEL_STATUS(index).fault = false;        // bit 5
01510           SEL_STATUS(index).drive_ready = false;  // per step "m2"
01511         }
01512         else
01513         {
01514           SEL_STATUS(index).drive_ready = true;   // step "m1"
01515         }
01516 
01517         SEL_STATUS(index).busy = false;
01518 
01519         // some sources say there's no reset on device reset.
01520         // raise_interrupt(index);
01521       }
01522       else
01523       {
01524         command_aborted(index, SEL_COMMAND(index).current_command);
01525       }
01526       break;
01527 
01528     case 0x10:  // calibrate drive
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:  // read with retries
01541     case 0x21:  // read without retries
01542       if(SEL_COMMAND(index).command_cycle == 0)
01543       {
01544 
01545         // fixup the 0=256 case.
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         // buffer is empty, so lets fill it.
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           // prepare for next sector
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); // per 9.1
01589           }
01590           else
01591           {
01592 
01593             // set the next block to read.
01594             // increment the lba.
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:  // write with retries
01614     case 0x31:  // write without retries
01615       if(SEL_COMMAND(index).command_cycle == 0)
01616       {
01617 
01618         // this is our first time through
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         // now we should be getting data.
01638         if(!SEL_STATUS(index).drq)
01639         {
01640 
01641           // the buffer is full.  Do something with the data.
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             // prepare for next sector
01678             SEL_REGISTERS(index).sector_count--;
01679             if(SEL_REGISTERS(index).sector_count == 0)
01680             {
01681 
01682               // we're done
01683               SEL_STATUS(index).drq = false;
01684               SEL_COMMAND(index).command_in_progress = false;
01685             }
01686             else
01687             {
01688 
01689               // set the next block to read.
01690               // increment the lba.
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        * case 0x40, 0x41: read verify sector(s) is mandatory for
01712        * non-packet (no w/packet
01713        */
01714     case 0x70:  // seek
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        * 0x90: execute device diagnostic: mandatory
01734        */
01735     case 0x91:  // initialize device parameters
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           // use the default translation -- ok!
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;  // ABORT.
01774           raise_interrupt(index);
01775         }
01776       }
01777       break;
01778 
01779     case 0xa0:  // packet send
01780       /*
01781        * The state machine and protocol used here was actually
01782        * derived from ATA/ATAPI-5 (D1321R3) instead of the -4
01783        * documenation.  State names were taken from that document.
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           // overlap not supported
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             // this must be the first time through.
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             // we drop out of the thread and shut down the
01820             // controller. we will be awakened when the drq flag
01821             // is false, and the process will start in the state machine.
01822             break;
01823           }
01824 
01825           /*
01826            * This is the Packet I/O state machine. The gist of
01827            * it is this: we loop until yield==true, so we can
01828            * move from state to state in the same DoClock().
01829            * By the time we get here, we're in DP1 (Receive
01830            * Packet) and we're waiting for an actual packet to
01831            * arrive.
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:  // receive packet
01849               // we now have a full command packet.
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:  // prepare b
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;  // word count.
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                 // transition to an idle state
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                 // send back via dma
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                 // send back via pio
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                   // first time through: no data
01947                   // transferred, and drq=0
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                     // all of the data has been read
01959                     // from the buffer.
01960                     // for now I assume that it is
01961                     // everything.
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                 // do the transfer
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               // this is either DI0 or DI1
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:  // identify packet device
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:  // read multiple
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           // fixup the 0=256 case.
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           // buffer is empty, so lets fill it.
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               // easy, its a full block
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               // partial block.
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);  // actual number of blocks we want.
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             // prepare for next sector
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); // per 9.1
02117             }
02118             else
02119             {
02120 
02121               // set the next block to read.
02122               // increment the lba.
02123               SEL_REGISTERS(index).sector_no += CONTROLLER(index).data_size * 256;  // # sectors read.
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:  // write multiple
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           // this is our first time through
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           // now we should be getting data.
02182           if(!SEL_STATUS(index).drq)
02183           {
02184 
02185             // the buffer is full.  Do something with the data.
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                 // we're done
02226                 SEL_STATUS(index).drq = false;
02227                 SEL_COMMAND(index).command_in_progress = false;
02228               }
02229               else
02230               {
02231 
02232                 // prepare for next block
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                 // set the next block to read.
02246                 // increment the lba.
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:  // set multiple mode
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:  // read dma
02288     case 0xc9:  // read dma (old)
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:  // write dma
02332     case 0xcb:  // write dma (old)
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:  // check power mode
02385       ide_status(index);
02386       command_aborted(index, SEL_COMMAND(index).current_command);
02387       SEL_COMMAND(index).command_in_progress = false;
02388 
02389       // raise_interrupt(index);
02390       break;
02391 #endif
02392 
02393     case 0xec:  // identify
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); // per
02409 
02410         //
02411         // 9.1
02412         command_aborted(index, 0xec);
02413       }
02414       break;
02415 
02416     case 0xef:    // set features
02417       SEL_COMMAND(index).command_in_progress = false;
02418       switch(SEL_REGISTERS(index).features)
02419       {
02420       case 0x03:  // set transfer mode
02421         if(SEL_REGISTERS(index).sector_count < 16)
02422         {
02423 
02424           // allow all PIO modes.
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           // a DMA mode.
02438           switch(SEL_REGISTERS(index).sector_count)
02439           {
02440           case 0x20:
02441           case 0x21:
02442           case 0x22:
02443 
02444             // multiword dma
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             // ultra dma
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            * Special cases:  commands we don't support, but return success.
02476            ***/
02477     case 0xe0:    // standby now
02478     case 0xe1:    // idle immediate
02479     case 0xe2:    // standby
02480     case 0xe3:    // idle
02481     case 0xe6:    // sleep
02482     case 0xe7:    // flush cache
02483     case 0xea:    // flush cache ext
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:      // unknown/unhandled ATA command
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();  // wait until the start bit is set.
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       // only copy as much data as we have from the disk.
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     // copy it to/from ram.
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; // go to next entry.
02570     if(xfer == 0x80 && xfersize < buffersize)
02571     {
02572 
02573       // we still have disk data left over!
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       // we're done, but there's more prd nodes.
02586       status = 2;
02587     }
02588   } while(xfer != 0x80 && status == 0);
02589 
02590   switch(status)
02591   {
02592   case 0:     // normal completion.
02593     {
02594       SCOPED_WRITE_LOCK(mtBusMaster[index]);
02595       CONTROLLER(index).busmaster[2] &= 0xfe; // clear active.
02596     }
02597 
02598     raise_interrupt(index);
02599     break;
02600 
02601   case 1: // PRD is smaller than the data we have.
02602     {
02603       SCOPED_WRITE_LOCK(mtBusMaster[index]);
02604       CONTROLLER(index).busmaster[2] &= 0xfe; // clear active.
02605     }
02606 
02607     // do not raise an interrupt
02608     break;
02609       
02610   case 2: // PRD is larger than the data we have.
02611     // leave active set.
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     // Let the thread die...
02660   }
02661 }

SourceForge.net Logo
Project space on SourceForge.net