2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief ATA device class
|
|
|
|
* \author Sebastian.Sump <Sebastian.Sumpf@genode-labs.com>
|
|
|
|
* \date 2010-07-15
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2013-01-10 21:44:47 +01:00
|
|
|
* Copyright (C) 2010-2013 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _ATA_DEVICE_H_
|
|
|
|
#define _ATA_DEVICE_H_
|
|
|
|
|
|
|
|
#include <base/exception.h>
|
|
|
|
#include <base/stdint.h>
|
2013-12-03 15:41:14 +01:00
|
|
|
#include <block/component.h>
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
namespace Genode {
|
|
|
|
class Io_port_session;
|
|
|
|
class Irq_connection;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace Ata {
|
|
|
|
|
|
|
|
class Bus_master;
|
|
|
|
|
2013-11-28 12:45:20 +01:00
|
|
|
class Device : public Block::Driver
|
2011-12-22 16:19:25 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
/* I/O back end may access private data (see io.cc) */
|
|
|
|
friend Genode::Io_port_session *get_io(Device *dev);
|
|
|
|
friend Genode::Irq_connection *get_irq(Device *dev);
|
|
|
|
friend Bus_master *get_bus_master(Device *dev);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
unsigned char _dev_num;
|
|
|
|
Genode::Io_port_session *_pio;
|
|
|
|
Genode::Irq_connection *_irq;
|
|
|
|
Bus_master *_bus_master;
|
|
|
|
bool _dma;
|
|
|
|
unsigned _block_start;
|
|
|
|
unsigned _block_end;
|
|
|
|
unsigned _block_size;
|
2013-03-01 15:25:39 +01:00
|
|
|
bool _lba48;
|
2013-07-04 15:16:32 +02:00
|
|
|
bool _host_protected_area;
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
void probe_dma();
|
|
|
|
|
|
|
|
void set_bus_master(bool secondary);
|
|
|
|
void set_irq(unsigned irq);
|
|
|
|
void set_dev_num(unsigned char dev_num) { _dev_num = dev_num; }
|
|
|
|
|
|
|
|
unsigned char dev_num() { return _dev_num; }
|
|
|
|
Bus_master *bus_master(){ return _bus_master; }
|
|
|
|
Genode::Irq_connection *irq() { return _irq; }
|
|
|
|
Genode::Io_port_session *io() { return _pio; }
|
|
|
|
|
2013-12-04 14:34:53 +01:00
|
|
|
virtual void _read(Block::sector_t block_number,
|
2013-11-28 12:45:20 +01:00
|
|
|
Genode::size_t block_count,
|
|
|
|
char *out_buffer,
|
|
|
|
bool dma);
|
2013-12-04 14:34:53 +01:00
|
|
|
virtual void _write(Block::sector_t block_number,
|
2013-11-28 12:45:20 +01:00
|
|
|
Genode::size_t block_count,
|
|
|
|
char const *buffer,
|
|
|
|
bool dma);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2013-11-28 12:45:20 +01:00
|
|
|
class Exception : public ::Genode::Exception { };
|
|
|
|
class Io_error : public Exception { };
|
|
|
|
|
2011-12-22 16:19:25 +01:00
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* \param base_cmd I/O port base of command registers
|
|
|
|
* \param base_ctrl I/O prot base of control registers
|
|
|
|
*/
|
|
|
|
Device(unsigned base_cmd, unsigned base_ctrl);
|
|
|
|
~Device();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return and set current device
|
|
|
|
*/
|
|
|
|
static Device * current(Device *dev = 0)
|
|
|
|
{
|
|
|
|
static Device *_current = 0;
|
|
|
|
if (dev) _current = dev;
|
|
|
|
return _current;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Probe legacy bus for device class
|
|
|
|
*
|
|
|
|
* \param search_type REG_CONFIG_TYPE_ATA or REG_CONFIG_TYPE_ATAPI
|
|
|
|
*/
|
|
|
|
static Device * probe_legacy(int search_type);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read block size and block count (from device),
|
|
|
|
* updates block_count and block_size
|
|
|
|
*/
|
|
|
|
virtual void read_capacity();
|
|
|
|
|
|
|
|
|
2013-11-28 12:45:20 +01:00
|
|
|
/*******************************
|
|
|
|
** Block::Driver interface **
|
|
|
|
*******************************/
|
|
|
|
|
2013-12-04 14:34:53 +01:00
|
|
|
Block::sector_t block_count() {
|
2013-11-28 12:45:20 +01:00
|
|
|
return _block_end - _block_start + 1; }
|
|
|
|
Genode::size_t block_size() { return _block_size; }
|
|
|
|
|
|
|
|
virtual Block::Session::Operations ops();
|
|
|
|
|
2013-12-04 14:34:53 +01:00
|
|
|
void read(Block::sector_t block_number,
|
2013-11-28 12:45:20 +01:00
|
|
|
Genode::size_t block_count,
|
2013-12-03 15:41:14 +01:00
|
|
|
char *buffer,
|
|
|
|
Block::Packet_descriptor &packet)
|
|
|
|
{
|
|
|
|
_read(block_number, block_count, buffer, false);
|
|
|
|
session->complete_packet(packet);
|
|
|
|
}
|
|
|
|
|
2013-12-04 14:34:53 +01:00
|
|
|
void write(Block::sector_t block_number,
|
2013-11-28 12:45:20 +01:00
|
|
|
Genode::size_t block_count,
|
2013-12-03 15:41:14 +01:00
|
|
|
char const *buffer,
|
|
|
|
Block::Packet_descriptor &packet)
|
|
|
|
{
|
|
|
|
_write(block_number, block_count, buffer, false);
|
|
|
|
session->complete_packet(packet);
|
|
|
|
}
|
|
|
|
|
2013-12-04 14:34:53 +01:00
|
|
|
void read_dma(Block::sector_t block_number,
|
|
|
|
Genode::size_t block_count,
|
|
|
|
Genode::addr_t phys,
|
2013-12-03 15:41:14 +01:00
|
|
|
Block::Packet_descriptor &packet)
|
|
|
|
{
|
|
|
|
_read(block_number, block_count, (char*)phys, true);
|
|
|
|
session->complete_packet(packet);
|
|
|
|
}
|
|
|
|
|
2013-12-04 14:34:53 +01:00
|
|
|
void write_dma(Block::sector_t block_number,
|
2013-11-28 12:45:20 +01:00
|
|
|
Genode::size_t block_count,
|
2013-12-03 15:41:14 +01:00
|
|
|
Genode::addr_t phys,
|
|
|
|
Block::Packet_descriptor &packet)
|
|
|
|
{
|
|
|
|
_write(block_number, block_count, (char*)phys, true);
|
|
|
|
session->complete_packet(packet);
|
|
|
|
}
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
bool dma_enabled() { return _dma; }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class Atapi_device : public Device
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
|
|
int read_sense(unsigned char *sense, int length);
|
2013-11-28 12:45:20 +01:00
|
|
|
void read_capacity();
|
|
|
|
|
2013-12-04 14:34:53 +01:00
|
|
|
void _read(Block::sector_t block_number,
|
2013-11-28 12:45:20 +01:00
|
|
|
Genode::size_t block_count,
|
|
|
|
char *out_buffer,
|
|
|
|
bool dma);
|
2013-12-04 14:34:53 +01:00
|
|
|
void _write(Block::sector_t block_number,
|
2013-11-28 12:45:20 +01:00
|
|
|
Genode::size_t block_count,
|
|
|
|
char const *buffer,
|
|
|
|
bool dma);
|
2011-12-22 16:19:25 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
Atapi_device(unsigned base_cmd, unsigned base_ctrl);
|
|
|
|
|
|
|
|
bool test_unit_ready(int level = 0);
|
2013-11-28 12:45:20 +01:00
|
|
|
Block::Session::Operations ops();
|
2011-12-22 16:19:25 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|