mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
os: remove ATAPI driver
The driver will be superseeded soon by a new AHCI driver that supports ATAPI devices. There is no IDE support in Gende anymore, however. Issue #1456.
This commit is contained in:
parent
97dc9664fe
commit
2002e1ccba
@ -1,34 +1,15 @@
|
||||
set use_sd_card_drv [expr [have_spec omap4] || [have_spec platform_arndale] || [have_spec pl180]]
|
||||
set use_atapi_drv [have_spec x86]
|
||||
set use_ahci_drv [have_spec x86]
|
||||
|
||||
if {[expr [have_spec linux] || [have_spec hw_odroid_xu]]} {
|
||||
puts "Run script does not support this platform"; exit }
|
||||
|
||||
if {[expr [have_spec 64bit] && $use_atapi_drv]} {
|
||||
puts "ATAPI driver does not support 64 bit."; exit 0 }
|
||||
|
||||
if {![have_include power_on/qemu]} {
|
||||
puts "\nPlease setup your native sd or hard drive. Remove this fail stop";
|
||||
puts "check when you have prepared your native environment.\n";
|
||||
exit 0
|
||||
}
|
||||
|
||||
if {[have_spec x86]} {
|
||||
set qemu "qemu-system-i386"
|
||||
if {[have_spec 64bit]} { set qemu "qemu-system-x86_64" }
|
||||
|
||||
set version [exec $qemu --version]
|
||||
set version [regexp -inline {[0-9]+\.[0-9]+\.[0-9]+} $version]
|
||||
|
||||
if {$version >= 1.5} {
|
||||
puts "Atapi driver on Qemu $version known to be not working.";
|
||||
puts "For more details see Genode issue 827 on github";
|
||||
|
||||
puts stderr "Test requires 'fix for issue 827'"
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
@ -41,7 +22,7 @@ set build_components {
|
||||
|
||||
lappend_if [have_spec pci] build_components drivers/pci
|
||||
lappend_if [have_spec acpi] build_components drivers/acpi
|
||||
lappend_if $use_atapi_drv build_components drivers/atapi
|
||||
lappend_if $use_ahci_drv build_components drivers/ahci
|
||||
lappend_if $use_sd_card_drv build_components drivers/sd_card
|
||||
|
||||
build $build_components
|
||||
@ -108,8 +89,8 @@ append_if [expr ![have_spec acpi] && [have_spec pci]] config {
|
||||
<provides><service name="PCI"/></provides>
|
||||
</start>}
|
||||
|
||||
append_if $use_atapi_drv config {
|
||||
<start name="atapi_drv">
|
||||
append_if $use_ahci_drv config {
|
||||
<start name="ahci">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Block"/> </provides>
|
||||
<config ata="yes" />
|
||||
@ -142,7 +123,7 @@ set boot_modules {
|
||||
|
||||
lappend_if [have_spec pci] boot_modules pci_drv
|
||||
lappend_if [have_spec acpi] boot_modules acpi_drv
|
||||
lappend_if $use_atapi_drv boot_modules atapi_drv
|
||||
lappend_if $use_ahci_drv boot_modules ahci
|
||||
lappend_if $use_sd_card_drv boot_modules sd_card_drv
|
||||
|
||||
build_boot_image $boot_modules
|
||||
@ -160,7 +141,7 @@ catch { exec sh -c $cmd }
|
||||
# Qemu
|
||||
#
|
||||
append qemu_args " -m 128 -nographic "
|
||||
append_if $use_atapi_drv qemu_args " -hda $disk_image -boot order=d "
|
||||
append_if $use_ahci_drv qemu_args " -drive id=disk,file=$disk_image,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -boot d"
|
||||
append_if $use_sd_card_drv qemu_args " -drive file=$disk_image,if=sd,cache=writeback "
|
||||
|
||||
run_genode_until {.*child "test-libc_block" exited with exit value 0.*} 60
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
|
||||
set use_sd_card_drv [expr [have_spec omap4] || [have_spec platform_arndale] || [have_spec pl180]]
|
||||
set use_atapi_drv [have_spec x86]
|
||||
set use_ahci_drv [have_spec x86]
|
||||
|
||||
if {[catch { exec which mkfs.vfat } ]} {
|
||||
puts stderr "Error: mkfs.vfat not installed, aborting test"; exit }
|
||||
@ -26,7 +26,7 @@ set build_components {
|
||||
|
||||
lappend_if [have_spec pci] build_components drivers/pci
|
||||
lappend_if [have_spec acpi] build_components drivers/acpi
|
||||
lappend_if $use_atapi_drv build_components drivers/atapi
|
||||
lappend_if $use_ahci_drv build_components drivers/ahci
|
||||
lappend_if $use_sd_card_drv build_components drivers/sd_card
|
||||
|
||||
build $build_components
|
||||
@ -96,8 +96,8 @@ append_if [expr ![have_spec acpi] && [have_spec pci]] config {
|
||||
<provides><service name="PCI"/></provides>
|
||||
</start>}
|
||||
|
||||
append_if $use_atapi_drv config {
|
||||
<start name="atapi_drv">
|
||||
append_if $use_ahci_drv config {
|
||||
<start name="ahci">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Block"/> </provides>
|
||||
<config ata="yes" />
|
||||
@ -130,7 +130,7 @@ set boot_modules {
|
||||
|
||||
lappend_if [have_spec pci] boot_modules pci_drv
|
||||
lappend_if [have_spec acpi] boot_modules acpi_drv
|
||||
lappend_if $use_atapi_drv boot_modules atapi_drv
|
||||
lappend_if $use_ahci_drv boot_modules ahci
|
||||
lappend_if $use_sd_card_drv boot_modules sd_card_drv
|
||||
|
||||
build_boot_image $boot_modules
|
||||
@ -152,7 +152,7 @@ catch { exec sh -c $cmd }
|
||||
# Qemu
|
||||
#
|
||||
append qemu_args " -m 128 -nographic "
|
||||
append_if $use_atapi_drv qemu_args " -hda $disk_image -boot order=d "
|
||||
append_if $use_ahci_drv qemu_args " -drive id=disk,file=$disk_image,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -boot d"
|
||||
append_if $use_sd_card_drv qemu_args " -drive file=$disk_image,if=sd,cache=writeback "
|
||||
|
||||
run_genode_until {.*child "test-libc_vfs" exited with exit value 0.*} 60
|
||||
|
@ -12,19 +12,8 @@ if {[have_spec hw_odroid_xu]} {
|
||||
# use SD on ARM
|
||||
set use_sd_card_drv [expr [have_spec omap4] || [have_spec platform_arndale] || [have_spec pl180]]
|
||||
|
||||
# use ATAPI on x86 (deprecated)
|
||||
#set use_atapi_drv [have_spec x86]
|
||||
#set use_ahci 0
|
||||
|
||||
# use AHCI on x86
|
||||
set use_ahci [have_spec x86]
|
||||
set use_atapi_drv 0
|
||||
|
||||
|
||||
if {[expr $use_atapi_drv && $use_ahci]} {
|
||||
puts "Usage of atapi and ahci is exclusive - choose one."
|
||||
exit 1
|
||||
}
|
||||
|
||||
if {[catch { exec which $mkfs_cmd } ]} {
|
||||
puts stderr "Error: $mkfs_cmd not installed, aborting test"; exit }
|
||||
@ -32,31 +21,12 @@ if {[catch { exec which $mkfs_cmd } ]} {
|
||||
if {[have_spec linux]} {
|
||||
puts "Run script does not support this platform"; exit }
|
||||
|
||||
if {[expr [have_spec 64bit] && $use_atapi_drv]} {
|
||||
puts "ATAPI driver does not support 64 bit."; exit 0 }
|
||||
|
||||
if {![have_include "power_on/qemu"]} {
|
||||
puts "\nPlease setup your native sd or hard drive. Remove this fail stop";
|
||||
puts "check when you have prepared your native environment.\n";
|
||||
exit 0
|
||||
}
|
||||
|
||||
if {[expr $use_atapi_drv && [have_spec x86]]} {
|
||||
set qemu "qemu-system-i386"
|
||||
if {[have_spec 64bit]} { set qemu "qemu-system-x86_64" }
|
||||
|
||||
set version [exec $qemu --version]
|
||||
set version [regexp -inline {[0-9]+\.[0-9]+\.[0-9]+} $version]
|
||||
|
||||
if {$version >= 1.5} {
|
||||
puts "Atapi driver on Qemu $version known to be not working.";
|
||||
puts "For more details see Genode issue 827 on github";
|
||||
|
||||
puts stderr "Test requires 'fix for issue 827'"
|
||||
exit 0;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
@ -72,7 +42,6 @@ lappend build_components test/libc_$filesystem
|
||||
lappend_if [have_spec pci] build_components drivers/pci
|
||||
lappend_if [have_spec acpi] build_components drivers/acpi
|
||||
lappend_if $use_ahci build_components drivers/ahci
|
||||
lappend_if $use_atapi_drv build_components drivers/atapi
|
||||
lappend_if $use_sd_card_drv build_components drivers/sd_card
|
||||
|
||||
build $build_components
|
||||
@ -142,14 +111,6 @@ append_if [expr ![have_spec acpi] && [have_spec pci]] config {
|
||||
<provides><service name="PCI"/></provides>
|
||||
</start>}
|
||||
|
||||
append_if $use_atapi_drv config {
|
||||
<start name="atapi_drv">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Block"/> </provides>
|
||||
<config ata="yes" />
|
||||
</start>
|
||||
}
|
||||
|
||||
append_if $use_ahci config {
|
||||
<start name="ahci">
|
||||
<binary name="ahci" />
|
||||
@ -193,7 +154,6 @@ append boot_modules libc_$filesystem.lib.so
|
||||
|
||||
lappend_if [have_spec pci] boot_modules pci_drv
|
||||
lappend_if [have_spec acpi] boot_modules acpi_drv
|
||||
lappend_if $use_atapi_drv boot_modules atapi_drv
|
||||
lappend_if $use_ahci boot_modules ahci
|
||||
lappend_if $use_sd_card_drv boot_modules sd_card_drv
|
||||
|
||||
@ -216,7 +176,6 @@ catch { exec sh -c $cmd }
|
||||
# Qemu
|
||||
#
|
||||
append qemu_args " -m 128 -nographic "
|
||||
append_if $use_atapi_drv qemu_args " -hda $disk_image -boot order=d "
|
||||
append_if $use_ahci qemu_args " -drive id=disk,file=$disk_image,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -boot d"
|
||||
append_if $use_sd_card_drv qemu_args " -drive file=$disk_image,if=sd,cache=writeback "
|
||||
|
||||
|
@ -16,9 +16,10 @@ append build_components {
|
||||
}
|
||||
|
||||
set use_sd_card_driver [expr [have_spec omap4] || [have_spec platform_arndale]]
|
||||
set use_ahci_driver [have_spec x86]
|
||||
|
||||
lappend_if $use_sd_card_driver build_components drivers/sd_card
|
||||
lappend_if [have_spec pci] build_components drivers/atapi
|
||||
lappend_if $use_ahci_driver build_components drivers/ahci
|
||||
lappend_if [have_spec acpi] build_components drivers/acpi
|
||||
lappend_if [have_spec linux] build_components server/ram_fs
|
||||
lappend_if [expr ![have_spec linux]] build_components server/ffat_fs
|
||||
@ -48,8 +49,8 @@ append config {
|
||||
|
||||
append config [qt5_start_nodes feature]
|
||||
|
||||
append_if [have_spec pci] config {
|
||||
<start name="atapi_drv">
|
||||
append_if $use_ahci_driver config {
|
||||
<start name="ahci">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Block"/> </provides>
|
||||
<config ata="yes" />
|
||||
@ -143,8 +144,8 @@ append boot_modules {
|
||||
# platform-specific modules
|
||||
lappend_if [have_spec linux] boot_modules ram_fs
|
||||
lappend_if [expr ![have_spec linux]] boot_modules ffat_fs
|
||||
lappend_if [have_spec pci] boot_modules atapi_drv
|
||||
lappend_if $use_sd_card_driver boot_modules sd_card_drv
|
||||
lappend_if $use_ahci_driver boot_modules ahci
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
@ -157,7 +158,7 @@ set cmd "mkfs.vfat -F32 $disk_image"
|
||||
puts "formating disk image with vfat file system: $cmd"
|
||||
catch { exec sh -c $cmd }
|
||||
|
||||
append_if [have_spec pci] qemu_args " -hda $disk_image -boot order=d "
|
||||
append_if $use_ahci_driver qemu_args " -drive id=disk,file=$disk_image,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -boot d"
|
||||
|
||||
append qemu_args " -m 256"
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
This directory contains a port of the MINDRVR PATA/SATA driver (See:
|
||||
[http://ata-atapi.com].
|
||||
|
||||
The driver will probe the system's IDE bus and will use the first ATAPI device
|
||||
present.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Simply start the 'atapi_drv' in your Genode environment. The front-end
|
||||
implemented by the driver is Genode's block interface (see:
|
||||
'os/include/block_session').
|
||||
|
||||
Configuration example:
|
||||
|
||||
! <start name="atapi_drv">
|
||||
! <resource name="RAM" quantum="1M" />
|
||||
! <provides><service name="Block" /></provides>
|
||||
! </start>
|
||||
|
||||
To use the driver as IDE block driver supporting both read and write
|
||||
transactions, supply the XML attribute 'ata="yes"' to the config node of
|
||||
'atapi_drv'.
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* \brief I/O interface to the IDE bus master
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \date 2010-07-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <io_port_session/connection.h>
|
||||
#include <pci_session/connection.h>
|
||||
#include <pci_device/client.h>
|
||||
|
||||
/* local includes */
|
||||
#include "ata_bus_master.h"
|
||||
#include "mindrvr.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Ata::Bus_master::Bus_master(bool secondary) : _bmiba(0), _secondary(secondary)
|
||||
{}
|
||||
|
||||
|
||||
Ata::Bus_master::~Bus_master()
|
||||
{
|
||||
destroy(env()->heap(), _pio);
|
||||
}
|
||||
|
||||
|
||||
bool Ata::Bus_master::scan_pci()
|
||||
{
|
||||
Pci::Connection pci;
|
||||
Pci::Device_capability prev_device_cap,
|
||||
device_cap = pci.first_device();
|
||||
|
||||
/* test if standard legacy ports are used, if not skip */
|
||||
uint32_t legacy = _secondary ? PI_CH2_LEGACY : PI_CH1_LEGACY;
|
||||
|
||||
while (device_cap.valid()) {
|
||||
pci.release_device(prev_device_cap);
|
||||
prev_device_cap = device_cap;
|
||||
|
||||
::Pci::Device_client device(device_cap);
|
||||
|
||||
if ((device.class_code() & CLASS_MASK)
|
||||
== (CLASS_MASS_STORAGE | SUBCLASS_IDE) &&
|
||||
!(device.class_code() & legacy)) {
|
||||
Genode::printf("Found IDE Bus Master (Vendor ID: %04x Device ID: %04x Class: %08x)\n",
|
||||
device.vendor_id(), device.device_id(), device.class_code());
|
||||
|
||||
/* read BMIBA */
|
||||
_bmiba = device.config_read(PCI_CFG_BMIBA_OFF,
|
||||
::Pci::Device::ACCESS_32BIT);
|
||||
|
||||
if (_bmiba == 0xffff)
|
||||
_bmiba = 0;
|
||||
|
||||
/* port I/O or memory mapped ? */
|
||||
_port_io = _bmiba & 0x1 ? true : false;
|
||||
|
||||
/* XXX cbass: This may only be true for Intel IDE controllers */
|
||||
if (_bmiba && _port_io) {
|
||||
_bmiba &= 0xfff0;
|
||||
_pio = new(env()->heap()) Genode::Io_port_connection(_bmiba, 0x10);
|
||||
|
||||
if (_secondary)
|
||||
_bmiba += 0x8;
|
||||
}
|
||||
|
||||
Genode::printf("\tBus master interface base addr: %08x (%s) secondary (%s) (%s)\n",
|
||||
_bmiba, _port_io ? "I/O" : "MEM",
|
||||
_secondary ? "yes" : "no",
|
||||
_bmiba ? "supported" : "invalid");
|
||||
|
||||
pci.release_device(prev_device_cap);
|
||||
return _bmiba;
|
||||
}
|
||||
|
||||
device_cap = pci.next_device(prev_device_cap);
|
||||
}
|
||||
|
||||
/* release last device */
|
||||
pci.release_device(prev_device_cap);
|
||||
|
||||
return _bmiba;
|
||||
}
|
||||
|
||||
|
||||
unsigned char Ata::Bus_master::read_cmd()
|
||||
{
|
||||
if (!_bmiba || !_port_io)
|
||||
return 0;
|
||||
|
||||
return _pio->inb(_bmiba + BM_COMMAND_REG);
|
||||
}
|
||||
|
||||
|
||||
unsigned char Ata::Bus_master::read_status()
|
||||
{
|
||||
if (!_bmiba || !_port_io)
|
||||
return 0;
|
||||
|
||||
return _pio->inb(_bmiba + BM_STATUS_REG);
|
||||
}
|
||||
|
||||
|
||||
void Ata::Bus_master::write_cmd(unsigned char val)
|
||||
{
|
||||
if (!_bmiba || !_port_io)
|
||||
return;
|
||||
|
||||
_pio->outb(_bmiba + BM_COMMAND_REG, val);
|
||||
}
|
||||
|
||||
|
||||
void Ata::Bus_master::write_status(unsigned char val)
|
||||
{
|
||||
if (!_bmiba || !_port_io)
|
||||
return;
|
||||
|
||||
_pio->outb(_bmiba + BM_STATUS_REG, val);
|
||||
}
|
||||
|
||||
|
||||
void Ata::Bus_master::write_prd(unsigned long val)
|
||||
{
|
||||
if (!_bmiba || !_port_io)
|
||||
return;
|
||||
|
||||
if (val == _prd_virt) {
|
||||
_pio->outl(_bmiba + BM_PRD_ADDR_LOW, _prd_phys);
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* \brief I/O interface to the IDE bus master
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \date 2010-07-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* 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_PCI_H_
|
||||
#define _ATA_PCI_H_
|
||||
|
||||
namespace Genode {
|
||||
class Io_port_connection;
|
||||
}
|
||||
|
||||
namespace Ata {
|
||||
|
||||
class Bus_master {
|
||||
|
||||
enum {
|
||||
PCI_CFG_BMIBA_OFF = 0x20, /* offset in PCI config space */
|
||||
CLASS_MASS_STORAGE = 0x10000,
|
||||
SUBCLASS_IDE = 0x0100,
|
||||
CLASS_MASK = 0xffff00,
|
||||
|
||||
/* These bits of the programming interface part within the class code
|
||||
* define if the corresponding channel operates on standard legacy ports
|
||||
* (bits are cleared) or if the corresponding ports in base register 0-1
|
||||
* and 2-3 for channel 2 must be used as I/O bases (bits are set) */
|
||||
PI_CH1_LEGACY = 0x1,
|
||||
PI_CH2_LEGACY = 0x4,
|
||||
};
|
||||
|
||||
/**
|
||||
* Bus master interface base address
|
||||
*/
|
||||
unsigned _bmiba;
|
||||
|
||||
bool _port_io;
|
||||
bool _secondary;
|
||||
unsigned long _prd_virt;
|
||||
unsigned long _prd_phys;
|
||||
Genode::Io_port_connection *_pio;
|
||||
|
||||
public:
|
||||
|
||||
Bus_master(bool secondary);
|
||||
~Bus_master();
|
||||
|
||||
unsigned char read_cmd();
|
||||
unsigned char read_status();
|
||||
|
||||
void write_cmd(unsigned char val);
|
||||
void write_status(unsigned char val);
|
||||
void write_prd(unsigned long val);
|
||||
|
||||
void set_prd(unsigned long virt, unsigned long phys)
|
||||
{
|
||||
_prd_virt = virt;
|
||||
_prd_phys = phys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan PCI Bus for IDE devices and set BMBIA
|
||||
*/
|
||||
bool scan_pci();
|
||||
|
||||
};
|
||||
}
|
||||
#endif /* _ATA_PCI_H_ */
|
@ -1,317 +0,0 @@
|
||||
/*
|
||||
* \brief ATA device class
|
||||
* \author Sebastian.Sump <Sebastian.Sumpf@genode-labs.com>
|
||||
* \date 2010-07-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/lock.h>
|
||||
#include <io_port_session/io_port_session.h>
|
||||
#include <irq_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include "ata_device.h"
|
||||
#include "ata_bus_master.h"
|
||||
#include "io.h"
|
||||
#include "mindrvr.h"
|
||||
|
||||
static const int verbose = 0;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
Ata::Device::Device(unsigned base_cmd, unsigned base_ctrl)
|
||||
: _lba48(false), _host_protected_area(false)
|
||||
{
|
||||
_pio = new(env()->heap()) Ata::Io_port(base_cmd, base_ctrl);
|
||||
}
|
||||
|
||||
|
||||
Ata::Device::~Device()
|
||||
{
|
||||
destroy(env()->heap(), _pio);
|
||||
|
||||
if (_irq)
|
||||
destroy(env()->heap(), _irq);
|
||||
|
||||
if (_bus_master)
|
||||
destroy(env()->heap(), _bus_master);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Ata::Device::set_bus_master(bool secondary)
|
||||
{
|
||||
_bus_master = new(env()->heap()) Ata::Bus_master(secondary);
|
||||
}
|
||||
|
||||
|
||||
void Ata::Device::set_irq(unsigned irq)
|
||||
{
|
||||
_irq = new(env()->heap()) Irq_connection(irq);
|
||||
}
|
||||
|
||||
|
||||
void Ata::Device::probe_dma()
|
||||
{
|
||||
/* find bus master interface base address */
|
||||
if (!_bus_master->scan_pci())
|
||||
return;
|
||||
|
||||
/* read device information */
|
||||
reg_reset(dev_num());
|
||||
|
||||
unsigned char *buffer;
|
||||
if (!(env()->heap()->alloc(4096, &buffer))) return;
|
||||
|
||||
unsigned char cmd = dynamic_cast<Atapi_device *>(this) ? CMD_IDENTIFY_DEVICE_PACKET : CMD_IDENTIFY_DEVICE;
|
||||
if (!reg_pio_data_in_lba28(
|
||||
dev_num(),
|
||||
cmd,
|
||||
0, 1,
|
||||
0L,
|
||||
buffer,
|
||||
1L, 0 )) {
|
||||
|
||||
/* check command set's LBA48 bit */
|
||||
_lba48 = !!(buffer[167] & 0x4);
|
||||
/* check for host protected area feature */
|
||||
_host_protected_area = !!(buffer[165] & 0x4);
|
||||
|
||||
Genode::printf( "Adress mode is LBA%d\n", _lba48 ? 48 : 28 );
|
||||
Genode::printf("UDMA Modes supported:\n");
|
||||
|
||||
for (int i = 0; i <= 5; i++) {
|
||||
Genode::printf("\t%d and below: %s enabled: %s\n",
|
||||
i ,(buffer[176] & (1 << i)) ? "yes" : "no",
|
||||
(buffer[177] & (1 << i)) ? "yes" : "no");
|
||||
|
||||
if (buffer[177] & (1 << i)) {
|
||||
|
||||
/* initialize PRD's */
|
||||
dma_pci_config();
|
||||
_dma = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env()->heap()->free(buffer, 4096);
|
||||
}
|
||||
|
||||
|
||||
void Ata::Device::read_capacity()
|
||||
{
|
||||
_block_start = 0;
|
||||
_block_size = 512;
|
||||
|
||||
enum {
|
||||
CMD_NATIVE_MAX_ADDRESS = 0xf8, /* LBA28 */
|
||||
CMD_NATIVE_MAX_ADDRESS_EXT = 0x27, /* LBA48 */
|
||||
};
|
||||
|
||||
/*
|
||||
* If both LBA48 is enabled and host protected area feature is set, then NATIVE MAX
|
||||
* ADDRESS EXT becomes mandatory, use LBA28 otherwise
|
||||
*/
|
||||
if (_lba48 && _host_protected_area) {
|
||||
if (!reg_non_data_lba48(dev_num(), CMD_NATIVE_MAX_ADDRESS_EXT, 0, 1, 0UL, 0UL)) {
|
||||
|
||||
_block_end = _pio->inb(CB_SN); /* 0 - 7 */
|
||||
_block_end |= _pio->inb(CB_CL) << 8; /* 8 - 15 */
|
||||
_block_end |= _pio->inb(CB_CH) << 16; /* 16 - 23 */
|
||||
|
||||
/* read higher order LBA registers */
|
||||
_pio->outb(CB_DC, CB_DC_HOB);
|
||||
_block_end |= _pio->inb(CB_SN) << 24; /* 24 - 31 */
|
||||
/* FIXME: read bits 32 - 47 */
|
||||
|
||||
}
|
||||
} else {
|
||||
if (!reg_non_data_lba28(dev_num(), CMD_NATIVE_MAX_ADDRESS, 0, 1, 0UL)) {
|
||||
|
||||
_block_end = _pio->inb(CB_SN); /* 0 - 7 */
|
||||
_block_end |= _pio->inb(CB_CL) << 8; /* 8 - 15 */
|
||||
_block_end |= _pio->inb(CB_CH) << 16; /* 16 - 23 */
|
||||
_block_end |= (_pio->inb(CB_DH) & 0xf) << 24; /* 24 - 27 */
|
||||
}
|
||||
}
|
||||
|
||||
PINF("First block: %u last block %u, block size %u",
|
||||
_block_start, _block_end, _block_size);
|
||||
}
|
||||
|
||||
|
||||
void Ata::Device::_read(Block::sector_t block_nr,
|
||||
Genode::size_t count,
|
||||
char *buffer,
|
||||
bool dma)
|
||||
{
|
||||
Genode::size_t offset = 0;
|
||||
|
||||
while (count > 0) {
|
||||
Genode::size_t c = count > 255 ? 255 : count;
|
||||
|
||||
if (dma) {
|
||||
|
||||
if (verbose)
|
||||
PDBG("DMA read: block %llu, c %zu, buffer: %p",
|
||||
block_nr, c, (void*)(buffer + offset));
|
||||
|
||||
if (!_lba48)
|
||||
{
|
||||
if (dma_pci_lba28(dev_num(), CMD_READ_DMA, 0, c, block_nr,
|
||||
(unsigned char*)(buffer + offset), c))
|
||||
throw Io_error();
|
||||
} else {
|
||||
if (dma_pci_lba48(dev_num(), CMD_READ_DMA_EXT, 0, c, 0, block_nr,
|
||||
(unsigned char*)(buffer + offset), c))
|
||||
throw Io_error();
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!_lba48)
|
||||
{
|
||||
if (reg_pio_data_in_lba28(dev_num(), CMD_READ_SECTORS, 0, c, block_nr,
|
||||
(unsigned char*)(buffer + offset), c, 0))
|
||||
throw Io_error();
|
||||
} else {
|
||||
if (reg_pio_data_in_lba48(dev_num(), CMD_READ_SECTORS_EXT, 0, c, 0, block_nr,
|
||||
(unsigned char*)(buffer + offset), c, 0))
|
||||
throw Io_error();
|
||||
}
|
||||
}
|
||||
|
||||
count -= c;
|
||||
block_nr += c;
|
||||
offset += c * block_size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ata::Device::_write(Block::sector_t block_nr,
|
||||
Genode::size_t count,
|
||||
char const *buffer,
|
||||
bool dma)
|
||||
{
|
||||
Genode::size_t offset = 0;
|
||||
|
||||
while (count > 0) {
|
||||
Genode::size_t c = count > 255 ? 255 : count;
|
||||
|
||||
if (dma) {
|
||||
|
||||
if (verbose)
|
||||
PDBG("DMA read: block %llu, c %zu, buffer: %p",
|
||||
block_nr, c, (void*)(buffer + offset));
|
||||
|
||||
if (!_lba48)
|
||||
{
|
||||
if (dma_pci_lba28(dev_num(), CMD_WRITE_DMA, 0, c, block_nr,
|
||||
(unsigned char*)(buffer + offset), c))
|
||||
throw Io_error();
|
||||
}
|
||||
else {
|
||||
if (dma_pci_lba48(dev_num(), CMD_WRITE_DMA_EXT, 0, c, 0, block_nr,
|
||||
(unsigned char*)(buffer + offset), c))
|
||||
throw Io_error();
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!_lba48)
|
||||
{
|
||||
if (reg_pio_data_out_lba28(dev_num(), CMD_WRITE_SECTORS, 0, c, block_nr,
|
||||
(unsigned char*)(buffer + offset), c, 0))
|
||||
throw Io_error();
|
||||
} else {
|
||||
if (reg_pio_data_out_lba48(dev_num(), CMD_WRITE_SECTORS_EXT, 0, c, 0, block_nr,
|
||||
(unsigned char*)(buffer + offset), c, 0))
|
||||
throw Io_error();
|
||||
}
|
||||
}
|
||||
|
||||
count -= c;
|
||||
block_nr += c;
|
||||
offset += c * block_size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ata::Device * Ata::Device::probe_legacy(int search_type)
|
||||
{
|
||||
unsigned base[] = { 0x1f0, 0x170 };
|
||||
unsigned dev_irq[] = { 14, 15 };
|
||||
|
||||
const char *type = "";
|
||||
for (int i = 0; i < 2; i++) {
|
||||
|
||||
Device *dev = new (env()->heap() )Device(base[i], base[i] + 0x200);
|
||||
Device::current(dev);
|
||||
|
||||
/* Scan for devices */
|
||||
reg_config();
|
||||
|
||||
for (unsigned char j = 0; j < 2; j++) {
|
||||
|
||||
switch (reg_config_info[j]) {
|
||||
|
||||
case REG_CONFIG_TYPE_NONE:
|
||||
type = "none"; break;
|
||||
|
||||
case REG_CONFIG_TYPE_UNKN:
|
||||
type = "unknown"; break;
|
||||
|
||||
case REG_CONFIG_TYPE_ATA:
|
||||
type = "ATA"; break;
|
||||
|
||||
case REG_CONFIG_TYPE_ATAPI:
|
||||
type = "ATAPI";
|
||||
destroy (env()->heap(), dev);
|
||||
dev = new (env()->heap() )Atapi_device(base[i], base[i] + 0x200);
|
||||
break;
|
||||
|
||||
default:
|
||||
type = "";
|
||||
}
|
||||
|
||||
Genode::printf("IDE %d Device %d: %s IRQ: %u\n", i, j, type, dev_irq[i]);
|
||||
|
||||
/* prepare device */
|
||||
if (reg_config_info[j] == search_type) {
|
||||
|
||||
dev->set_bus_master(i);
|
||||
dev->set_dev_num(j);
|
||||
dev->set_irq(dev_irq[i]);
|
||||
|
||||
dev->probe_dma();
|
||||
Genode::printf("Device initialized! Enabling interrupts ...\n");
|
||||
int_use_intr_flag = 1;
|
||||
reg_reset(dev->dev_num());
|
||||
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
|
||||
type = "";
|
||||
destroy(env()->heap(), dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Block::Session::Operations Ata::Device::ops()
|
||||
{
|
||||
Block::Session::Operations o;
|
||||
o.set_operation(Block::Packet_descriptor::READ);
|
||||
o.set_operation(Block::Packet_descriptor::WRITE);
|
||||
return o;
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
/*
|
||||
* \brief ATA device class
|
||||
* \author Sebastian.Sump <Sebastian.Sumpf@genode-labs.com>
|
||||
* \date 2010-07-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* 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>
|
||||
#include <block/component.h>
|
||||
|
||||
namespace Genode {
|
||||
class Io_port_session;
|
||||
class Irq_connection;
|
||||
}
|
||||
|
||||
namespace Ata {
|
||||
|
||||
class Bus_master;
|
||||
|
||||
class Device : public Block::Driver
|
||||
{
|
||||
|
||||
/* 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;
|
||||
bool _lba48;
|
||||
bool _host_protected_area;
|
||||
|
||||
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; }
|
||||
|
||||
virtual void _read(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char *out_buffer,
|
||||
bool dma);
|
||||
virtual void _write(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char const *buffer,
|
||||
bool dma);
|
||||
|
||||
public:
|
||||
|
||||
class Exception : public ::Genode::Exception { };
|
||||
class Io_error : public Exception { };
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
|
||||
/*******************************
|
||||
** Block::Driver interface **
|
||||
*******************************/
|
||||
|
||||
Block::sector_t block_count() {
|
||||
return _block_end - _block_start + 1; }
|
||||
Genode::size_t block_size() { return _block_size; }
|
||||
|
||||
virtual Block::Session::Operations ops();
|
||||
|
||||
void read(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char *buffer,
|
||||
Block::Packet_descriptor &packet)
|
||||
{
|
||||
_read(block_number, block_count, buffer, false);
|
||||
ack_packet(packet);
|
||||
}
|
||||
|
||||
void write(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char const *buffer,
|
||||
Block::Packet_descriptor &packet)
|
||||
{
|
||||
_write(block_number, block_count, buffer, false);
|
||||
ack_packet(packet);
|
||||
}
|
||||
|
||||
void read_dma(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
Genode::addr_t phys,
|
||||
Block::Packet_descriptor &packet)
|
||||
{
|
||||
_read(block_number, block_count, (char*)phys, true);
|
||||
ack_packet(packet);
|
||||
}
|
||||
|
||||
void write_dma(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
Genode::addr_t phys,
|
||||
Block::Packet_descriptor &packet)
|
||||
{
|
||||
_write(block_number, block_count, (char*)phys, true);
|
||||
ack_packet(packet);
|
||||
}
|
||||
|
||||
bool dma_enabled() { return _dma; }
|
||||
};
|
||||
|
||||
|
||||
class Atapi_device : public Device
|
||||
{
|
||||
private:
|
||||
|
||||
int read_sense(unsigned char *sense, int length);
|
||||
void read_capacity();
|
||||
|
||||
void _read(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char *out_buffer,
|
||||
bool dma);
|
||||
void _write(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char const *buffer,
|
||||
bool dma);
|
||||
|
||||
public:
|
||||
|
||||
Atapi_device(unsigned base_cmd, unsigned base_ctrl);
|
||||
|
||||
bool test_unit_ready(int level = 0);
|
||||
Block::Session::Operations ops();
|
||||
};
|
||||
}
|
||||
#endif
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* \brief ATAPI specific implementation of an Ata::Device
|
||||
* \author Sebastian.Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2010-07-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <util/string.h>
|
||||
|
||||
/* local includes */
|
||||
#include "ata_device.h"
|
||||
#include "ata_bus_master.h"
|
||||
#include "endian.h"
|
||||
#include "mindrvr.h"
|
||||
|
||||
static const int verbose = 0;
|
||||
|
||||
using namespace Ata;
|
||||
using namespace Genode;
|
||||
|
||||
enum Commands {
|
||||
CMD_READ_10 = 0x28,
|
||||
CMD_READ_CAPACITY = 0x25,
|
||||
CMD_REQUEST_SENSE = 0x03,
|
||||
CMD_TEST_UNIT_READY = 0x00,
|
||||
};
|
||||
|
||||
|
||||
Atapi_device::Atapi_device(unsigned base_cmd, unsigned base_ctrl)
|
||||
: Device(base_cmd, base_ctrl) { }
|
||||
|
||||
|
||||
int Atapi_device::read_sense(unsigned char *sense, int length)
|
||||
{
|
||||
unsigned char cmd_sense[12];
|
||||
|
||||
memset(cmd_sense, 0, 12);
|
||||
memset(sense, 0, length);
|
||||
|
||||
cmd_sense[0] = CMD_REQUEST_SENSE;
|
||||
cmd_sense[4] = length; /* allocation length */
|
||||
return reg_packet(dev_num(), 12, cmd_sense, 0, length, sense);
|
||||
}
|
||||
|
||||
|
||||
bool Atapi_device::test_unit_ready(int level)
|
||||
{
|
||||
unsigned char cmd[12];
|
||||
|
||||
memset(cmd, 0, 12);
|
||||
cmd[0] = CMD_TEST_UNIT_READY;
|
||||
|
||||
if (reg_packet(dev_num(), 12, cmd, 0, 0, 0)) {
|
||||
unsigned char sense[32];
|
||||
read_sense(sense, 32);
|
||||
|
||||
PERR("Sense: key %x sub-key %x", sense[2], sense[12]);
|
||||
if (level < 3)
|
||||
return test_unit_ready(level + 1);
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Atapi_device::read_capacity()
|
||||
{
|
||||
unsigned char cmd[12];
|
||||
unsigned buffer[2];
|
||||
memset(cmd, 0, 12);
|
||||
memset(buffer, 0, 8);
|
||||
|
||||
cmd[0] = CMD_READ_CAPACITY;
|
||||
|
||||
if (!test_unit_ready())
|
||||
throw Io_error();
|
||||
|
||||
if (reg_packet(dev_num(), 12, cmd, 0, 8, (unsigned char *)buffer))
|
||||
throw Io_error();
|
||||
|
||||
_block_start = 0;
|
||||
_block_end = bswap32(buffer[0]);
|
||||
_block_size = bswap32(buffer[1]);
|
||||
|
||||
if (verbose)
|
||||
PDBG("First block: %u last block %u, block size %u",
|
||||
_block_start, _block_end, _block_size);
|
||||
}
|
||||
|
||||
|
||||
void Atapi_device::_read(Block::sector_t block_nr,
|
||||
Genode::size_t count,
|
||||
char *buffer,
|
||||
bool dma)
|
||||
{
|
||||
unsigned char cmd[12];
|
||||
memset(cmd, 0, 12);
|
||||
|
||||
cmd[0] = CMD_READ_10;
|
||||
|
||||
block_nr += _block_start;
|
||||
|
||||
if (block_nr < _block_start || block_nr + count > _block_end + 1)
|
||||
throw Io_error();
|
||||
|
||||
/* block address */
|
||||
cmd[2] = (block_nr >> 24) & 0xff;
|
||||
cmd[3] = (block_nr >> 16) & 0xff;
|
||||
cmd[4] = (block_nr >> 8) & 0xff;
|
||||
cmd[5] = block_nr & 0xff;
|
||||
|
||||
/* transfer length */
|
||||
cmd[7] = (count >> 8) & 0xff;
|
||||
cmd[8] = count & 0xff;
|
||||
|
||||
if (dma) {
|
||||
if (verbose)
|
||||
PDBG("DMA read: block %llu, count %zu, buffer: %p",
|
||||
block_nr, count, (void*)buffer);
|
||||
|
||||
if (dma_pci_packet(dev_num(), 12, cmd, 0, count * _block_size,
|
||||
(unsigned char*)buffer))
|
||||
throw Io_error();
|
||||
} else {
|
||||
if (reg_packet(dev_num(), 12, cmd, 0, count * _block_size,
|
||||
(unsigned char*)buffer))
|
||||
throw Io_error();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Atapi_device::_write(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char const *buffer,
|
||||
bool dma) { throw Io_error(); }
|
||||
|
||||
|
||||
Block::Session::Operations Atapi_device::ops()
|
||||
{
|
||||
Block::Session::Operations o;
|
||||
o.set_operation(Block::Packet_descriptor::READ);
|
||||
return o;
|
||||
}
|
@ -1,387 +0,0 @@
|
||||
|
||||
|
||||
MINDRVR
|
||||
Simple ATA/ATAPI Low Level Driver for Embedded Systems
|
||||
User's Guide
|
||||
|
||||
by Hale Landis
|
||||
|
||||
Version 0G and higher
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
------------
|
||||
|
||||
MINDRVR is a simple version of ATADRVR. ATADRVR is Hale Landis'
|
||||
C code that shows the low level programming required to configure
|
||||
and execute commands on ATA and ATAPI devices. MINDRVR is
|
||||
suitable for embedded systems that have simple ATA interface
|
||||
hardware that is memory mapped. MINDRVR does not have some
|
||||
features of ATADRVR, such as, the command and low level trace
|
||||
facility, no support for ATA CHS addressing, no and checking of
|
||||
ATAPI command protocol errors.
|
||||
|
||||
MINDRVR is fully contained in two files: MINDRVR.H and
|
||||
MINDRVR.C.
|
||||
|
||||
MINDRVR, like ATADRVR, supports all of the ATA and ATA/ATAPI
|
||||
standards.
|
||||
|
||||
The MINDRVR C code has been placed into the public domain by Hale
|
||||
Landis. This C code has no copyright or other restrictions on
|
||||
how it is used.
|
||||
|
||||
|
||||
USING MINDRVR
|
||||
-------------
|
||||
|
||||
Normally a "file system" driver would call MINDRVR to perform actual
|
||||
phyical I/O operations on ATA or ATAPI devices using PIO or DMA data
|
||||
transfer modes. Any program or driver that calls MINDRVR must include
|
||||
the MINDRVR.H header file. MINDRVR.H defines all the MINDRVR public
|
||||
functions and public data.
|
||||
|
||||
The basics of using MINDRVR are:
|
||||
|
||||
1) Review the MINDRVR.H and MINDRVR.C files. In these files look
|
||||
for comment lines that have the string '!!!'. These comments
|
||||
explain the information you must provide at compile time, such
|
||||
as, the memory addresses for the ATA registers in your
|
||||
system's memory.
|
||||
|
||||
2) #include "mindrvr.h" in your program or driver that will call
|
||||
MINDRVR.
|
||||
|
||||
3) Call reg_config() so that MINDRVR can determine what devices
|
||||
are attached to the ATA host adapter.
|
||||
|
||||
4) Call reg_reset() or any of the other "reg_" functions to issue
|
||||
ATA or ATAPI commands in PIO data transfer mode. If your
|
||||
system can support ATA/ATAPI DMA then call the dma_pci_"
|
||||
functions to issue ATA or ATAPI commands in DMA data transfer
|
||||
mode.
|
||||
|
||||
Note that MINDRVR is designed for systems with a single ATA
|
||||
controller (single ATA inteface). If you system has multiple ATA
|
||||
controllers/interfaces then you will need to either: a) make a
|
||||
separate MINDRVR for each controller, or b) switch between
|
||||
controllers by swapping the MINDRVR configuration information
|
||||
between calls to MINDRVR.
|
||||
|
||||
|
||||
MINDRVR REFERENCE
|
||||
-----------------
|
||||
|
||||
Each of the public functions and symbols of MINDRVR are described
|
||||
below in alphabetical order.
|
||||
|
||||
Note that there is no "interrupt handler" defined by MINDRVR.
|
||||
You must supply the appropriate interrupt handler as described in
|
||||
MINDRVR.H and MINDRVR.C.
|
||||
|
||||
|
||||
Public Data
|
||||
-----------
|
||||
|
||||
unsigned char int_ata_status;
|
||||
|
||||
When using interrupts the interrupt handler must return this
|
||||
data. This is the interrupting device's ATA status as read by
|
||||
interrupt handler.
|
||||
|
||||
unsigned char int_bmide_status;
|
||||
|
||||
When using interrupts the interrupt handler must return this
|
||||
data. This is the interrupting controller's BMIDE status read
|
||||
by interrupt handler.
|
||||
|
||||
unsigned char int_use_intr_flag;
|
||||
|
||||
MINDRVR can be switched between polling mode and interrupt
|
||||
mode. Note that interrupt mode is required for DMA data
|
||||
transfers.
|
||||
|
||||
Make this value not zero to use interrupts.
|
||||
|
||||
unsigned char pio_xfer_width;
|
||||
|
||||
This variable controls the width of PIO data transfers.
|
||||
This variable can have the following values:
|
||||
|
||||
8 = 8-bits. PIO transfers will use 8-bit memory write/read
|
||||
when accessing the ATA Data register.
|
||||
|
||||
16 = 16-bits. PIO transfers will use 16-bit memory write/read
|
||||
when accessing the ATA Data register.
|
||||
|
||||
32 = 32-bits. PIO transfers will 32-bit memory write/read
|
||||
when accessing the ATA Data register.
|
||||
|
||||
Any other value is treated the same as 16.
|
||||
|
||||
struct REG_CMD_INFO
|
||||
{
|
||||
// command code
|
||||
unsigned char cmd; // command code
|
||||
// command parameters
|
||||
unsigned int fr; // feature (8 or 16 bits)
|
||||
unsigned int sc; // sec cnt (8 or 16 bits)
|
||||
unsigned int sn; // sec num (8 or 16 bits)
|
||||
unsigned int cl; // cyl low (8 or 16 bits)
|
||||
unsigned int ch; // cyl high (8 or 16 bits)
|
||||
unsigned char dh; // device head
|
||||
unsigned char dc; // device control
|
||||
long ns; // actual sector count
|
||||
int mc; // current multiple block setting
|
||||
unsigned char lbaSize; // size of LBA used
|
||||
#define LBACHS 0 // last command used ATA CHS (not supported by MINDRVR)
|
||||
// -or- last command was ATAPI PACKET command
|
||||
#define LBA28 28 // last command used ATA 28-bit LBA
|
||||
#define LBA48 48 // last command used ATA 48-bit LBA
|
||||
unsigned long lbaLow; // lower 32-bits of ATA LBA
|
||||
unsigned long lbaHigh; // upper 32-bits of ATA LBA
|
||||
// status and error regs
|
||||
unsigned char st; // status reg
|
||||
unsigned char as; // alt status reg
|
||||
unsigned char er ; // error reg
|
||||
// driver error codes
|
||||
unsigned char ec; // detailed error code
|
||||
unsigned char to; // not zero if time out error
|
||||
// additional result info
|
||||
long totalBytesXfer; // total bytes transfered
|
||||
long drqPackets; // number of PIO DRQ packets
|
||||
} ;
|
||||
struct REG_CMD_INFO reg_cmd_info;
|
||||
|
||||
This data structure contains information about the last reset or command
|
||||
that was executed.
|
||||
|
||||
int reg_config( void );
|
||||
|
||||
This function shoul be called so that MINDRVR can correctly
|
||||
configure itself. reg_config() sets the values into
|
||||
reg_config_info[2].
|
||||
|
||||
Note that the program calling MINDRVR may bypass calling this
|
||||
function as long as reg_config_info[] is set appropriately
|
||||
before attempting to execute any resets or commands.
|
||||
|
||||
int reg_config_info[2];
|
||||
|
||||
This array is set by calling reg_config(). reg_config_info[0]
|
||||
describes device 0 and reg_config_info[1] describes device 1.
|
||||
The possible values in these words are (see MINDRVR.H):
|
||||
REG_CONFIG_TYPE_NONE, REG_CONFIG_TYPE_UNKN,
|
||||
REG_CONFIG_TYPE_ATA, REG_CONFIG_TYPE_ATAPI.
|
||||
|
||||
Note that MINDRVR is not able to determine the type of some
|
||||
devices. However, after issuing some commands the calling
|
||||
program may be able to determine the exact type of a device.
|
||||
The calling program may change the values in this array but
|
||||
this must be done very carefully:
|
||||
|
||||
a) DO NOT CHANGE the value REG_CONFIG_TYPE_NONE.
|
||||
b) DO NOT CHANGE a value to REG_CONFIG_TYPE_NONE.
|
||||
c) The value REG_CONFIG_TYPE_UNKN can be changed to either
|
||||
REG_CONFIG_TYPE_ATA or REG_CONFIG_TYPE_ATAPI.
|
||||
|
||||
int reg_non_data_lba28( unsigned char dev, // device (0 or 1)
|
||||
unsigned char cmd, // command register
|
||||
int fr, // feature register
|
||||
int sc, // sector count
|
||||
long lba ); // LBA
|
||||
|
||||
Execute an ATA Non-Data command using LBA sector addressing.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int reg_non_data_lba48( unsigned char dev, // device (0 or 1)
|
||||
unsigned char cmd, // command register
|
||||
int fr, // feature register
|
||||
int sc, // sector count
|
||||
long lbahi, // LBA upper 16-bits
|
||||
long lbalo ); // LBA lower 32 bits
|
||||
|
||||
Execute an ATA Non-Data command using LBA sector addressing.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int reg_packet( unsigned char dev, // device (0 or 1)
|
||||
unsigned int cpbc, // command packet size
|
||||
unsigned char * cdbBufAddr, // CDB buffer
|
||||
int dir, // 0 for no data or read, 1 for write
|
||||
unsigned int dpbc, // max data packet size
|
||||
unsigned char * dataBufAddr ); // data packet buffer
|
||||
|
||||
Execute an ATAPI Packet (A0H) command in PIO mode. Note that
|
||||
the first byte of the Commmand Packet buffer is the command
|
||||
code of the "SCSI CDB" that is to be executed by the device.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int reg_pio_data_in_lba28( unsigned char dev, // device (0 or 1)
|
||||
unsigned char cmd, // command register
|
||||
int fr, // feature register
|
||||
int sc, // sector count
|
||||
long lba, // LBA
|
||||
unsigned char * bufAddr, // buffer address
|
||||
int numSect, // number of sectors to transfer
|
||||
int multiCnt ); // current multiple count
|
||||
|
||||
Execute an ATA PIO Data In command in LBA sector addressing
|
||||
mode.
|
||||
|
||||
numSect is the actual number of sectors to be transferred.
|
||||
This value may be different than the sc value.
|
||||
|
||||
If cmd is C4H (Read Multiple) then multiCnt MUST be set to the
|
||||
current sectors per block.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int reg_pio_data_in_lba48( unsigned char dev, // device (0 or 1)
|
||||
unsigned char cmd, // command register
|
||||
int fr, // feature register
|
||||
int sc, // sector count
|
||||
long lbahi, // LBA upper 16-bits
|
||||
long lbalo, // LBA lower 32 bits
|
||||
unsigned char * bufAddr, // buffer address
|
||||
int numSect, // number of sectors to transfer
|
||||
int multiCnt ); // current multiple count
|
||||
|
||||
Execute an ATA PIO Data In command in LBA sector addressing
|
||||
mode.
|
||||
|
||||
numSect is the actual number of sectors to be transferred.
|
||||
This value may be different than the sc value.
|
||||
|
||||
If cmd is C4H (Read Multiple) then multiCnt MUST be set to the
|
||||
current sectors per block.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int reg_pio_data_out_lba28( unsigned char dev, // device (0 or 1)
|
||||
unsigned char cmd, // command register
|
||||
int fr, // feature register
|
||||
int sc, // sector count
|
||||
long lba, // LBA
|
||||
unsigned char * bufAddr, // buffer address
|
||||
int numSect, // number of sectors to transfer
|
||||
int multiCnt ); // current multiple count
|
||||
|
||||
Execute an ATA PIO Data Out command in LBA sector addressing
|
||||
mode.
|
||||
|
||||
numSect is the actual number of sectors to be transferred.
|
||||
This value may be different than the sc value.
|
||||
|
||||
If cmd is C5H (Write Multiple) then multiCnt MUST be set to
|
||||
the current sectors per block.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int reg_pio_data_out_lba48( unsigned char dev, // device (0 or 1)
|
||||
unsigned char cmd, // command register
|
||||
int fr, // feature register
|
||||
int sc, // sector count
|
||||
long lbahi, // LBA upper 16-bits
|
||||
long lbalo, // LBA lower 32 bits
|
||||
unsigned char * bufAddr, // buffer address
|
||||
int numSect, // number of sectors to transfer
|
||||
int multiCnt ); // current multiple count
|
||||
|
||||
Execute an ATA PIO Data Out command in LBA sector addressing
|
||||
mode.
|
||||
|
||||
numSect is the actual number of sectors to be transferred.
|
||||
This value may be different than the sc value.
|
||||
|
||||
If cmd is C5H (Write Multiple) then multiCnt MUST be set to
|
||||
the current sectors per block.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int reg_reset( unsigned char devRtrn ); // device's data returned
|
||||
|
||||
Execute an ATA Soft Reset. Set devRtrn to 0 or 1 to determine
|
||||
which device's register contents are returned in reg_cmd_info.
|
||||
|
||||
|
||||
DMA Data Transfer Functions And Data
|
||||
------------------------------------
|
||||
|
||||
These functions setup PCI bus DMA (ATA Multiword or Ultra DMA)
|
||||
and perform ATA and ATAPI commands using DMA. The function
|
||||
dma_pci_config() MUST be called with no error before any of the
|
||||
other functions will attempt to execute a command.
|
||||
|
||||
int dma_pci_config( void );
|
||||
|
||||
Configure MINDRVR to use PCI bus DMA (ATA Multiword or Ultra
|
||||
DMA) on a PCI Bus Mastering ATA controller.
|
||||
|
||||
This function may not be needed in your system - see the MINDRVR.H
|
||||
and MINDRVR.C files.
|
||||
|
||||
int dma_pci_lba28( unsigned char dev, // device (0 or 1)
|
||||
unsigned char cmd, // command register
|
||||
int fr, // feature register
|
||||
int sc, // sector count
|
||||
long lba, // LBA
|
||||
unsigned char * bufAddr ); // buffer address
|
||||
|
||||
Execute an ATA Read DMA (C8H) or ATA Write DMA (CAH) command
|
||||
using LBA sector addressing.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int dma_pci_lba48( unsigned char dev, // device (0 or 1)
|
||||
unsigned char cmd, // command register
|
||||
int fr, // feature register
|
||||
int sc, // sector count
|
||||
long lbahi, // LBA upper 16-bits
|
||||
long lbalo, // LBA lower 32 bits
|
||||
unsigned char * bufAddr ); // buffer address
|
||||
|
||||
Execute an ATA Read DMA (C8H) or ATA Write DMA (CAH) command
|
||||
using LBA sector addressing.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
int dma_pci_packet( unsigned char dev, // device (0 or 1)
|
||||
unsigned int cpbc, // command packet size
|
||||
unsigned char * cdbBufAddr, // CDB buffer
|
||||
int dir, // 0 for no data or read, 1 for write
|
||||
unsigned int dpbc, // max data packet size
|
||||
unsigned char * dataBufAddr ); // data packet buffer
|
||||
|
||||
Execute an ATAPI Packet (A0H) command in DMA mode. Note that
|
||||
the first byte of the Commmand Packet buffer is the command
|
||||
code of the "SCSI CDB" that is to be executed by the device.
|
||||
|
||||
Returns 0 if no error or 1 if there is an error. See the
|
||||
contents of reg_cmd_info.
|
||||
|
||||
|
||||
QUESTIONS OR PROBLEMS?
|
||||
----------------------
|
||||
|
||||
Send your question(s) or problem description(s) to Hale Landis
|
||||
via email at this address:
|
||||
|
||||
hlandis@ata-atapi.com
|
||||
|
||||
Visit Hale's web site:
|
||||
|
||||
www.ata-atapi.com
|
||||
|
||||
/end/
|
File diff suppressed because it is too large
Load Diff
@ -1,450 +0,0 @@
|
||||
//********************************************************************
|
||||
// MINIMUM ATA LOW LEVEL I/O DRIVER -- MINDRVR.H
|
||||
//
|
||||
// by Hale Landis (hlandis@ata-atapi.com)
|
||||
//
|
||||
// There is no copyright and there are no restrictions on the use
|
||||
// of this ATA Low Level I/O Driver code. It is distributed to
|
||||
// help other programmers understand how the ATA device interface
|
||||
// works and it is distributed without any warranty. Use this
|
||||
// code at your own risk.
|
||||
//
|
||||
// Minimum ATA Driver (MINDRVR) is a subset of ATADRVR. MINDRVR
|
||||
// has a single header file and a single C file. MINDRVR can
|
||||
// be used as the starting point for an ATADRVR for an embedded
|
||||
// system. NOTE all the places in the MINDRVR.H and MINDRVR.C files
|
||||
// where there is a comment containing the string "!!!".
|
||||
//
|
||||
// Use the header file mindrvr.h in any C files that call MINDRVR
|
||||
// functions.
|
||||
//
|
||||
// This code is based on the ATA/ATAPI-4,-5 and -6 standards and
|
||||
// on interviews with various ATA controller and drive designers.
|
||||
//
|
||||
// Note that MINDRVR does not support ATA CHS addressing.
|
||||
//
|
||||
// Most of the MINDRVR code is standard C code and should compile
|
||||
// using any C compiler. It has been tested using Borland C/C++ 4.5.
|
||||
//
|
||||
// This C source file is the header file for the driver
|
||||
// and is used in the MINDRVR.C files and must also be used
|
||||
// by any program using the MINDRVR code/functions.
|
||||
//********************************************************************
|
||||
|
||||
#define MIN_ATA_DRIVER_VERSION "0H"
|
||||
|
||||
//********************************************************************
|
||||
//
|
||||
// !!! What parts of MINDRVR do you want in your build?
|
||||
//
|
||||
//********************************************************************
|
||||
|
||||
#define INCLUDE_ATA_DMA 1 // not zero to include ATA_DMA
|
||||
|
||||
#define INCLUDE_ATAPI_PIO 1 // not zero to include ATAPI PIO
|
||||
|
||||
#define INCLUDE_ATAPI_DMA 1 // not zero to include ATAPI DMA
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//********************************************************************
|
||||
//
|
||||
// !!! System specific functions and data you must supply
|
||||
//
|
||||
//********************************************************************
|
||||
|
||||
// You must supply a function that waits for an interrupt from the
|
||||
// ATA controller. This function should return 0 when the interrupt
|
||||
// is received and a non zero value if the interrupt is not received
|
||||
// within the time out period.
|
||||
|
||||
extern int SYSTEM_WAIT_INTR_OR_TIMEOUT( void );
|
||||
|
||||
// You must supply a function that returns a system timer value. This
|
||||
// should be a value that increments at some constant rate.
|
||||
|
||||
extern long SYSTEM_READ_TIMER( void );
|
||||
|
||||
// This defines the number of system timer ticks per second.
|
||||
|
||||
#define SYSTEM_TIMER_TICKS_PER_SECOND 1L
|
||||
|
||||
//********************************************************************
|
||||
//
|
||||
// !!! ATA controller hardware specific data
|
||||
//
|
||||
//********************************************************************
|
||||
|
||||
// ATA Command Block base address
|
||||
// (the address of the ATA Data register)
|
||||
#define PIO_BASE_ADDR1 ( (unsigned char *) 0x1000 )
|
||||
|
||||
// ATA Control Block base address
|
||||
// (the address of the ATA DevCtrl
|
||||
// and AltStatus registers)
|
||||
#define PIO_BASE_ADDR2 ( (unsigned char *) 0x2000 )
|
||||
|
||||
// BMIDE base address (address of
|
||||
// the BMIDE Command register for
|
||||
// the Primary or Secondary side of
|
||||
// the PCI ATA controller)
|
||||
#define PIO_BMIDE_BASE_ADDR ( (unsigned char *) 0x3000 )
|
||||
|
||||
// Size of the ATA Data register - allowed values are 8, 16 and 32
|
||||
#define PIO_DEFAULT_XFER_WIDTH 16
|
||||
|
||||
// Interrupts or polling mode - not zero to use interrrupts
|
||||
// Note: Interrupt mode is required for DMA
|
||||
#define INT_DEFAULT_INTERRUPT_MODE 0
|
||||
|
||||
// Command time out in seconds
|
||||
#define TMR_TIME_OUT 20
|
||||
|
||||
//**************************************************************
|
||||
//
|
||||
// Data that MINDRVR makes available.
|
||||
//
|
||||
//**************************************************************
|
||||
|
||||
// public interrupt handler data
|
||||
|
||||
extern unsigned char int_ata_status; // ATA status read by interrupt handler
|
||||
|
||||
extern unsigned char int_bmide_status; // BMIDE status read by interrupt handler
|
||||
|
||||
// Interrupt or Polling mode flag.
|
||||
|
||||
extern unsigned char int_use_intr_flag; // not zero to use interrupts
|
||||
|
||||
// ATA Data register width (8, 16 or 32)
|
||||
|
||||
extern unsigned char pio_xfer_width;
|
||||
|
||||
// Command and extended error information returned by the
|
||||
// reg_reset(), reg_non_data_*(), reg_pio_data_in_*(),
|
||||
// reg_pio_data_out_*(), reg_packet() and dma_pci_*() functions.
|
||||
|
||||
struct REG_CMD_INFO
|
||||
{
|
||||
// command code
|
||||
unsigned char cmd; // command code
|
||||
// command parameters
|
||||
unsigned int fr; // feature (8 or 16 bits)
|
||||
unsigned int sc; // sec cnt (8 or 16 bits)
|
||||
unsigned int sn; // sec num (8 or 16 bits)
|
||||
unsigned int cl; // cyl low (8 or 16 bits)
|
||||
unsigned int ch; // cyl high (8 or 16 bits)
|
||||
unsigned char dh; // device head
|
||||
unsigned char dc; // device control
|
||||
long ns; // actual sector count
|
||||
int mc; // current multiple block setting
|
||||
unsigned char lbaSize; // size of LBA used
|
||||
#define LBACHS 0 // last command used ATA CHS (not supported by MINDRVR)
|
||||
// -or- last command was ATAPI PACKET command
|
||||
#define LBA28 28 // last command used ATA 28-bit LBA
|
||||
#define LBA48 48 // last command used ATA 48-bit LBA
|
||||
unsigned long lbaLow; // lower 32-bits of ATA LBA
|
||||
unsigned long lbaHigh; // upper 32-bits of ATA LBA
|
||||
// status and error regs
|
||||
unsigned char st; // status reg
|
||||
unsigned char as; // alt status reg
|
||||
unsigned char er ; // error reg
|
||||
// driver error codes
|
||||
unsigned char ec; // detailed error code
|
||||
unsigned char to; // not zero if time out error
|
||||
// additional result info
|
||||
long totalBytesXfer; // total bytes transfered
|
||||
long drqPackets; // number of PIO DRQ packets
|
||||
} ;
|
||||
|
||||
extern struct REG_CMD_INFO reg_cmd_info;
|
||||
|
||||
// Configuration data for device 0 and 1
|
||||
// returned by the reg_config() function.
|
||||
|
||||
extern int reg_config_info[2];
|
||||
|
||||
#define REG_CONFIG_TYPE_NONE 0
|
||||
#define REG_CONFIG_TYPE_UNKN 1
|
||||
#define REG_CONFIG_TYPE_ATA 2
|
||||
#define REG_CONFIG_TYPE_ATAPI 3
|
||||
|
||||
//**************************************************************
|
||||
//
|
||||
// Global defines -- ATA register and register bits.
|
||||
// command block & control block regs
|
||||
//
|
||||
//**************************************************************
|
||||
|
||||
// These are the offsets into pio_reg_addrs[]
|
||||
|
||||
#define CB_DATA 0 // data reg in/out cmd_blk_base1+0
|
||||
#define CB_ERR 1 // error in cmd_blk_base1+1
|
||||
#define CB_FR 1 // feature reg out cmd_blk_base1+1
|
||||
#define CB_SC 2 // sector count in/out cmd_blk_base1+2
|
||||
#define CB_SN 3 // sector number in/out cmd_blk_base1+3
|
||||
#define CB_CL 4 // cylinder low in/out cmd_blk_base1+4
|
||||
#define CB_CH 5 // cylinder high in/out cmd_blk_base1+5
|
||||
#define CB_DH 6 // device head in/out cmd_blk_base1+6
|
||||
#define CB_STAT 7 // primary status in cmd_blk_base1+7
|
||||
#define CB_CMD 7 // command out cmd_blk_base1+7
|
||||
#define CB_ASTAT 8 // alternate status in ctrl_blk_base2+6
|
||||
#define CB_DC 8 // device control out ctrl_blk_base2+6
|
||||
|
||||
// error reg (CB_ERR) bits
|
||||
|
||||
#define CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC
|
||||
#define CB_ER_BBK 0x80 // ATA bad block
|
||||
#define CB_ER_UNC 0x40 // ATA uncorrected error
|
||||
#define CB_ER_MC 0x20 // ATA media change
|
||||
#define CB_ER_IDNF 0x10 // ATA id not found
|
||||
#define CB_ER_MCR 0x08 // ATA media change request
|
||||
#define CB_ER_ABRT 0x04 // ATA command aborted
|
||||
#define CB_ER_NTK0 0x02 // ATA track 0 not found
|
||||
#define CB_ER_NDAM 0x01 // ATA address mark not found
|
||||
|
||||
#define CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask)
|
||||
#define CB_ER_P_MCR 0x08 // ATAPI Media Change Request
|
||||
#define CB_ER_P_ABRT 0x04 // ATAPI command abort
|
||||
#define CB_ER_P_EOM 0x02 // ATAPI End of Media
|
||||
#define CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication
|
||||
|
||||
// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
|
||||
|
||||
#define CB_SC_P_TAG 0xf8 // ATAPI tag (mask)
|
||||
#define CB_SC_P_REL 0x04 // ATAPI release
|
||||
#define CB_SC_P_IO 0x02 // ATAPI I/O
|
||||
#define CB_SC_P_CD 0x01 // ATAPI C/D
|
||||
|
||||
// bits 7-4 of the device/head (CB_DH) reg
|
||||
|
||||
#define CB_DH_LBA 0x40 // LBA bit
|
||||
#define CB_DH_DEV0 0x00 // select device 0
|
||||
#define CB_DH_DEV1 0x10 // select device 1
|
||||
// #define CB_DH_DEV0 0xa0 // select device 0 (old definition)
|
||||
// #define CB_DH_DEV1 0xb0 // select device 1 (old definition)
|
||||
|
||||
// status reg (CB_STAT and CB_ASTAT) bits
|
||||
|
||||
#define CB_STAT_BSY 0x80 // busy
|
||||
#define CB_STAT_RDY 0x40 // ready
|
||||
#define CB_STAT_DF 0x20 // device fault
|
||||
#define CB_STAT_WFT 0x20 // write fault (old name)
|
||||
#define CB_STAT_SKC 0x10 // seek complete (only SEEK command)
|
||||
#define CB_STAT_SERV 0x10 // service (overlap/queued commands)
|
||||
#define CB_STAT_DRQ 0x08 // data request
|
||||
#define CB_STAT_CORR 0x04 // corrected (obsolete)
|
||||
#define CB_STAT_IDX 0x02 // index (obsolete)
|
||||
#define CB_STAT_ERR 0x01 // error (ATA)
|
||||
#define CB_STAT_CHK 0x01 // check (ATAPI)
|
||||
|
||||
// device control reg (CB_DC) bits
|
||||
|
||||
#define CB_DC_HOB 0x80 // High Order Byte (48-bit LBA)
|
||||
// #define CB_DC_HD15 0x00 // bit 3 is reserved
|
||||
// #define CB_DC_HD15 0x08 // (old definition of bit 3)
|
||||
#define CB_DC_SRST 0x04 // soft reset
|
||||
#define CB_DC_NIEN 0x02 // disable interrupts
|
||||
|
||||
//**************************************************************
|
||||
//
|
||||
// Most mandtory and optional ATA commands
|
||||
//
|
||||
//**************************************************************
|
||||
|
||||
#define CMD_CFA_ERASE_SECTORS 0xC0
|
||||
#define CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
|
||||
#define CMD_CFA_TRANSLATE_SECTOR 0x87
|
||||
#define CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
|
||||
#define CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
|
||||
#define CMD_CHECK_POWER_MODE1 0xE5
|
||||
#define CMD_CHECK_POWER_MODE2 0x98
|
||||
#define CMD_DEVICE_RESET 0x08
|
||||
#define CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
|
||||
#define CMD_FLUSH_CACHE 0xE7
|
||||
#define CMD_FLUSH_CACHE_EXT 0xEA
|
||||
#define CMD_FORMAT_TRACK 0x50
|
||||
#define CMD_IDENTIFY_DEVICE 0xEC
|
||||
#define CMD_IDENTIFY_DEVICE_PACKET 0xA1
|
||||
#define CMD_IDENTIFY_PACKET_DEVICE 0xA1
|
||||
#define CMD_IDLE1 0xE3
|
||||
#define CMD_IDLE2 0x97
|
||||
#define CMD_IDLE_IMMEDIATE1 0xE1
|
||||
#define CMD_IDLE_IMMEDIATE2 0x95
|
||||
#define CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
|
||||
#define CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
|
||||
#define CMD_NOP 0x00
|
||||
#define CMD_PACKET 0xA0
|
||||
#define CMD_READ_BUFFER 0xE4
|
||||
#define CMD_READ_DMA 0xC8
|
||||
#define CMD_READ_DMA_EXT 0x25
|
||||
#define CMD_READ_DMA_QUEUED 0xC7
|
||||
#define CMD_READ_DMA_QUEUED_EXT 0x26
|
||||
#define CMD_READ_MULTIPLE 0xC4
|
||||
#define CMD_READ_MULTIPLE_EXT 0x29
|
||||
#define CMD_READ_SECTORS 0x20
|
||||
#define CMD_READ_SECTORS_EXT 0x24
|
||||
#define CMD_READ_VERIFY_SECTORS 0x40
|
||||
#define CMD_READ_VERIFY_SECTORS_EXT 0x42
|
||||
#define CMD_RECALIBRATE 0x10
|
||||
#define CMD_SEEK 0x70
|
||||
#define CMD_SET_FEATURES 0xEF
|
||||
#define CMD_SET_MULTIPLE_MODE 0xC6
|
||||
#define CMD_SLEEP1 0xE6
|
||||
#define CMD_SLEEP2 0x99
|
||||
#define CMD_SMART 0xB0
|
||||
#define CMD_STANDBY1 0xE2
|
||||
#define CMD_STANDBY2 0x96
|
||||
#define CMD_STANDBY_IMMEDIATE1 0xE0
|
||||
#define CMD_STANDBY_IMMEDIATE2 0x94
|
||||
#define CMD_WRITE_BUFFER 0xE8
|
||||
#define CMD_WRITE_DMA 0xCA
|
||||
#define CMD_WRITE_DMA_EXT 0x35
|
||||
#define CMD_WRITE_DMA_QUEUED 0xCC
|
||||
#define CMD_WRITE_DMA_QUEUED_EXT 0x36
|
||||
#define CMD_WRITE_MULTIPLE 0xC5
|
||||
#define CMD_WRITE_MULTIPLE_EXT 0x39
|
||||
#define CMD_WRITE_SECTORS 0x30
|
||||
#define CMD_WRITE_SECTORS_EXT 0x34
|
||||
#define CMD_WRITE_VERIFY 0x3C
|
||||
|
||||
//**************************************************************
|
||||
//
|
||||
// ATA and ATAPI PIO support functions
|
||||
//
|
||||
//**************************************************************
|
||||
|
||||
// config and reset funcitons
|
||||
|
||||
extern int reg_config( void );
|
||||
|
||||
extern int reg_reset( unsigned char devRtrn );
|
||||
|
||||
// ATA Non-Data command funnctions (for LBA28 and LBA48)
|
||||
|
||||
extern int reg_non_data_lba28( unsigned char dev, unsigned char cmd,
|
||||
unsigned int fr, unsigned int sc,
|
||||
unsigned long lba );
|
||||
|
||||
extern int reg_non_data_lba48( unsigned char dev, unsigned char cmd,
|
||||
unsigned int fr, unsigned int sc,
|
||||
unsigned long lbahi, unsigned long lbalo );
|
||||
|
||||
// ATA PIO Data In command functions (for LBA28 and LBA48)
|
||||
|
||||
extern int reg_pio_data_in_lba28( unsigned char dev, unsigned char cmd,
|
||||
unsigned int fr, unsigned int sc,
|
||||
unsigned long lba,
|
||||
unsigned char * bufAddr,
|
||||
long numSect, int multiCnt );
|
||||
|
||||
extern int reg_pio_data_in_lba48( unsigned char dev, unsigned char cmd,
|
||||
unsigned int fr, unsigned int sc,
|
||||
unsigned long lbahi, unsigned long lbalo,
|
||||
unsigned char * bufAddr,
|
||||
long numSect, int multiCnt );
|
||||
|
||||
// ATA PIO Data Out command functions (for LBA28 and LBA48)
|
||||
|
||||
extern int reg_pio_data_out_lba28( unsigned char dev, unsigned char cmd,
|
||||
unsigned int fr, unsigned int sc,
|
||||
unsigned long lba,
|
||||
unsigned char * bufAddr,
|
||||
long numSect, int multiCnt );
|
||||
|
||||
extern int reg_pio_data_out_lba48( unsigned char dev, unsigned char cmd,
|
||||
unsigned int fr, unsigned int sc,
|
||||
unsigned long lbahi, unsigned long lbalo,
|
||||
unsigned char * bufAddr,
|
||||
long numSect, int multiCnt );
|
||||
|
||||
#if INCLUDE_ATAPI_PIO
|
||||
|
||||
// ATAPI Packet PIO function
|
||||
|
||||
extern int reg_packet( unsigned char dev,
|
||||
unsigned int cpbc,
|
||||
unsigned char * cdbBufAddr,
|
||||
int dir,
|
||||
long dpbc,
|
||||
unsigned char * dataBufAddr );
|
||||
|
||||
#endif // INCLUDE_ATAPI_PIO
|
||||
|
||||
//**************************************************************
|
||||
//
|
||||
// ATA and ATAPI DMA support functions
|
||||
//
|
||||
//**************************************************************
|
||||
|
||||
#if INCLUDE_ATA_DMA || INCLUDE_ATAPI_DMA
|
||||
|
||||
// BMIDE registers and bits
|
||||
|
||||
#define BM_COMMAND_REG 0 // offset to BM command reg
|
||||
#define BM_CR_MASK_READ 0x00 // read from memory
|
||||
#define BM_CR_MASK_WRITE 0x08 // write to memory
|
||||
#define BM_CR_MASK_START 0x01 // start transfer
|
||||
#define BM_CR_MASK_STOP 0x00 // stop transfer
|
||||
|
||||
#define BM_STATUS_REG 2 // offset to BM status reg
|
||||
#define BM_SR_MASK_SIMPLEX 0x80 // simplex only
|
||||
#define BM_SR_MASK_DRV1 0x40 // drive 1 can do dma
|
||||
#define BM_SR_MASK_DRV0 0x20 // drive 0 can do dma
|
||||
#define BM_SR_MASK_INT 0x04 // INTRQ signal asserted
|
||||
#define BM_SR_MASK_ERR 0x02 // error
|
||||
#define BM_SR_MASK_ACT 0x01 // active
|
||||
|
||||
#define BM_PRD_ADDR_LOW 4 // offset to BM prd addr reg low 16 bits
|
||||
#define BM_PRD_ADDR_HIGH 6 // offset to BM prd addr reg high 16 bits
|
||||
|
||||
#define MAX_TRANSFER_SIZE 262144L // max transfer size (in bytes,
|
||||
// should be multiple of 65536)
|
||||
|
||||
#define MAX_SEG ((MAX_TRANSFER_SIZE/65536L)+2L) // number physical segments
|
||||
#define MAX_PRD (MAX_SEG*4L) // number of PRDs required
|
||||
|
||||
#define PRD_BUF_SIZE (48+(2*MAX_PRD*8)) // size of PRD list buffer
|
||||
// PCI DMA setup function (usually called once).
|
||||
|
||||
// !!! You may not need this function in your system - see the comments
|
||||
// !!! for this function in MINDRVR.C.
|
||||
|
||||
extern int dma_pci_config( void );
|
||||
|
||||
// ATA DMA functions
|
||||
|
||||
extern int dma_pci_lba28( unsigned char dev, unsigned char cmd,
|
||||
unsigned int fr, unsigned int sc,
|
||||
unsigned long lba,
|
||||
unsigned char * bufAddr,
|
||||
long numSect );
|
||||
|
||||
extern int dma_pci_lba48( unsigned char dev, unsigned char cmd,
|
||||
unsigned int fr, unsigned int sc,
|
||||
unsigned long lbahi, unsigned long lbalo,
|
||||
unsigned char * bufAddr,
|
||||
long numSect );
|
||||
|
||||
#endif // INCLUDE_ATA_DMA or INCLUDE_ATAPI_DMA
|
||||
|
||||
#if INCLUDE_ATAPI_DMA
|
||||
|
||||
// ATA DMA function
|
||||
|
||||
extern int dma_pci_packet( unsigned char dev,
|
||||
unsigned int cpbc,
|
||||
unsigned char * cdbBufAddr,
|
||||
int dir,
|
||||
long dpbc,
|
||||
unsigned char * dataBufAddr );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* extern "C" */
|
||||
|
||||
#endif // INCLUDE_ATAPI_DMA
|
||||
|
||||
// end mindrvr.h
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* \brief Convert host endianess to big endian
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2010-08-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
#ifndef _ENDIAN_H_
|
||||
#define _ENDIAN_H_
|
||||
|
||||
template <typename T>
|
||||
inline T bswap32(T x)
|
||||
{
|
||||
unsigned char v[4] = {
|
||||
(unsigned char)((x & 0xff000000) >> 24),
|
||||
(unsigned char)((x & 0x00ff0000) >> 16),
|
||||
(unsigned char)((x & 0x0000ff00) >> 8),
|
||||
(unsigned char)((x & 0x000000ff) >> 0),
|
||||
};
|
||||
return *(T *)v;
|
||||
}
|
||||
|
||||
#endif /* _ENDIAN_H_ */
|
||||
|
@ -1,256 +0,0 @@
|
||||
/*
|
||||
* \brief I/O back-end of the mindrvr driver
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2010-07-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <base/thread.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <io_port_session/connection.h>
|
||||
#include <irq_session/connection.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
#include "ata_device.h"
|
||||
#include "ata_bus_master.h"
|
||||
#include "mindrvr.h"
|
||||
#include "pio.h"
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Ata;
|
||||
|
||||
namespace Ata {
|
||||
|
||||
/**
|
||||
* Alarm thread, which counts jiffies and triggers timeout events.
|
||||
*/
|
||||
class Timeout_thread : public Thread<4096>
|
||||
{
|
||||
private:
|
||||
|
||||
Timer::Connection _timer; /* timer session */
|
||||
long _jiffies; /* jiffies counter */
|
||||
|
||||
void entry(void);
|
||||
|
||||
public:
|
||||
|
||||
enum { GRANULARITY_MSECS = 1000 };
|
||||
|
||||
Timeout_thread()
|
||||
: Thread<4096>("jiffies"), _jiffies(0)
|
||||
{
|
||||
start();
|
||||
}
|
||||
|
||||
long time(void) { return _jiffies; }
|
||||
|
||||
/*
|
||||
* Returns the singleton timeout-thread used for all timeouts.
|
||||
*/
|
||||
static Timeout_thread *timer();
|
||||
};
|
||||
|
||||
|
||||
void Timeout_thread::entry()
|
||||
{
|
||||
while (true) {
|
||||
_timer.msleep(GRANULARITY_MSECS);
|
||||
_jiffies += 1;
|
||||
|
||||
if (_jiffies < 0)
|
||||
_jiffies = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Timeout_thread *Timeout_thread::timer()
|
||||
{
|
||||
static Timeout_thread _timer;
|
||||
return &_timer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
** Mindrvr back-end C-bindings **
|
||||
*********************************/
|
||||
|
||||
namespace Ata {
|
||||
|
||||
/*
|
||||
* Friends of Device class
|
||||
*/
|
||||
inline Genode::Io_port_session * get_io(Device *dev)
|
||||
{
|
||||
return dev->io();
|
||||
}
|
||||
|
||||
|
||||
inline Bus_master * get_bus_master(Device *dev)
|
||||
{
|
||||
return dev->bus_master();
|
||||
}
|
||||
|
||||
|
||||
inline Genode::Irq_connection * get_irq(Device *dev)
|
||||
{
|
||||
return dev->irq();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" unsigned char pio_inbyte(unsigned char addr)
|
||||
{
|
||||
return get_io(Device::current())->inb(addr);
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned int pio_inword(unsigned char addr)
|
||||
{
|
||||
return get_io(Device::current())->inw(addr);
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned long pio_indword(unsigned char addr)
|
||||
{
|
||||
return get_io(Device::current())->inl(addr);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void pio_outbyte(int addr, unsigned char data)
|
||||
{
|
||||
get_io(Device::current())->outb(addr, data);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void pio_outword(int addr, unsigned int data)
|
||||
{
|
||||
get_io(Device::current())->outw(addr, data);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void pio_outdword(int addr, unsigned long data)
|
||||
{
|
||||
get_io(Device::current())->outl(addr, data);
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned char pio_readBusMstrCmd(void)
|
||||
{
|
||||
if (!get_bus_master(Device::current())) return 0;
|
||||
return get_bus_master(Device::current())->read_cmd();
|
||||
}
|
||||
|
||||
|
||||
extern "C" unsigned char pio_readBusMstrStatus(void)
|
||||
{
|
||||
if (!get_bus_master(Device::current())) return 0;
|
||||
return get_bus_master(Device::current())->read_status();
|
||||
}
|
||||
|
||||
|
||||
extern "C" void pio_writeBusMstrCmd(unsigned char x)
|
||||
{
|
||||
if (!get_bus_master(Device::current())) return;
|
||||
get_bus_master(Device::current())->write_cmd(x);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void pio_writeBusMstrStatus(unsigned char x)
|
||||
{
|
||||
if (!get_bus_master(Device::current())) return;
|
||||
get_bus_master(Device::current())->write_status(x);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void pio_writeBusMstrPrd(unsigned long x)
|
||||
{
|
||||
if (!get_bus_master(Device::current())) return;
|
||||
get_bus_master(Device::current())->write_prd(x);
|
||||
}
|
||||
|
||||
|
||||
extern "C" long SYSTEM_READ_TIMER(void)
|
||||
{
|
||||
return Ata::Timeout_thread::timer()->time();
|
||||
}
|
||||
|
||||
|
||||
/* We just wait for interrupts */
|
||||
extern "C" int SYSTEM_WAIT_INTR_OR_TIMEOUT(void)
|
||||
{
|
||||
get_irq(Device::current())->wait_for_irq();
|
||||
int_ata_status = pio_inbyte(CB_STAT);
|
||||
int_bmide_status = get_bus_master(Device::current())->read_status();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int printf(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
Genode::vprintf(format, args);
|
||||
va_end(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure/setup for Read/Write DMA
|
||||
*
|
||||
* The caller must call this function before attempting to use any ATA or ATAPI
|
||||
* commands in PCI DMA mode.
|
||||
*
|
||||
* MINDRVR assumes the entire DMA data transfer is contained within a single
|
||||
* contiguous I/O buffer. You may not need the 'dma_pci_config()' function
|
||||
* depending on how your system allocates the PRD buffer.
|
||||
*
|
||||
* This function shows an example of PRD buffer allocation. The PRD buffer
|
||||
* must be aligned on a 8 byte boundary and must not cross a 64K byte boundary
|
||||
* in memory.
|
||||
*/
|
||||
extern "C" int dma_pci_config( void )
|
||||
{
|
||||
extern unsigned char *prdBuf;
|
||||
extern unsigned long *prdBufPtr;
|
||||
extern unsigned char statReg;
|
||||
extern unsigned long *dma_pci_prd_ptr;
|
||||
extern int dma_pci_num_prd;
|
||||
|
||||
/*
|
||||
* Set up the PRD entry list buffer address - the PRD entry list may not
|
||||
* span a 64KB boundary in physical memory. Space is allocated (above) for
|
||||
* this buffer such that it will be aligned on a seqment boundary and such
|
||||
* that the PRD list will not span a 64KB boundary...
|
||||
* ... return the address of the first PRD
|
||||
*/
|
||||
|
||||
Dataspace_capability ds_cap = env()->ram_session()->alloc(PRD_BUF_SIZE);
|
||||
unsigned long *prd_addr = env()->rm_session()->attach(ds_cap);
|
||||
Dataspace_client ds_client(ds_cap);
|
||||
|
||||
Genode::printf("PRD base at %08lx (physical) at %08lx (virtual)\n",
|
||||
ds_client.phys_addr(), (long)prd_addr);
|
||||
|
||||
dma_pci_prd_ptr = prdBufPtr = prd_addr;
|
||||
prdBuf = (unsigned char*)prd_addr;
|
||||
|
||||
/* ... return the current number of PRD entries */
|
||||
dma_pci_num_prd = 0;
|
||||
|
||||
/* read the BM status reg and save the upper 3 bits */
|
||||
statReg = (unsigned char) ( pio_readBusMstrStatus() & 0x60 );
|
||||
|
||||
get_bus_master(Device::current())->set_prd((unsigned long)prd_addr,
|
||||
(unsigned long)ds_client.phys_addr());
|
||||
return 0;
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* \brief I/O back-end of the mindrvr driver
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2010-07-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* 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_IO_H_
|
||||
#define _ATA_IO_H_
|
||||
|
||||
#include <io_port_session/connection.h>
|
||||
|
||||
namespace Ata {
|
||||
|
||||
class Io_port : public Genode::Io_port_session
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Io_port_connection _io_cmd;
|
||||
Genode::Io_port_connection _io_ctrl;
|
||||
unsigned _base_cmd; /* command base */
|
||||
unsigned _base_ctrl; /* control base */
|
||||
|
||||
unsigned short translate_address(unsigned short address)
|
||||
{
|
||||
return address < 8 ? _base_cmd + address : _base_ctrl + 6;
|
||||
}
|
||||
|
||||
Genode::Io_port_connection * io(unsigned short address)
|
||||
{
|
||||
return (address < 8) ? &_io_cmd : &_io_ctrl;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Io_port(unsigned base, unsigned base_ctrl)
|
||||
: _io_cmd(base, 8), _io_ctrl(base_ctrl, 8),
|
||||
_base_cmd(base), _base_ctrl(base_ctrl) {}
|
||||
|
||||
unsigned char inb(unsigned short address)
|
||||
{
|
||||
return io(address)->inb(translate_address(address));
|
||||
}
|
||||
|
||||
unsigned short inw(unsigned short address)
|
||||
{
|
||||
return io(address)->inw(translate_address(address));
|
||||
}
|
||||
|
||||
unsigned inl(unsigned short address)
|
||||
{
|
||||
return io(address)->inl(translate_address(address));
|
||||
}
|
||||
|
||||
void outb(unsigned short address, unsigned char value)
|
||||
{
|
||||
io(address)->outb(translate_address(address), value);
|
||||
}
|
||||
|
||||
void outw(unsigned short address, unsigned short value)
|
||||
{
|
||||
io(address)->outw(translate_address(address), value);
|
||||
}
|
||||
|
||||
void outl(unsigned short address, unsigned value)
|
||||
{
|
||||
io(address)->outl(translate_address(address), value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _ATA_IO_H_ */
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* \brief Block interface for ATA driver
|
||||
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2010-07-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/config.h>
|
||||
#include <os/server.h>
|
||||
|
||||
/* local includes */
|
||||
#include "ata_device.h"
|
||||
#include "mindrvr.h"
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Ata;
|
||||
|
||||
struct Factory : Block::Driver_factory
|
||||
{
|
||||
Ata::Device *device;
|
||||
|
||||
Factory() : device(0)
|
||||
{
|
||||
/* determine if we probe for ATA or ATAPI */
|
||||
bool ata = false;
|
||||
try {
|
||||
ata = config()->xml_node().attribute("ata").has_value("yes");
|
||||
} catch (...) {}
|
||||
|
||||
int type = ata ? REG_CONFIG_TYPE_ATA : REG_CONFIG_TYPE_ATAPI;
|
||||
|
||||
/*
|
||||
* Probe for ATA(PI) device, but only once
|
||||
*/
|
||||
device = Ata::Device::probe_legacy(type);
|
||||
device->read_capacity();
|
||||
}
|
||||
|
||||
Block::Driver *create()
|
||||
{
|
||||
if (!device) {
|
||||
PERR("No device present");
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
if (Atapi_device *atapi_device = dynamic_cast<Atapi_device *>(device))
|
||||
if (!atapi_device->test_unit_ready()) {
|
||||
PERR("No disc present");
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void destroy(Block::Driver *driver) { }
|
||||
};
|
||||
|
||||
|
||||
struct Main
|
||||
{
|
||||
Server::Entrypoint &ep;
|
||||
struct Factory factory;
|
||||
Block::Root root;
|
||||
|
||||
Main(Server::Entrypoint &ep)
|
||||
: ep(ep), root(ep, Genode::env()->heap(), factory) {
|
||||
Genode::env()->parent()->announce(ep.manage(root)); }
|
||||
};
|
||||
|
||||
|
||||
/************
|
||||
** Server **
|
||||
************/
|
||||
|
||||
namespace Server {
|
||||
char const *name() { return "atapi_ep"; }
|
||||
size_t stack_size() { return 2*1024*sizeof(long); }
|
||||
void construct(Entrypoint &ep) { static Main server(ep); }
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* \brief I/0 interface used by MinATA driver
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \date 2010-07-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PIO_H_
|
||||
#define _PIO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
unsigned char pio_inbyte(unsigned char addr);
|
||||
unsigned long pio_indword(unsigned char addr);
|
||||
unsigned int pio_inword(unsigned char addr);
|
||||
|
||||
void pio_outbyte(int addr, unsigned char data);
|
||||
void pio_outword(int addr, unsigned int data);
|
||||
void pio_outdword(int addr, unsigned long data);
|
||||
|
||||
unsigned char pio_readBusMstrCmd(void);
|
||||
unsigned char pio_readBusMstrStatus(void);
|
||||
|
||||
void pio_writeBusMstrCmd(unsigned char x);
|
||||
void pio_writeBusMstrStatus(unsigned char x);
|
||||
void pio_writeBusMstrPrd(unsigned long x);
|
||||
|
||||
/* DEBUGGING */
|
||||
int printf(const char *formant, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* _PIO_H_ */
|
@ -1,9 +0,0 @@
|
||||
TARGET = atapi_drv
|
||||
REQUIRES = x86
|
||||
SRC_CC = main.cc ata_device.cc atapi_device.cc io.cc ata_bus_master.cc
|
||||
SRC_C = mindrvr.c
|
||||
LIBS = base config server
|
||||
|
||||
INC_DIR += $(PRG_DIR)/contrib $(PRG_DIR)
|
||||
|
||||
vpath %.c $(PRG_DIR)/contrib
|
@ -12,7 +12,6 @@ assert_spec nova
|
||||
set use_multiboot 1
|
||||
set use_genode_iso 0
|
||||
|
||||
set use_block_ide 0
|
||||
set use_block_sata 0
|
||||
|
||||
set use_nic_session 1
|
||||
|
@ -10,7 +10,6 @@
|
||||
set use_multiboot 0
|
||||
set use_genode_iso 0
|
||||
|
||||
set use_block_ide 0
|
||||
set use_block_sata 1
|
||||
|
||||
set use_nic_session 0
|
||||
@ -36,7 +35,6 @@ if {[have_include power_on/qemu]} {
|
||||
|
||||
append qemu_args " -m 1024 "
|
||||
append qemu_args " -cpu phenom"
|
||||
append_if $use_block_ide qemu_args " -boot d -hda bin/seoul-disc.raw "
|
||||
append_if $use_block_sata qemu_args " -drive id=disk,file=bin/seoul-disc.raw,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -boot d"
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
set use_multiboot 1
|
||||
set use_genode_iso 0
|
||||
|
||||
set use_block_ide 0
|
||||
set use_block_sata 0
|
||||
|
||||
set use_nic_session 1
|
||||
|
@ -11,7 +11,6 @@
|
||||
set use_multiboot 1
|
||||
set use_genode_iso 1
|
||||
|
||||
set use_block_ide 0
|
||||
set use_block_sata 0
|
||||
|
||||
set use_nic_session 1
|
||||
|
@ -17,7 +17,6 @@ if {[have_include power_on/qemu]} {
|
||||
set use_multiboot 1
|
||||
set use_genode_iso 0
|
||||
|
||||
set use_block_ide 0
|
||||
set use_block_sata 0
|
||||
|
||||
set use_nic_session 0
|
||||
|
@ -10,7 +10,6 @@
|
||||
set use_multiboot 1
|
||||
set use_genode_iso 0
|
||||
|
||||
set use_block_ide 0
|
||||
set use_block_sata 0
|
||||
|
||||
set use_nic_session 1
|
||||
|
@ -28,7 +28,6 @@ if {$use_fancy_stuff} { set use_framebuffer 1 }
|
||||
lappend_if [have_spec acpi] build_components drivers/acpi
|
||||
lappend_if [have_spec pci] build_components drivers/pci/device_pd
|
||||
lappend_if $use_usb build_components drivers/usb
|
||||
lappend_if $use_block_ide build_components drivers/atapi
|
||||
lappend_if $use_block_sata build_components drivers/ahci
|
||||
lappend_if $use_nic_session build_components drivers/nic
|
||||
lappend_if $use_nic_bridge build_components server/nic_bridge
|
||||
@ -171,13 +170,6 @@ append_if $use_block_sata config {
|
||||
<provides><service name="Block"/></provides>
|
||||
</start>}
|
||||
|
||||
append_if $use_block_ide config {
|
||||
<start name="atapi_drv" priority="-1">
|
||||
<resource name="RAM" quantum="1M" />
|
||||
<provides><service name="Block"/></provides>
|
||||
<config ata="yes" />
|
||||
</start>}
|
||||
|
||||
append_if $use_genode_iso config {
|
||||
<start name="rom_blk" priority="-1">
|
||||
<resource name="RAM" quantum="16M" />
|
||||
@ -427,7 +419,6 @@ lappend_if [have_spec acpi] boot_modules acpi_drv
|
||||
lappend_if [have_spec nova] boot_modules pci_device_pd
|
||||
lappend_if [expr !$use_usb] boot_modules ps2_drv
|
||||
lappend_if $use_usb boot_modules usb_drv
|
||||
lappend_if $use_block_ide boot_modules atapi_drv
|
||||
lappend_if $use_block_sata boot_modules ahci
|
||||
lappend_if $use_nic_session boot_modules nic_drv
|
||||
lappend_if $use_nic_bridge boot_modules nic_bridge
|
||||
|
Loading…
Reference in New Issue
Block a user