00001 #if !defined(__ATA_CHANNEL_HPP__)
00002 #define __ATA_CHANNEL_HPP__
00003
00004
00005
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
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
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
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
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
00093 return 0;
00094 }
00095
00096 virtual inline int unmap_mmio_region(l4_gpa_t base, l4_gpa_t size=1)
00097 {
00098
00099 return -L4_ENOTSUPP;
00100 }
00101
00102
00103
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
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
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
00138
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
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
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
00189