Overview   API Reference  

ata_channel.hpp

00001 #if !defined(__ATA_CHANNEL_HPP__)
00002 #define __ATA_CHANNEL_HPP__
00003 
00004 //
00005 // local includes
00006 //
00007 #include "ata_drive.hpp"
00008 
00012 struct ata_channel : public iospace_handler, public mmio_handler, private noncopyable
00013 {
00014   protected:
00018     const string channel_name;
00019 
00023     l4_gpa_t command_base,
00024 
00028              control_base;
00029 
00033     ata_drive *drives[2];
00034 
00038     uint8_t current_drive;
00039 
00040   public:
00041     //
00042     // constructor & destructor
00043     //
00044     inline ata_channel(machine_base &machine, const string &channel_name, ata_drive *drives[2])
00045         : channel_name(channel_name), command_base(0), control_base(0), current_drive(0)
00046     {
00047         // we always need a drive to handle the protocol correctly
00048         this->drives[0]=drives[0] ? drives[0] : new ata_drive(machine);
00049         this->drives[0]->set_drive_name_index(channel_name + " master", 0);
00050         this->drives[1]=drives[1] ? drives[1] : new ata_drive(machine);
00051         this->drives[1]->set_drive_name_index(channel_name + " slave", 1);
00052     }
00053 
00054     virtual inline ~ata_channel(void)
00055     {
00056         delete drives[1];
00057         delete drives[0];
00058     }
00059 
00060     //
00061     // iospace_handler: override I/O space access handlers
00062     //
00063     virtual inline uint32_t read_ioport(l4_port_t port, access_size access_size)
00064     {
00065         static const char *type="port";
00066         return read_blocks<type, l4_port_t>(port, access_size);
00067     }
00068 
00069     virtual inline int write_ioport(l4_port_t port, uint32_t data, access_size access_size)
00070     {
00071         static const char *type="port";
00072         return write_blocks<type, l4_port_t>(port, data, access_size);
00073     }
00074 
00075     //
00076     // mmio_handler: override read_mmio/write_mmio & I/O memory (un)map functions
00077     //
00078     virtual inline l4_umword_t read_mmio(l4_gpa_t address, access_size access_size)
00079     {
00080         static const char *type="address";
00081         return read_blocks<type, l4_gpa_t>(address, access_size);
00082     }
00083 
00084     virtual inline int write_mmio(l4_gpa_t address, l4_umword_t data, access_size access_size)
00085     {
00086         static const char *type="address";
00087         return write_blocks<type, l4_gpa_t>(address, data, access_size);
00088     }
00089 
00090     virtual inline l4_hva_t map_mmio_region(int flags, l4_gpa_t base, l4_gpa_t size=1)
00091     {
00092         // dummy. should not be called.
00093         return 0;
00094     }
00095 
00096     virtual inline int unmap_mmio_region(l4_gpa_t base, l4_gpa_t size=1)
00097     {
00098         // dummy. should not be called.
00099         return -L4_ENOTSUPP;
00100     }
00101 
00102     //
00103     // channel management functions
00104     //
00105     inline const char *name(void) const
00106     {
00107         return channel_name.c_str();
00108     }
00109 
00110     inline int reset(void)
00111     {
00112         return drives[0]->reset() | drives[1]->reset();
00113     }
00114 
00115     //
00116     // resources functions
00117     //
00118     inline void locate_registers(const l4_gpa_t command_base=0, const l4_gpa_t control_base=0)
00119     {
00120         this->command_base=command_base;
00121         this->control_base=control_base;
00122     }
00123 
00124     inline void set_irq(const l4_irq_t irq)
00125     {
00126         // the controller requests an IRQ, so always (try to) use what is set
00127         drives[0]->set_irq(irq);
00128         drives[1]->set_irq(irq);
00129     }
00130 
00131     inline void assert_irq_if_enabled(void)
00132     {
00133         drives[current_drive]->assert_irq_if_enabled();
00134     }
00135 
00136     //
00137     // DMA read/write functions:
00138     //     read_write as the IDE controller was programed
00139     //
00140     inline int read_write_DMA(uint8_t read_write, l4_gpa_t PRD_base)
00141     {
00142         return drives[current_drive]->read_write_DMA(read_write, PRD_base);
00143     }
00144 
00145   protected:
00146     //
00147     // read & write command & control block functions
00148     //
00149     template <const char *&AddressTypeC, typename AddressT>
00150     inline l4_umword_t read_blocks(AddressT address, access_size access_size)
00151     {
00152         if (command_base && (address >= command_base) && (address < command_base + sizeof(ata_command_block)))
00153             return drives[current_drive]->read_command_block(address - command_base, access_size);
00154 
00155         if (control_base && (address >= control_base) && (address < control_base + sizeof(ata_control_block)))
00156             return drives[current_drive]->read_control_block(address - control_base, access_size);
00157 
00158         logd(L4VMM_DEBUG_ATA >= 2, L4VMM_ERROR": %s:\n  invalid read from %s %s [%d]\n",
00159              name(), AddressTypeC, format_hex<AddressT>(address).c_str(), access_size());
00160         return iospace_handler::INVALID;
00161     }
00162 
00163     template <const char *&AddressTypeC, typename AddressT>
00164     inline int write_blocks(AddressT address, l4_umword_t data, access_size access_size)
00165     {
00166         if (command_base && (address >= command_base) && (address < command_base + sizeof(ata_command_block))) {
00167             //
00168             // check for device register (device bit) & switch drive
00169             //
00170             const ata_command_block::offset_t offset=address - command_base;
00171             if (ata_command_block::is_device(offset))
00172                 current_drive=(data >> ata_command_block::DEVICE_REGISTER_DEVICE_BIT) & 0x01;
00173 
00174             return drives[current_drive]->write_command_block(offset, data, access_size);
00175         }
00176 
00177         if (control_base && (address >= control_base) && (address < control_base + sizeof(ata_control_block)))
00178             return drives[current_drive]->write_control_block(address - control_base, data, access_size);
00179 
00180         logd(L4VMM_DEBUG_ATA >= 2, L4VMM_ERROR": %s:\n  invalid write to %s %s [%d]\n",
00181              name(), AddressTypeC, format_hex<AddressT>(address).c_str(), access_size());
00182         return -L4_EINVAL;
00183     }
00184 };
00185 
00186 #endif
00187 
00188 // ***** end of source ***** //
00189 

L4vmm Reference Manual, written by Mario Schwalbe  © 2006-2008