From 2002e1ccba42d9469598de17893edc73a498b3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Fri, 17 Apr 2015 15:56:21 +0200 Subject: [PATCH] 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. --- repos/libports/run/libc_block.run | 31 +- repos/libports/run/libc_ffat_fs.run | 12 +- repos/libports/run/libc_filesystem_test.inc | 41 - repos/libports/run/qt5_textedit.run | 11 +- repos/os/src/drivers/atapi/README | 24 - repos/os/src/drivers/atapi/ata_bus_master.cc | 140 - repos/os/src/drivers/atapi/ata_bus_master.h | 75 - repos/os/src/drivers/atapi/ata_device.cc | 317 -- repos/os/src/drivers/atapi/ata_device.h | 185 -- repos/os/src/drivers/atapi/atapi_device.cc | 155 - .../drivers/atapi/contrib/mindrvr-guide.txt | 387 --- repos/os/src/drivers/atapi/contrib/mindrvr.c | 2831 ----------------- repos/os/src/drivers/atapi/contrib/mindrvr.h | 450 --- repos/os/src/drivers/atapi/endian.h | 29 - repos/os/src/drivers/atapi/io.cc | 256 -- repos/os/src/drivers/atapi/io.h | 78 - repos/os/src/drivers/atapi/main.cc | 87 - repos/os/src/drivers/atapi/pio.h | 43 - repos/os/src/drivers/atapi/target.mk | 9 - repos/ports/run/seoul-auto.run | 1 - repos/ports/run/seoul-disc.run | 2 - repos/ports/run/seoul-fancy.run | 1 - repos/ports/run/seoul-genode.run | 1 - repos/ports/run/seoul-kernelbuild.run | 1 - repos/ports/run/seoul-net.run | 1 - repos/ports/run/seoul.inc | 9 - 26 files changed, 18 insertions(+), 5159 deletions(-) delete mode 100644 repos/os/src/drivers/atapi/README delete mode 100644 repos/os/src/drivers/atapi/ata_bus_master.cc delete mode 100644 repos/os/src/drivers/atapi/ata_bus_master.h delete mode 100644 repos/os/src/drivers/atapi/ata_device.cc delete mode 100644 repos/os/src/drivers/atapi/ata_device.h delete mode 100644 repos/os/src/drivers/atapi/atapi_device.cc delete mode 100644 repos/os/src/drivers/atapi/contrib/mindrvr-guide.txt delete mode 100644 repos/os/src/drivers/atapi/contrib/mindrvr.c delete mode 100644 repos/os/src/drivers/atapi/contrib/mindrvr.h delete mode 100644 repos/os/src/drivers/atapi/endian.h delete mode 100644 repos/os/src/drivers/atapi/io.cc delete mode 100644 repos/os/src/drivers/atapi/io.h delete mode 100644 repos/os/src/drivers/atapi/main.cc delete mode 100644 repos/os/src/drivers/atapi/pio.h delete mode 100644 repos/os/src/drivers/atapi/target.mk diff --git a/repos/libports/run/libc_block.run b/repos/libports/run/libc_block.run index b7e860170..65b857289 100644 --- a/repos/libports/run/libc_block.run +++ b/repos/libports/run/libc_block.run @@ -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 { } -append_if $use_atapi_drv config { - +append_if $use_ahci_drv config { + @@ -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 diff --git a/repos/libports/run/libc_ffat_fs.run b/repos/libports/run/libc_ffat_fs.run index fd31f7019..ad05cd9eb 100644 --- a/repos/libports/run/libc_ffat_fs.run +++ b/repos/libports/run/libc_ffat_fs.run @@ -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 { } -append_if $use_atapi_drv config { - +append_if $use_ahci_drv config { + @@ -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 diff --git a/repos/libports/run/libc_filesystem_test.inc b/repos/libports/run/libc_filesystem_test.inc index e9e1ede5b..a75f44673 100644 --- a/repos/libports/run/libc_filesystem_test.inc +++ b/repos/libports/run/libc_filesystem_test.inc @@ -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 { } -append_if $use_atapi_drv config { - - - - - -} - append_if $use_ahci config { @@ -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 " diff --git a/repos/libports/run/qt5_textedit.run b/repos/libports/run/qt5_textedit.run index 1b6bc6e7f..f3249918c 100644 --- a/repos/libports/run/qt5_textedit.run +++ b/repos/libports/run/qt5_textedit.run @@ -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 { - +append_if $use_ahci_driver config { + @@ -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" diff --git a/repos/os/src/drivers/atapi/README b/repos/os/src/drivers/atapi/README deleted file mode 100644 index d29183988..000000000 --- a/repos/os/src/drivers/atapi/README +++ /dev/null @@ -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: - -! -! -! -! - -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'. diff --git a/repos/os/src/drivers/atapi/ata_bus_master.cc b/repos/os/src/drivers/atapi/ata_bus_master.cc deleted file mode 100644 index 5ef201b9d..000000000 --- a/repos/os/src/drivers/atapi/ata_bus_master.cc +++ /dev/null @@ -1,140 +0,0 @@ -/* - * \brief I/O interface to the IDE bus master - * \author Sebastian Sumpf - * \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 -#include -#include -#include - -/* 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); - } -} diff --git a/repos/os/src/drivers/atapi/ata_bus_master.h b/repos/os/src/drivers/atapi/ata_bus_master.h deleted file mode 100644 index b415a9900..000000000 --- a/repos/os/src/drivers/atapi/ata_bus_master.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * \brief I/O interface to the IDE bus master - * \author Sebastian Sumpf - * \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_ */ diff --git a/repos/os/src/drivers/atapi/ata_device.cc b/repos/os/src/drivers/atapi/ata_device.cc deleted file mode 100644 index 99830e6d3..000000000 --- a/repos/os/src/drivers/atapi/ata_device.cc +++ /dev/null @@ -1,317 +0,0 @@ -/* - * \brief ATA device class - * \author Sebastian.Sump - * \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 -#include -#include - -/* 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(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; -} diff --git a/repos/os/src/drivers/atapi/ata_device.h b/repos/os/src/drivers/atapi/ata_device.h deleted file mode 100644 index 1e48a9be0..000000000 --- a/repos/os/src/drivers/atapi/ata_device.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * \brief ATA device class - * \author Sebastian.Sump - * \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 -#include -#include - -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 diff --git a/repos/os/src/drivers/atapi/atapi_device.cc b/repos/os/src/drivers/atapi/atapi_device.cc deleted file mode 100644 index 223555678..000000000 --- a/repos/os/src/drivers/atapi/atapi_device.cc +++ /dev/null @@ -1,155 +0,0 @@ -/* - * \brief ATAPI specific implementation of an Ata::Device - * \author Sebastian.Sumpf - * \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 -#include -#include - -/* 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; -} diff --git a/repos/os/src/drivers/atapi/contrib/mindrvr-guide.txt b/repos/os/src/drivers/atapi/contrib/mindrvr-guide.txt deleted file mode 100644 index c3e7839ed..000000000 --- a/repos/os/src/drivers/atapi/contrib/mindrvr-guide.txt +++ /dev/null @@ -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/ diff --git a/repos/os/src/drivers/atapi/contrib/mindrvr.c b/repos/os/src/drivers/atapi/contrib/mindrvr.c deleted file mode 100644 index b816925f3..000000000 --- a/repos/os/src/drivers/atapi/contrib/mindrvr.c +++ /dev/null @@ -1,2831 +0,0 @@ -//******************************************************************** -// MINIMUM ATA LOW LEVEL I/O DRIVER -- MINDRVR.C -// -// 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. -//******************************************************************** - -#include "mindrvr.h" -#include "pio.h" -//************************************************************** -// -// !!! data that functions outside of MINDRVR must use -// -// Note that there is no actual "interrupt handler" provide in -// MINDRVR. The interrupt handler is usually a small function that -// is very system specific. However, MINDRVR expects that interrupt -// handler function to provide some status data at the time the -// interrupt handler is executed. -// -// In many systems, including PCI bus based systems, when an -// interrupt is received from an ATA controller, the interrupt -// handler must acknowledge the interrupt by reading both the -// ATA/ATAPI device Status register and the controller status -// register. This status must be stored here so that MINDRVR -// can use it. -// -//************************************************************** - -unsigned char int_ata_status; // ATA status read by interrupt handler - -unsigned char int_bmide_status; // BMIDE status read by interrupt handler - -unsigned char int_use_intr_flag = INT_DEFAULT_INTERRUPT_MODE; - -struct REG_CMD_INFO reg_cmd_info; - -int reg_config_info[2]; - -unsigned char * pio_bmide_base_addr; - -unsigned char * pio_reg_addrs[9] = -{ - PIO_BASE_ADDR1 + 0, // [0] CB_DATA - PIO_BASE_ADDR1 + 1, // [1] CB_FR & CB_ER - PIO_BASE_ADDR1 + 2, // [2] CB_SC - PIO_BASE_ADDR1 + 3, // [3] CB_SN - PIO_BASE_ADDR1 + 4, // [4] CB_CL - PIO_BASE_ADDR1 + 5, // [5] CB_CH - PIO_BASE_ADDR1 + 6, // [6] CB_DH - PIO_BASE_ADDR1 + 7, // [7] CB_CMD & CB_STAT - PIO_BASE_ADDR2 + 0 // [8] CB_DC & CB_ASTAT -} ; - -unsigned char pio_xfer_width = PIO_DEFAULT_XFER_WIDTH; - -//************************************************************** -// -// functions internal and private to MINDRVR -// -//************************************************************** - -static void sub_setup_command( void ); -static void sub_trace_command( void ); -static int sub_select( unsigned char dev ); -static void sub_wait_poll( unsigned char we, unsigned char pe ); - -//static unsigned char pio_inbyte( unsigned char addr ); -//static void pio_outbyte( int addr, unsigned char data ); -//static unsigned int pio_inword( unsigned char addr ); -//static void pio_outword( int addr, unsigned int data ); -//static unsigned long pio_indword( unsigned char addr ); -//static void pio_outdword( int addr, unsigned long data ); -static void pio_drq_block_in( unsigned char addrDataReg, - unsigned char * bufAddr, - long wordCnt ); -static void pio_drq_block_out( unsigned char addrDataReg, - unsigned char * bufAddr, - long wordCnt ); -static void pio_rep_inbyte( unsigned char addrDataReg, - unsigned char * bufAddr, - long byteCnt ); -static void pio_rep_outbyte( unsigned char addrDataReg, - unsigned char * bufAddr, - long byteCnt ); -static void pio_rep_inword( unsigned char addrDataReg, - unsigned char * bufAddr, - long wordCnt ); -static void pio_rep_outword( unsigned char addrDataReg, - unsigned char * bufAddr, - long wordCnt ); -static void pio_rep_indword( unsigned char addrDataReg, - unsigned char * bufAddr, - long dwordCnt ); -static void pio_rep_outdword( unsigned char addrDataReg, - unsigned char * bufAddr, - long dwordCnt ); -/* -static unsigned char pio_readBusMstrCmd( void ); -static unsigned char pio_readBusMstrStatus( void ); -static void pio_writeBusMstrCmd( unsigned char x ); -static void pio_writeBusMstrStatus( unsigned char x ); -*/ - -static long tmr_cmd_start_time; // command start time -static void tmr_set_timeout( void ); -static int tmr_chk_timeout( void ); - -// This macro provides a small delay that is used in several -// places in the ATA command protocols: - -#define DELAY400NS { pio_inbyte( CB_ASTAT ); pio_inbyte( CB_ASTAT ); \ - pio_inbyte( CB_ASTAT ); pio_inbyte( CB_ASTAT ); } - -//************************************************************* -// -// reg_config() - Check the host adapter and determine the -// number and type of drives attached. -// -// This process is not documented by any of the ATA standards. -// -// Infomation is returned by this function is in -// reg_config_info[] -- see MINDRVR.H. -// -//************************************************************* - -int reg_config( void ) - -{ - int numDev = 0; - unsigned char sc; - unsigned char sn; - unsigned char cl; - unsigned char ch; - unsigned char st; - unsigned char dc; - - // setup register values - - dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - - // reset Bus Master Error bit - - pio_writeBusMstrStatus( BM_SR_MASK_ERR ); - - // assume there are no devices - - reg_config_info[0] = REG_CONFIG_TYPE_NONE; - reg_config_info[1] = REG_CONFIG_TYPE_NONE; - - // set up Device Control register - - pio_outbyte( CB_DC, dc ); - - // lets see if there is a device 0 - - pio_outbyte( CB_DH, CB_DH_DEV0 ); - DELAY400NS; - pio_outbyte( CB_SC, 0x55 ); - pio_outbyte( CB_SN, 0xaa ); - pio_outbyte( CB_SC, 0xaa ); - pio_outbyte( CB_SN, 0x55 ); - pio_outbyte( CB_SC, 0x55 ); - pio_outbyte( CB_SN, 0xaa ); - sc = pio_inbyte( CB_SC ); - sn = pio_inbyte( CB_SN ); - if ( ( sc == 0x55 ) && ( sn == 0xaa ) ) - reg_config_info[0] = REG_CONFIG_TYPE_UNKN; - - // lets see if there is a device 1 - - pio_outbyte( CB_DH, CB_DH_DEV1 ); - DELAY400NS; - pio_outbyte( CB_SC, 0x55 ); - pio_outbyte( CB_SN, 0xaa ); - pio_outbyte( CB_SC, 0xaa ); - pio_outbyte( CB_SN, 0x55 ); - pio_outbyte( CB_SC, 0x55 ); - pio_outbyte( CB_SN, 0xaa ); - sc = pio_inbyte( CB_SC ); - sn = pio_inbyte( CB_SN ); - if ( ( sc == 0x55 ) && ( sn == 0xaa ) ) - reg_config_info[1] = REG_CONFIG_TYPE_UNKN; - - // now we think we know which devices, if any are there, - // so lets try a soft reset (ignoring any errors). - - pio_outbyte( CB_DH, CB_DH_DEV0 ); - DELAY400NS; - reg_reset( 0 ); - - // lets check device 0 again, is device 0 really there? - // is it ATA or ATAPI? - - pio_outbyte( CB_DH, CB_DH_DEV0 ); - DELAY400NS; - sc = pio_inbyte( CB_SC ); - sn = pio_inbyte( CB_SN ); - if ( ( sc == 0x01 ) && ( sn == 0x01 ) ) - { - reg_config_info[0] = REG_CONFIG_TYPE_UNKN; - st = pio_inbyte( CB_STAT ); - cl = pio_inbyte( CB_CL ); - ch = pio_inbyte( CB_CH ); - if ( ( ( cl == 0x14 ) && ( ch == 0xeb ) ) // PATAPI - || - ( ( cl == 0x69 ) && ( ch == 0x96 ) ) // SATAPI - ) - { - reg_config_info[0] = REG_CONFIG_TYPE_ATAPI; - } - else - if ( ( st != 0 ) - && - ( ( ( cl == 0x00 ) && ( ch == 0x00 ) ) // PATA - || - ( ( cl == 0x3c ) && ( ch == 0xc3 ) ) ) // SATA - ) - { - reg_config_info[0] = REG_CONFIG_TYPE_ATA; - } - } - - // lets check device 1 again, is device 1 really there? - // is it ATA or ATAPI? - - pio_outbyte( CB_DH, CB_DH_DEV1 ); - DELAY400NS; - sc = pio_inbyte( CB_SC ); - sn = pio_inbyte( CB_SN ); - if ( ( sc == 0x01 ) && ( sn == 0x01 ) ) - { - reg_config_info[1] = REG_CONFIG_TYPE_UNKN; - st = pio_inbyte( CB_STAT ); - cl = pio_inbyte( CB_CL ); - ch = pio_inbyte( CB_CH ); - if ( ( ( cl == 0x14 ) && ( ch == 0xeb ) ) // PATAPI - || - ( ( cl == 0x69 ) && ( ch == 0x96 ) ) // SATAPI - ) - { - reg_config_info[1] = REG_CONFIG_TYPE_ATAPI; - } - else - if ( ( st != 0 ) - && - ( ( ( cl == 0x00 ) && ( ch == 0x00 ) ) // PATA - || - ( ( cl == 0x3c ) && ( ch == 0xc3 ) ) ) // SATA - ) - { - reg_config_info[1] = REG_CONFIG_TYPE_ATA; - } - } - - // If possible, select a device that exists, try device 0 first. - - if ( reg_config_info[1] != REG_CONFIG_TYPE_NONE ) - { - pio_outbyte( CB_DH, CB_DH_DEV1 ); - DELAY400NS; - numDev ++ ; - } - if ( reg_config_info[0] != REG_CONFIG_TYPE_NONE ) - { - pio_outbyte( CB_DH, CB_DH_DEV0 ); - DELAY400NS; - numDev ++ ; - } - - // BMIDE Error=1? - - if ( pio_readBusMstrStatus() & BM_SR_MASK_ERR ) - { - reg_cmd_info.ec = 78; // yes - } - - // return the number of devices found - - return numDev; -} - -//************************************************************* -// -// reg_reset() - Execute a Software Reset. -// -// See ATA-2 Section 9.2, ATA-3 Section 9.2, ATA-4 Section 8.3. -// -//************************************************************* - -int reg_reset( unsigned char devRtrn ) - -{ - unsigned char sc; - unsigned char sn; - unsigned char status; - unsigned char dc; - - // setup register values - - dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - - // reset Bus Master Error bit - - pio_writeBusMstrStatus( BM_SR_MASK_ERR ); - - // initialize the command timeout counter - - tmr_set_timeout(); - - // Set and then reset the soft reset bit in the Device Control - // register. This causes device 0 be selected. - - pio_outbyte( CB_DC, (unsigned char) ( dc | CB_DC_SRST ) ); - DELAY400NS; - pio_outbyte( CB_DC, dc ); - DELAY400NS; - - // If there is a device 0, wait for device 0 to set BSY=0. - - if ( reg_config_info[0] != REG_CONFIG_TYPE_NONE ) - { - while ( 1 ) - { - status = pio_inbyte( CB_STAT ); - if ( ( status & CB_STAT_BSY ) == 0 ) - break; - if ( tmr_chk_timeout() ) - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 1; - break; - } - } - } - - // If there is a device 1, wait until device 1 allows - // register access. - - if ( reg_config_info[1] != REG_CONFIG_TYPE_NONE ) - { - while ( 1 ) - { - pio_outbyte( CB_DH, CB_DH_DEV1 ); - DELAY400NS; - sc = pio_inbyte( CB_SC ); - sn = pio_inbyte( CB_SN ); - if ( ( sc == 0x01 ) && ( sn == 0x01 ) ) - break; - if ( tmr_chk_timeout() ) - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 2; - break; - } - } - - // Now check if drive 1 set BSY=0. - - if ( reg_cmd_info.ec == 0 ) - { - if ( pio_inbyte( CB_STAT ) & CB_STAT_BSY ) - { - reg_cmd_info.ec = 3; - } - } - } - - // RESET_DONE: - - // We are done but now we must select the device the caller - // requested. This will cause - // the correct data to be returned in reg_cmd_info. - - pio_outbyte( CB_DH, (unsigned char) ( devRtrn ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - DELAY400NS; - - // If possible, select a device that exists, - // try device 0 first. - - if ( reg_config_info[1] != REG_CONFIG_TYPE_NONE ) - { - pio_outbyte( CB_DH, CB_DH_DEV1 ); - DELAY400NS; - } - if ( reg_config_info[0] != REG_CONFIG_TYPE_NONE ) - { - pio_outbyte( CB_DH, CB_DH_DEV0 ); - DELAY400NS; - } - - // BMIDE Error=1? - - if ( pio_readBusMstrStatus() & BM_SR_MASK_ERR ) - { - reg_cmd_info.ec = 78; // yes - } - - // All done. The return values of this function are described in - // MINDRVR.H. - - sub_trace_command(); - if ( reg_cmd_info.ec ) - return 1; - return 0; -} - -//************************************************************* -// -// exec_non_data_cmd() - Execute a non-data command. -// -// This includes the strange ATAPI DEVICE RESET 'command' -// (command code 08H). -// -// Note special handling for Execute Device Diagnostics -// command when there is no device 0. -// -// See ATA-2 Section 9.5, ATA-3 Section 9.5, -// ATA-4 Section 8.8 Figure 12. Also see Section 8.5. -// -//************************************************************* - -static int exec_non_data_cmd( unsigned char dev ); - -static int exec_non_data_cmd( unsigned char dev ) - -{ - unsigned char secCnt; - unsigned char secNum; - unsigned char status; - int polled = 0; - - // reset Bus Master Error bit - - pio_writeBusMstrStatus( BM_SR_MASK_ERR ); - - // Set command time out. - - tmr_set_timeout(); - - // PAY ATTENTION HERE - // If the caller is attempting a Device Reset command, then - // don't do most of the normal stuff. Device Reset has no - // parameters, should not generate an interrupt and it is the - // only command that can be written to the Command register - // when a device has BSY=1 (a very strange command!). Not - // all devices support this command (even some ATAPI devices - // don't support the command. - - if ( reg_cmd_info.cmd != CMD_DEVICE_RESET ) - { - // Select the drive - call the sub_select function. - // Quit now if this fails. - - if ( sub_select( dev ) ) - { - return 1; - } - - // Set up all the registers except the command register. - - sub_setup_command(); - } - - // Start the command by setting the Command register. The drive - // should immediately set BUSY status. - - pio_outbyte( CB_CMD, reg_cmd_info.cmd ); - - // Waste some time by reading the alternate status a few times. - // This gives the drive time to set BUSY in the status register on - // really fast systems. If we don't do this, a slow drive on a fast - // system may not set BUSY fast enough and we would think it had - // completed the command when it really had not even started the - // command yet. - - DELAY400NS; - - // IF - // This is an Exec Dev Diag command (cmd=0x90) - // and there is no device 0 then - // there will be no interrupt. So we must - // poll device 1 until it allows register - // access and then do normal polling of the Status - // register for BSY=0. - // ELSE - // IF - // This is a Dev Reset command (cmd=0x08) then - // there should be no interrupt. So we must - // poll for BSY=0. - // ELSE - // Do the normal wait for interrupt or polling for - // completion. - - if ( ( reg_cmd_info.cmd == CMD_EXECUTE_DEVICE_DIAGNOSTIC ) - && - ( reg_config_info[0] == REG_CONFIG_TYPE_NONE ) - ) - { - polled = 1; - while ( 1 ) - { - pio_outbyte( CB_DH, CB_DH_DEV1 ); - DELAY400NS; - secCnt = pio_inbyte( CB_SC ); - secNum = pio_inbyte( CB_SN ); - if ( ( secCnt == 0x01 ) && ( secNum == 0x01 ) ) - break; - if ( tmr_chk_timeout() ) - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 24; - break; - } - } - } - else - { - if ( reg_cmd_info.cmd == CMD_DEVICE_RESET ) - { - // Wait for not BUSY -or- wait for time out. - - polled = 1; - sub_wait_poll( 0, 23 ); - } - else - { - // Wait for interrupt -or- wait for not BUSY -or- wait for time out. - - if ( ! int_use_intr_flag ) - polled = 1; - sub_wait_poll( 22, 23 ); - } - } - - // If status was polled or if any error read the status register, - // otherwise get the status that was read by the interrupt handler. - - if ( ( polled ) || ( reg_cmd_info.ec ) ) - status = pio_inbyte( CB_STAT ); - else - status = int_ata_status; - - // Error if BUSY, DEVICE FAULT, DRQ or ERROR status now. - - if ( reg_cmd_info.ec == 0 ) - { - if ( status & ( CB_STAT_BSY | CB_STAT_DF | CB_STAT_DRQ | CB_STAT_ERR ) ) - { - reg_cmd_info.ec = 21; - } - } - - // BMIDE Error=1? - - if ( pio_readBusMstrStatus() & BM_SR_MASK_ERR ) - { - reg_cmd_info.ec = 78; // yes - } - - // NON_DATA_DONE: - - // All done. The return values of this function are described in - // MINDRVR.H. - - sub_trace_command(); - if ( reg_cmd_info.ec ) - return 1; - return 0; -} - -//************************************************************* -// -// reg_non_data_lba28() - Easy way to execute a non-data command -// using an LBA sector address. -// -//************************************************************* - -int reg_non_data_lba28( unsigned char dev, unsigned char cmd, - unsigned int fr, unsigned int sc, - unsigned long lba ) - -{ - - // Setup current command information. - - reg_cmd_info.cmd = cmd; - reg_cmd_info.fr = fr; - reg_cmd_info.sc = sc; - reg_cmd_info.dh = (unsigned char) ( CB_DH_LBA | ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - reg_cmd_info.dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - reg_cmd_info.ns = sc; - reg_cmd_info.lbaSize = LBA28; - reg_cmd_info.lbaHigh = 0L; - reg_cmd_info.lbaLow = lba; - - // Execute the command. - - return exec_non_data_cmd( dev ); -} - -//************************************************************* -// -// reg_non_data_lba48() - Easy way to execute a non-data command -// using an LBA sector address. -// -//************************************************************* - -int reg_non_data_lba48( unsigned char dev, unsigned char cmd, - unsigned int fr, unsigned int sc, - unsigned long lbahi, unsigned long lbalo ) - -{ - - // Setup current command infomation. - - reg_cmd_info.cmd = cmd; - reg_cmd_info.fr = fr; - reg_cmd_info.sc = sc; - reg_cmd_info.dh = (unsigned char) ( CB_DH_LBA | ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - reg_cmd_info.dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - reg_cmd_info.ns = sc; - reg_cmd_info.lbaSize = LBA48; - reg_cmd_info.lbaHigh = lbahi; - reg_cmd_info.lbaLow = lbalo; - - // Execute the command. - - return exec_non_data_cmd( dev ); -} - -//************************************************************* -// -// exec_pio_data_in_cmd() - Execute a PIO Data In command. -// -// See ATA-2 Section 9.3, ATA-3 Section 9.3, -// ATA-4 Section 8.6 Figure 10. -// -//************************************************************* - -static int exec_pio_data_in_cmd( unsigned char dev, - unsigned char * bufAddr, - long numSect, int multiCnt ); - - -static int exec_pio_data_in_cmd( unsigned char dev, - unsigned char * bufAddr, - long numSect, int multiCnt ) - -{ - unsigned char status; - long wordCnt; - - // reset Bus Master Error bit - - pio_writeBusMstrStatus( BM_SR_MASK_ERR ); - - // Set command time out. - - tmr_set_timeout(); - - // Select the drive - call the sub_select function. - // Quit now if this fails. - - if ( sub_select( dev ) ) - { - return 1; - } - - // Set up all the registers except the command register. - - sub_setup_command(); - - // Start the command by setting the Command register. The drive - // should immediately set BUSY status. - - pio_outbyte( CB_CMD, reg_cmd_info.cmd ); - - // Waste some time by reading the alternate status a few times. - // This gives the drive time to set BUSY in the status register on - // really fast systems. If we don't do this, a slow drive on a fast - // system may not set BUSY fast enough and we would think it had - // completed the command when it really had not even started the - // command yet. - - DELAY400NS; - - // Loop to read each sector. - - while ( 1 ) - { - // READ_LOOP: - // - // NOTE NOTE NOTE ... The primary status register (1f7) MUST NOT be - // read more than ONCE for each sector transferred! When the - // primary status register is read, the drive resets IRQ. The - // alternate status register (3f6) can be read any number of times. - // After interrupt read the the primary status register ONCE - // and transfer the 256 words (REP INSW). AS SOON as BOTH the - // primary status register has been read AND the last of the 256 - // words has been read, the drive is allowed to generate the next - // IRQ (newer and faster drives could generate the next IRQ in - // 50 microseconds or less). If the primary status register is read - // more than once, there is the possibility of a race between the - // drive and the software and the next IRQ could be reset before - // the system interrupt controller sees it. - - // Wait for interrupt -or- wait for not BUSY -or- wait for time out. - - sub_wait_poll( 34, 35 ); - - // If polling or error read the status, otherwise - // get the status that was read by the interrupt handler. - - if ( ( ! int_use_intr_flag ) || ( reg_cmd_info.ec ) ) - status = pio_inbyte( CB_STAT ); - else - status = int_ata_status; - - // If there was a time out error, go to READ_DONE. - - if ( reg_cmd_info.ec ) - break; // go to READ_DONE - - // If BSY=0 and DRQ=1, transfer the data, - // even if we find out there is an error later. - - if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == CB_STAT_DRQ ) - { - - // increment number of DRQ packets - - reg_cmd_info.drqPackets ++ ; - - // determine the number of sectors to transfer - - wordCnt = multiCnt ? multiCnt : 1; - if ( wordCnt > numSect ) - wordCnt = numSect; - wordCnt = wordCnt * 256; - - // Do the REP INSW to read the data for one DRQ block. - - reg_cmd_info.totalBytesXfer += ( wordCnt << 1 ); - pio_drq_block_in( CB_DATA, bufAddr, wordCnt ); - - DELAY400NS; // delay so device can get the status updated - - // Note: The drive should have dropped DATA REQUEST by now. If there - // are more sectors to transfer, BUSY should be active now (unless - // there is an error). - - // Decrement the count of sectors to be transferred - // and increment buffer address. - - numSect = numSect - ( multiCnt ? multiCnt : 1 ); - bufAddr = bufAddr + ( 512 * ( multiCnt ? multiCnt : 1 ) ); - } - - // So was there any error condition? - - if ( status & ( CB_STAT_BSY | CB_STAT_DF | CB_STAT_ERR ) ) - { - reg_cmd_info.ec = 31; - break; // go to READ_DONE - } - - // DRQ should have been set -- was it? - - if ( ( status & CB_STAT_DRQ ) == 0 ) - { - reg_cmd_info.ec = 32; - break; // go to READ_DONE - } - - // If all of the requested sectors have been transferred, make a - // few more checks before we exit. - - if ( numSect < 1 ) - { - // Since the drive has transferred all of the requested sectors - // without error, the drive should not have BUSY, DEVICE FAULT, - // DATA REQUEST or ERROR active now. - do { - status = pio_inbyte( CB_STAT ); - } - while (status & CB_STAT_BSY); - - if ( status & ( CB_STAT_BSY | CB_STAT_DF | CB_STAT_DRQ | CB_STAT_ERR ) ) - { - reg_cmd_info.ec = 33; - break; // go to READ_DONE - } - - // All sectors have been read without error, go to READ_DONE. - - break; // go to READ_DONE - - } - - // This is the end of the read loop. If we get here, the loop is - // repeated to read the next sector. Go back to READ_LOOP. - - } - - // BMIDE Error=1? - - if ( pio_readBusMstrStatus() & BM_SR_MASK_ERR ) - { - reg_cmd_info.ec = 78; // yes - } - - // READ_DONE: - - // All done. The return values of this function are described in - // MINDRVR.H. - - if ( reg_cmd_info.ec ) - return 1; - return 0; -} - -//************************************************************* -// -// reg_pio_data_in_lba28() - Easy way to execute a PIO Data In command -// using an LBA sector address. -// -//************************************************************* - -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 ) - -{ - - reg_cmd_info.cmd = cmd; - reg_cmd_info.fr = fr; - reg_cmd_info.sc = sc; - reg_cmd_info.dh = (unsigned char) ( CB_DH_LBA | ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - reg_cmd_info.dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - reg_cmd_info.lbaSize = LBA28; - reg_cmd_info.lbaHigh = 0L; - reg_cmd_info.lbaLow = lba; - // these commands transfer only 1 sector - if ( ( cmd == CMD_IDENTIFY_DEVICE ) - || ( cmd == CMD_IDENTIFY_DEVICE_PACKET ) - ) - numSect = 1; - - // adjust multiple count - if ( multiCnt & 0x0800 ) - { - // assume caller knows what they are doing - multiCnt &= 0x00ff; - } - else - { - // only Read Multiple uses multiCnt - if ( cmd != CMD_READ_MULTIPLE ) - multiCnt = 1; - } - - reg_cmd_info.ns = numSect; - reg_cmd_info.mc = multiCnt; - - return exec_pio_data_in_cmd( dev, bufAddr, numSect, multiCnt ); -} - -//************************************************************* -// -// reg_pio_data_in_lba48() - Easy way to execute a PIO Data In command -// using an LBA sector address. -// -//************************************************************* - -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 ) - -{ - - reg_cmd_info.cmd = cmd; - reg_cmd_info.fr = fr; - reg_cmd_info.sc = sc; - reg_cmd_info.dh = (unsigned char) ( CB_DH_LBA | ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - reg_cmd_info.dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - reg_cmd_info.lbaSize = LBA48; - reg_cmd_info.lbaHigh = lbahi; - reg_cmd_info.lbaLow = lbalo; - - // adjust multiple count - if ( multiCnt & 0x0800 ) - { - // assume caller knows what they are doing - multiCnt &= 0x00ff; - } - else - { - // only Read Multiple Ext uses multiCnt - if ( cmd != CMD_READ_MULTIPLE_EXT ) - multiCnt = 1; - } - - reg_cmd_info.ns = numSect; - reg_cmd_info.mc = multiCnt; - - return exec_pio_data_in_cmd( dev, bufAddr, numSect, multiCnt ); -} - -//************************************************************* -// -// exec_pio_data_out_cmd() - Execute a PIO Data Out command. -// -// See ATA-2 Section 9.4, ATA-3 Section 9.4, -// ATA-4 Section 8.7 Figure 11. -// -//************************************************************* - -static int exec_pio_data_out_cmd( unsigned char dev, - unsigned char * bufAddr, - long numSect, int multiCnt ); - -static int exec_pio_data_out_cmd( unsigned char dev, - unsigned char * bufAddr, - long numSect, int multiCnt ) - -{ - unsigned char status; - int loopFlag = 1; - long wordCnt; - - // reset Bus Master Error bit - - pio_writeBusMstrStatus( BM_SR_MASK_ERR ); - - // Set command time out. - - tmr_set_timeout(); - - // Select the drive - call the sub_select function. - // Quit now if this fails. - - if ( sub_select( dev ) ) - { - return 1; - } - - // Set up all the registers except the command register. - - sub_setup_command(); - - // Start the command by setting the Command register. The drive - // should immediately set BUSY status. - - pio_outbyte( CB_CMD, reg_cmd_info.cmd ); - - // Waste some time by reading the alternate status a few times. - // This gives the drive time to set BUSY in the status register on - // really fast systems. If we don't do this, a slow drive on a fast - // system may not set BUSY fast enough and we would think it had - // completed the command when it really had not even started the - // command yet. - - DELAY400NS; - - // Wait for not BUSY or time out. - // Note: No interrupt is generated for the - // first sector of a write command. - - while ( 1 ) - { - status = pio_inbyte( CB_ASTAT ); - if ( ( status & CB_STAT_BSY ) == 0 ) - break; - if ( tmr_chk_timeout() ) - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 47; - loopFlag = 0; - break; - } - } - - // This loop writes each sector. - - while ( loopFlag ) - { - // WRITE_LOOP: - // - // NOTE NOTE NOTE ... The primary status register (1f7) MUST NOT be - // read more than ONCE for each sector transferred! When the - // primary status register is read, the drive resets IRQ. The - // alternate status register (3f6) can be read any number of times. - // For correct results, transfer the 256 words (REP OUTSW), wait for - // interrupt and then read the primary status register. AS - // SOON as BOTH the primary status register has been read AND the - // last of the 256 words has been written, the drive is allowed to - // generate the next IRQ (newer and faster drives could generate - // the next IRQ in 50 microseconds or less). If the primary - // status register is read more than once, there is the possibility - // of a race between the drive and the software and the next IRQ - // could be reset before the system interrupt controller sees it. - - // If BSY=0 and DRQ=1, transfer the data, - // even if we find out there is an error later. - - if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == CB_STAT_DRQ ) - { - - // increment number of DRQ packets - - reg_cmd_info.drqPackets ++ ; - - // determine the number of sectors to transfer - - wordCnt = multiCnt ? multiCnt : 1; - if ( wordCnt > numSect ) - wordCnt = numSect; - wordCnt = wordCnt * 256; - - // Do the REP OUTSW to write the data for one DRQ block. - - reg_cmd_info.totalBytesXfer += ( wordCnt << 1 ); - pio_drq_block_out( CB_DATA, bufAddr, wordCnt ); - - DELAY400NS; // delay so device can get the status updated - - // Note: The drive should have dropped DATA REQUEST and - // raised BUSY by now. - - // Decrement the count of sectors to be transferred - // and increment buffer address. - - numSect = numSect - ( multiCnt ? multiCnt : 1 ); - bufAddr = bufAddr + ( 512 * ( multiCnt ? multiCnt : 1 ) ); - } - - // So was there any error condition? - - if ( status & ( CB_STAT_BSY | CB_STAT_DF | CB_STAT_ERR ) ) - { - reg_cmd_info.ec = 41; - break; // go to WRITE_DONE - } - - // DRQ should have been set -- was it? - - if ( ( status & CB_STAT_DRQ ) == 0 ) - { - reg_cmd_info.ec = 42; - break; // go to WRITE_DONE - } - - // Wait for interrupt -or- wait for not BUSY -or- wait for time out. - - sub_wait_poll( 44, 45 ); - - // If polling or error read the status, otherwise - // get the status that was read by the interrupt handler. - - if ( ( ! int_use_intr_flag ) || ( reg_cmd_info.ec ) ) - status = pio_inbyte( CB_STAT ); - else - status = int_ata_status; - - // If there was a time out error, go to WRITE_DONE. - - if ( reg_cmd_info.ec ) - break; // go to WRITE_DONE - - // If all of the requested sectors have been transferred, make a - // few more checks before we exit. - - if ( numSect < 1 ) - { - // Since the drive has transferred all of the sectors without - // error, the drive MUST not have BUSY, DEVICE FAULT, DATA REQUEST - // or ERROR status at this time. - - if ( status & ( CB_STAT_BSY | CB_STAT_DF | CB_STAT_DRQ | CB_STAT_ERR ) ) - { - reg_cmd_info.ec = 43; - break; // go to WRITE_DONE - } - - // All sectors have been written without error, go to WRITE_DONE. - - break; // go to WRITE_DONE - - } - - // - // This is the end of the write loop. If we get here, the loop - // is repeated to write the next sector. Go back to WRITE_LOOP. - - } - - // BMIDE Error=1? - - if ( pio_readBusMstrStatus() & BM_SR_MASK_ERR ) - { - reg_cmd_info.ec = 78; // yes - } - - // WRITE_DONE: - - // All done. The return values of this function are described in - // MINDRVR.H. - - if ( reg_cmd_info.ec ) - return 1; - return 0; -} - -//************************************************************* -// -// reg_pio_data_out_lba28() - Easy way to execute a PIO Data In command -// using an LBA sector address. -// -//************************************************************* - -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 ) - -{ - - reg_cmd_info.cmd = cmd; - reg_cmd_info.fr = fr; - reg_cmd_info.sc = sc; - reg_cmd_info.dh = (unsigned char) ( CB_DH_LBA | ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - reg_cmd_info.dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - reg_cmd_info.lbaSize = LBA28; - reg_cmd_info.lbaHigh = 0; - reg_cmd_info.lbaLow = lba; - - // adjust multiple count - if ( multiCnt & 0x0800 ) - { - // assume caller knows what they are doing - multiCnt &= 0x00ff; - } - else - { - // only Write Multiple and CFA Write Multiple W/O Erase uses multiCnt - if ( ( cmd != CMD_WRITE_MULTIPLE ) - && ( cmd != CMD_CFA_WRITE_MULTIPLE_WO_ERASE ) - ) - multiCnt = 1; - } - - reg_cmd_info.ns = numSect; - reg_cmd_info.mc = multiCnt; - - return exec_pio_data_out_cmd( dev, bufAddr, numSect, multiCnt ); -} - -//************************************************************* -// -// reg_pio_data_out_lba48() - Easy way to execute a PIO Data In command -// using an LBA sector address. -// -//************************************************************* - -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 ) - -{ - - reg_cmd_info.cmd = cmd; - reg_cmd_info.fr = fr; - reg_cmd_info.sc = sc; - reg_cmd_info.dh = (unsigned char) ( CB_DH_LBA | ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - reg_cmd_info.dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - reg_cmd_info.lbaSize = LBA48; - reg_cmd_info.lbaHigh = lbahi; - reg_cmd_info.lbaLow = lbalo; - - // adjust multiple count - if ( multiCnt & 0x0800 ) - { - // assume caller knows what they are doing - multiCnt &= 0x00ff; - } - else - { - // only Write Multiple Ext uses multiCnt - if ( cmd != CMD_WRITE_MULTIPLE_EXT ) - multiCnt = 1; - } - - reg_cmd_info.ns = numSect; - reg_cmd_info.mc = multiCnt; - - return exec_pio_data_out_cmd( dev, bufAddr, numSect, multiCnt ); -} - -#if INCLUDE_ATAPI_PIO - -//************************************************************* -// -// reg_packet() - Execute an ATAPI Packet (A0H) command. -// -// See ATA-4 Section 9.10, Figure 14. -// -//************************************************************* - -int reg_packet( unsigned char dev, - unsigned int cpbc, - unsigned char * cdbBufAddr, - int dir, - long dpbc, - unsigned char * dataBufAddr ) - -{ - unsigned char status; - unsigned int byteCnt; - long wordCnt; - - // reset Bus Master Error bit - - pio_writeBusMstrStatus( BM_SR_MASK_ERR ); - - // Make sure the command packet size is either 12 or 16 - // and save the command packet size and data. - - cpbc = cpbc < 12 ? 12 : cpbc; - cpbc = cpbc > 12 ? 16 : cpbc; - - // Setup current command information. - - reg_cmd_info.ec = 0; - reg_cmd_info.cmd = CMD_PACKET; - reg_cmd_info.fr = 0; - reg_cmd_info.sc = 0; - reg_cmd_info.sn = 0; - reg_cmd_info.cl = (unsigned char) ( dpbc & 0x00ff ); - reg_cmd_info.ch = ( unsigned char) ( ( dpbc & 0xff00 ) >> 8 ); - reg_cmd_info.dh = (unsigned char) ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ); - reg_cmd_info.dc = (unsigned char) ( int_use_intr_flag ? 0 : CB_DC_NIEN ); - reg_cmd_info.lbaSize = 0; - // Set command time out. - - tmr_set_timeout(); - - // Select the drive - call the sub_select function. - // Quit now if this fails. - - if ( sub_select( dev ) ) - { - return 1; - } - - // Set up all the registers except the command register. - - sub_setup_command(); - - // Start the command by setting the Command register. The drive - // should immediately set BUSY status. - - pio_outbyte( CB_CMD, CMD_PACKET ); - - // Waste some time by reading the alternate status a few times. - // This gives the drive time to set BUSY in the status register on - // really fast systems. If we don't do this, a slow drive on a fast - // system may not set BUSY fast enough and we would think it had - // completed the command when it really had not even started the - // command yet. - - DELAY400NS; - - // Command packet transfer... - // Poll Alternate Status for BSY=0. - - while ( 1 ) - { - status = pio_inbyte( CB_ASTAT ); // poll for not busy - if ( ( status & CB_STAT_BSY ) == 0 ) - break; - if ( tmr_chk_timeout() ) // time out yet ? - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 51; - dir = -1; // command done - break; - } - } - - // Command packet transfer... - // Check for protocol failures... no interrupt here please! - - // Command packet transfer... - // If no error, transfer the command packet. - - if ( reg_cmd_info.ec == 0 ) - { - - // Command packet transfer... - // Read the primary status register and the other ATAPI registers. - - status = pio_inbyte( CB_STAT ); - - // Command packet transfer... - // check status: must have BSY=0, DRQ=1 now - - if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR ) ) - != CB_STAT_DRQ - ) - { - reg_cmd_info.ec = 52; - dir = -1; // command done - } - else - { - // Command packet transfer... - // xfer the command packet (the cdb) - - pio_drq_block_out( CB_DATA, cdbBufAddr, cpbc >> 1 ); - - DELAY400NS; // delay so device can get the status updated - } - } - - // Data transfer loop... - // If there is no error, enter the data transfer loop. - - while ( reg_cmd_info.ec == 0 ) - { - // Data transfer loop... - // Wait for interrupt -or- wait for not BUSY -or- wait for time out. - - sub_wait_poll( 53, 54 ); - - // Data transfer loop... - // If there was a time out error, exit the data transfer loop. - - if ( reg_cmd_info.ec ) - { - dir = -1; // command done - break; - } - - // Data transfer loop... - // If using interrupts get the status read by the interrupt - // handler, otherwise read the status register. - - if ( int_use_intr_flag ) - status = int_ata_status; - else - status = pio_inbyte( CB_STAT ); - - // Data transfer loop... - // Exit the read data loop if the device indicates this - // is the end of the command. - - if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == 0 ) - { - dir = -1; // command done - break; - } - - // Data transfer loop... - // The device must want to transfer data... - // check status: must have BSY=0, DRQ=1 now. - - if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) != CB_STAT_DRQ ) - { - reg_cmd_info.ec = 55; - dir = -1; // command done - break; - } - - // Data transfer loop... - // get the byte count, check for zero... - - byteCnt = ( pio_inbyte( CB_CH ) << 8 ) | pio_inbyte( CB_CL ); - if ( byteCnt < 1 ) - { - reg_cmd_info.ec = 59; - dir = -1; // command done - break; - } - - // Data transfer loop... - // increment number of DRQ packets - - reg_cmd_info.drqPackets ++ ; - - // Data transfer loop... - // transfer the data and update the i/o buffer address - // and the number of bytes transfered. - - wordCnt = ( byteCnt >> 1 ) + ( byteCnt & 0x0001 ); - reg_cmd_info.totalBytesXfer += ( wordCnt << 1 ); - if ( dir ) - pio_drq_block_out( CB_DATA, dataBufAddr, wordCnt ); - else - pio_drq_block_in( CB_DATA, dataBufAddr, wordCnt ); - dataBufAddr = dataBufAddr + byteCnt; - - DELAY400NS; // delay so device can get the status updated - } - - // End of command... - // Wait for interrupt or poll for BSY=0, - // but don't do this if there was any error or if this - // was a commmand that did not transfer data. - - if ( ( reg_cmd_info.ec == 0 ) && ( dir >= 0 ) ) - { - sub_wait_poll( 56, 57 ); - } - - // Final status check, only if no previous error. - - if ( reg_cmd_info.ec == 0 ) - { - // Final status check... - // If using interrupts get the status read by the interrupt - // handler, otherwise read the status register. - - if ( int_use_intr_flag ) - status = int_ata_status; - else - status = pio_inbyte( CB_STAT ); - - // Final status check... - // check for any error. - - if ( status & ( CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR ) ) - { - reg_cmd_info.ec = 58; - } - } - - // Done... - - // Final status check - // BMIDE Error=1? - - if ( pio_readBusMstrStatus() & BM_SR_MASK_ERR ) - { - reg_cmd_info.ec = 78; // yes - } - - // All done. The return values of this function are described in - // MINDRVR.H. - - if ( reg_cmd_info.ec ) - return 1; - return 0; -} - -#endif // INCLUDE_ATAPI - -#if INCLUDE_ATA_DMA - -//*********************************************************** -// -// Some notes about PCI bus mastering DMA... -// -// !!! The DMA support in MINDRVR is based on x86 PCI bus mastering -// !!! ATA controller design as described by the T13 document -// !!! '1510 Host Controller Standard' (in sections 1-6). -// -// Note that the T13 1510D document also describes a -// complex DMA engine called ADMA. While ADMA is a good idea it -// will probably never be popular or widely implemented. MINDRVR -// does not support ADMA. -// -// The base address of the Bus Master Control Registers (BMIDE) is -// found in the PCI Configuration space for the ATA controller (at -// offset 0x20 in the config space data). This is normally an I/O -// address. -// -// The BMIDE data is 16 bytes of data starting at the BMIDE base -// address. The first 8 bytes is for the primary ATA channel and -// the second 8 bytes is for the secondary ATA channel. The 8 bytes -// contain a "command" byte and a "status" byte and a 4 byte -// (32-bit) physical memory address pointing to the Physical Region -// Descriptor (PRD) list. Each PRD entry describes an area of -// memory or data buffer for the DMA transfer. A region described -// by a PRD may not cross a 64K byte boundary in physical memory. -// Also, the PRD list must not cross a 64K byte boundary. -// -//*********************************************************** - -//*********************************************************** -// -// pci bus master registers and PRD list buffer, -// see the dma_pci_config() and set_up_xfer() functions. -// -// !!! Note that the PRD buffer is statically allocated here -// !!! but the actual address of the buffer is adjusted by -// !!! the dma_pci_config() function. -// -//*********************************************************** - -unsigned long * dma_pci_prd_ptr; // current PRD buffer address -int dma_pci_num_prd; // current number of PRD entries - -unsigned char statReg; // save BM status reg bits -static unsigned char rwControl; // read/write control bit setting - -unsigned char *prdBuf; // PRD buffer -unsigned long *prdBufPtr; // first PRD addr - -//*********************************************************** -// -// dma_pci_config() - 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. -// -//*********************************************************** -/* -int dma_pci_config( void ) - -{ - unsigned long lw; - - // 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... - lw = (unsigned long) prdBuf; - // ...move up to an 8 byte boundary. - lw = lw + 15; - lw = lw & 0xfffffff8L; - // ...check for 64KB boundary in the first part of the PRD buffer, - // ...if so just move the buffer to that boundary. - if ( ( lw & 0xffff0000L ) - != - ( ( lw + ( MAX_PRD * 8L ) - 1L ) & 0xffff0000L ) - ) - lw = ( lw + ( MAX_PRD * 8L ) ) & 0xffff0000L; - // ... return the address of the first PRD - dma_pci_prd_ptr = prdBufPtr = (unsigned long *) lw; - // ... 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 ); - - return 0; -} -*/ -//*********************************************************** -// -// set_up_xfer() -- set up the PRD entry list -// -// !!! MINDRVR assumes the entire DMA data transfer is contained -// !!! within a single contiguous I/O buffer. You may not need -// !!! a much more complex set_up_xfer() function to support -// !!! true scatter/gather lists. -// -// The PRD list must be aligned on an 8 byte boundary and the -// list must not cross a 64K byte boundary in memory. -// -//*********************************************************** - -static int set_up_xfer( int dir, long bc, unsigned char * bufAddr ); - -static int set_up_xfer( int dir, long bc, unsigned char * bufAddr ) - -{ - int numPrd; // number of PRD required - int maxPrd; // max number of PRD allowed - unsigned long temp; - unsigned long phyAddr; // physical memory address - unsigned long * prdPtr; // pointer to PRD entry list - - // disable/stop the dma channel, clear interrupt and error bits - pio_writeBusMstrCmd( BM_CR_MASK_STOP ); - pio_writeBusMstrStatus( (unsigned char) ( statReg | BM_SR_MASK_INT | BM_SR_MASK_ERR ) ); - - // setup to build the PRD list... - // ...max PRDs allowed - maxPrd = (int) MAX_PRD; - // ...PRD buffer address - prdPtr = prdBufPtr; - dma_pci_prd_ptr = prdPtr; - // ... convert I/O buffer address to an physical memory address - phyAddr = (unsigned long) bufAddr; - - // build the PRD list... - // ...PRD entry format: - // +0 to +3 = memory address - // +4 to +5 = 0x0000 (not EOT) or 0x8000 (EOT) - // +6 to +7 = byte count - // ...zero number of PRDs - numPrd = 0; - // ...loop to build each PRD - while ( bc > 0 ) - { - if ( numPrd >= maxPrd ) - return 1; - // set this PRD's address - prdPtr[0] = phyAddr; - // set count for this PRD - temp = 65536L; // max PRD length - if ( temp > bc ) // count to large? - temp = bc; // yes - use actual count - // check if count will fit - phyAddr = phyAddr + temp; - if ( ( phyAddr & 0xffff0000L ) != ( prdPtr[0] & 0xffff0000L ) ) - { - phyAddr = phyAddr & 0xffff0000L; - temp = phyAddr - prdPtr[0]; - } - // set this PRD's count - prdPtr[1] = temp & 0x0000ffffL; - // update byte count - bc = bc - temp; - // set the end bit in the prd list - if ( bc < 1 ) - prdPtr[1] = prdPtr[1] | 0x80000000L; - prdPtr ++ ; - prdPtr ++ ; - numPrd ++ ; - } - - // return the current PRD list size and - // write into BMIDE PRD address registers. - - dma_pci_num_prd = numPrd; - /* - * (unsigned long *) (pio_bmide_base_addr + BM_PRD_ADDR_LOW ) - = (unsigned long) prdBufPtr; - */ - pio_writeBusMstrPrd((unsigned long)prdBufPtr); - // set the read/write control: - // PCI reads for ATA Write DMA commands, - // PCI writes for ATA Read DMA commands. - - if ( dir ) - rwControl = BM_CR_MASK_READ; // ATA Write DMA - else - rwControl = BM_CR_MASK_WRITE; // ATA Read DMA - pio_writeBusMstrCmd( rwControl ); - return 0; -} - -//*********************************************************** -// -// exec_pci_ata_cmd() - PCI Bus Master for ATA R/W DMA commands -// -//*********************************************************** - -static int exec_pci_ata_cmd( unsigned char dev, - unsigned char * bufAddr, - long numSect ); - -static int exec_pci_ata_cmd( unsigned char dev, - unsigned char * bufAddr, - long numSect ) - -{ - unsigned char status; - - // Quit now if the command is incorrect. - - if ( ( reg_cmd_info.cmd != CMD_READ_DMA ) - && ( reg_cmd_info.cmd != CMD_READ_DMA_EXT ) - && ( reg_cmd_info.cmd != CMD_WRITE_DMA ) - && ( reg_cmd_info.cmd != CMD_WRITE_DMA_EXT ) ) - { - reg_cmd_info.ec = 77; - return 1; - } - - // Set up the dma transfer - - if ( set_up_xfer( ( reg_cmd_info.cmd == CMD_WRITE_DMA ) - || - ( reg_cmd_info.cmd == CMD_WRITE_DMA_EXT ), - numSect * 512L, bufAddr ) ) - { - reg_cmd_info.ec = 61; - return 1; - } - - // Set command time out. - - tmr_set_timeout(); - - // Select the drive - call the sub_select function. - // Quit now if this fails. - - if ( sub_select( dev ) ) - { - return 1; - } - - // Set up all the registers except the command register. - - sub_setup_command(); - - // Start the command by setting the Command register. The drive - // should immediately set BUSY status. - - pio_outbyte( CB_CMD, reg_cmd_info.cmd ); - - // The drive should start executing the command including any - // data transfer. - - // Data transfer... - // read the BMIDE regs - // enable/start the dma channel. - // read the BMIDE regs again - - pio_readBusMstrCmd(); - pio_readBusMstrStatus(); - pio_writeBusMstrCmd( (unsigned char) ( rwControl | BM_CR_MASK_START ) ); - pio_readBusMstrCmd(); - pio_readBusMstrStatus(); - - // Data transfer... - // the device and dma channel transfer the data here while we start - // checking for command completion... - // wait for the PCI BM Interrupt=1 (see ATAIOINT.C)... - - if ( SYSTEM_WAIT_INTR_OR_TIMEOUT() ) // time out ? - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 73; - } - - // End of command... - // disable/stop the dma channel - - status = int_bmide_status; // read BM status - status &= ~ BM_SR_MASK_ACT; // ignore Active bit - pio_writeBusMstrCmd( BM_CR_MASK_STOP ); // shutdown DMA - pio_readBusMstrCmd(); // read BM cmd (just for trace) - status |= pio_readBusMstrStatus(); // read BM status again - - if ( reg_cmd_info.ec == 0 ) - { - if ( status & BM_SR_MASK_ERR ) // bus master error? - { - reg_cmd_info.ec = 78; // yes - } - } - if ( reg_cmd_info.ec == 0 ) - { - if ( status & BM_SR_MASK_ACT ) // end of PRD list? - { - reg_cmd_info.ec = 71; // no - } - } - - // End of command... - // If no error use the Status register value that was read - // by the interrupt handler. If there was an error - // read the Status register because it may not have been - // read by the interrupt handler. - - if ( reg_cmd_info.ec ) - status = pio_inbyte( CB_STAT ); - else - status = int_ata_status; - - // Final status check... - // if no error, check final status... - // Error if BUSY, DEVICE FAULT, DRQ or ERROR status now. - - if ( reg_cmd_info.ec == 0 ) - { - if ( status & ( CB_STAT_BSY | CB_STAT_DF | CB_STAT_DRQ | CB_STAT_ERR ) ) - { - reg_cmd_info.ec = 74; - } - } - - // Final status check... - // if any error, update total bytes transferred. - - if ( reg_cmd_info.ec == 0 ) - reg_cmd_info.totalBytesXfer = numSect * 512L; - else - reg_cmd_info.totalBytesXfer = 0L; - - // All done. The return values of this function are described in - // MINDRVR.H. - - if ( reg_cmd_info.ec ) - return 1; - return 0; -} - -//*********************************************************** -// -// dma_pci_lba28() - DMA in PCI Multiword for ATA R/W DMA -// -//*********************************************************** - -int dma_pci_lba28( unsigned char dev, unsigned char cmd, - unsigned int fr, unsigned int sc, - unsigned long lba, - unsigned char * bufAddr, - long numSect ) - -{ - - // Setup current command information. - - reg_cmd_info.cmd = cmd; - reg_cmd_info.fr = fr; - reg_cmd_info.sc = sc; - reg_cmd_info.dh = (unsigned char) ( CB_DH_LBA | ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - reg_cmd_info.dc = 0x00; // nIEN=0 required on PCI ! - reg_cmd_info.ns = numSect; - reg_cmd_info.lbaSize = LBA28; - reg_cmd_info.lbaHigh = 0L; - reg_cmd_info.lbaLow = lba; - - // Execute the command. - - return exec_pci_ata_cmd( dev, bufAddr, numSect ); -} - -//*********************************************************** -// -// dma_pci_lba48() - DMA in PCI Multiword for ATA R/W DMA -// -//*********************************************************** - -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 ) - -{ - - // Setup current command information. - - reg_cmd_info.cmd = cmd; - reg_cmd_info.fr = fr; - reg_cmd_info.sc = sc; - reg_cmd_info.dh = (unsigned char) ( CB_DH_LBA | ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - reg_cmd_info.dc = 0x00; // nIEN=0 required on PCI ! - reg_cmd_info.ns = numSect; - reg_cmd_info.lbaSize = LBA48; - reg_cmd_info.lbaHigh = lbahi; - reg_cmd_info.lbaLow = lbalo; - - // Execute the command. - - return exec_pci_ata_cmd( dev, bufAddr, numSect ); -} - -#endif // INCLUDE_ATA_DMA - -#if INCLUDE_ATAPI_DMA - -//*********************************************************** -// -// dma_pci_packet() - PCI Bus Master for ATAPI Packet command -// -//*********************************************************** - -int dma_pci_packet( unsigned char dev, - unsigned int cpbc, - unsigned char * cdbBufAddr, - int dir, - long dpbc, - unsigned char * dataBufAddr ) - -{ - unsigned char status; - - // Make sure the command packet size is either 12 or 16 - // and save the command packet size and data. - - cpbc = cpbc < 12 ? 12 : cpbc; - cpbc = cpbc > 12 ? 16 : cpbc; - - // Setup current command information. - - reg_cmd_info.cmd = CMD_PACKET; - reg_cmd_info.fr = 0x01; // packet DMA mode ! - reg_cmd_info.sc = 0; - reg_cmd_info.sn = 0; - reg_cmd_info.cl = 0; // no Byte Count Limit in DMA ! - reg_cmd_info.ch = 0; // no Byte Count Limit in DMA ! - reg_cmd_info.dh = (unsigned char) ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ); - reg_cmd_info.dc = 0x00; // nIEN=0 required on PCI ! - reg_cmd_info.lbaSize = 0; - - // the data packet byte count must be even - // and must not be zero - - if ( dpbc & 1L ) - dpbc ++ ; - if ( dpbc < 2L ) - dpbc = 2L; - - // Set up the dma transfer - - if ( set_up_xfer( dir, dpbc, dataBufAddr ) ) - { - reg_cmd_info.ec = 61; - return 1; - } - - // Set command time out. - - tmr_set_timeout(); - - // Select the drive - call the reg_select function. - // Quit now if this fails. - - if ( sub_select( dev ) ) - { - return 1; - } - - // Set up all the registers except the command register. - - sub_setup_command(); - - // Start the command by setting the Command register. The drive - // should immediately set BUSY status. - - pio_outbyte( CB_CMD, CMD_PACKET ); - - // Waste some time by reading the alternate status a few times. - // This gives the drive time to set BUSY in the status register on - // really fast systems. If we don't do this, a slow drive on a fast - // system may not set BUSY fast enough and we would think it had - // completed the command when it really had not started the - // command yet. - - DELAY400NS; - - // Command packet transfer... - // Poll Alternate Status for BSY=0. - - while ( 1 ) - { - status = pio_inbyte( CB_ASTAT ); // poll for not busy - if ( ( status & CB_STAT_BSY ) == 0 ) - break; - if ( tmr_chk_timeout() ) // time out yet ? - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 75; - break; - } - } - - // Command packet transfer... - // Check for protocol failures... no interrupt here please! - - // Command packet transfer... - // If no error, transfer the command packet. - - if ( reg_cmd_info.ec == 0 ) - { - - // Command packet transfer... - // Read the primary status register and the other ATAPI registers. - - status = pio_inbyte( CB_STAT ); - - // Command packet transfer... - // check status: must have BSY=0, DRQ=1 now - - if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR ) ) - != CB_STAT_DRQ - ) - { - reg_cmd_info.ec = 76; - } - else - { - - // Command packet transfer... - // xfer the command packet (the cdb) - - pio_drq_block_out( CB_DATA, cdbBufAddr, cpbc >> 1 ); - } - } - - // Data transfer... - // The drive should start executing the command - // including any data transfer. - // If no error, set up and start the DMA, - // and wait for the DMA to complete. - - if ( reg_cmd_info.ec == 0 ) - { - - // Data transfer... - // read the BMIDE regs - // enable/start the dma channel. - // read the BMIDE regs again - - pio_readBusMstrCmd(); - pio_readBusMstrStatus(); - pio_writeBusMstrCmd( (unsigned char) ( rwControl | BM_CR_MASK_START ) ); - pio_readBusMstrCmd(); - pio_readBusMstrStatus(); - - // Data transfer... - // the device and dma channel transfer the data here while we start - // checking for command completion... - // wait for the PCI BM Active=0 and Interrupt=1 or PCI BM Error=1... - - if ( SYSTEM_WAIT_INTR_OR_TIMEOUT() ) // time out ? - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 73; - } - - // End of command... - // disable/stop the dma channel - - status = int_bmide_status; // read BM status - status &= ~ BM_SR_MASK_ACT; // ignore Active bit - pio_writeBusMstrCmd( BM_CR_MASK_STOP ); // shutdown DMA - pio_readBusMstrCmd(); // read BM cmd (just for trace) - status |= pio_readBusMstrStatus(); // read BM statu again - } - - if ( reg_cmd_info.ec == 0 ) - { - if ( status & ( BM_SR_MASK_ERR ) ) // bus master error? - { - reg_cmd_info.ec = 78; // yes - } - if ( ( status & BM_SR_MASK_ACT ) ) // end of PRD list? - { - reg_cmd_info.ec = 71; // no - } - } - - // End of command... - // If no error use the Status register value that was read - // by the interrupt handler. If there was an error - // read the Status register because it may not have been - // read by the interrupt handler. - - if ( reg_cmd_info.ec ) - status = pio_inbyte( CB_STAT ); - else - status = int_ata_status; - - // Final status check... - // if no error, check final status... - // Error if BUSY, DRQ or ERROR status now. - - if ( reg_cmd_info.ec == 0 ) - { - if ( status & ( CB_STAT_BSY | CB_STAT_DRQ | CB_STAT_ERR ) ) - { - reg_cmd_info.ec = 74; - } - } - - - // Final status check... - // if any error, update total bytes transferred. - - if ( reg_cmd_info.ec == 0 ) - reg_cmd_info.totalBytesXfer = dpbc; - else - reg_cmd_info.totalBytesXfer = 0L; - - // All done. The return values of this function are described in - // MINDRVR.H. - - if ( reg_cmd_info.ec ) - return 1; - return 0; -} - -#endif // INCLUDE_ATAPI_DMA - -//************************************************************* -// -// sub_setup_command() -- setup the command parameters -// in FR, SC, SN, CL, CH and DH. -// -//************************************************************* - -static void sub_setup_command( void ) - -{ - - // output DevCtrl - same for all devices and commands - pio_outbyte( CB_DC, reg_cmd_info.dc ); - - // output command parameters - if ( reg_cmd_info.lbaSize == LBA28 ) - { - // in ATA LBA28 mode - pio_outbyte( CB_FR, (unsigned char) reg_cmd_info.fr ); - pio_outbyte( CB_SC, (unsigned char) reg_cmd_info.sc ); - pio_outbyte( CB_SN, (unsigned char) reg_cmd_info.lbaLow ); - pio_outbyte( CB_CL, (unsigned char) ( reg_cmd_info.lbaLow >> 8 ) ); - pio_outbyte( CB_CH, (unsigned char) ( reg_cmd_info.lbaLow >> 16 ) ); - pio_outbyte( CB_DH, (unsigned char) ( ( reg_cmd_info.dh & 0xf0 ) - | ( ( reg_cmd_info.lbaLow >> 24 ) & 0x0f ) ) ); - } - else - if ( reg_cmd_info.lbaSize == LBA48 ) - { - // in ATA LBA48 mode - pio_outbyte( CB_FR, (unsigned char) ( reg_cmd_info.fr >> 8 ) ); - pio_outbyte( CB_SC, (unsigned char) ( reg_cmd_info.sc >> 8 ) ); - pio_outbyte( CB_SN, (unsigned char) ( reg_cmd_info.lbaLow >> 24 ) ); - pio_outbyte( CB_CL, (unsigned char) reg_cmd_info.lbaHigh ); - pio_outbyte( CB_CH, (unsigned char) ( reg_cmd_info.lbaHigh >> 8 ) ); - pio_outbyte( CB_FR, (unsigned char) reg_cmd_info.fr ); - pio_outbyte( CB_SC, (unsigned char) reg_cmd_info.sc ); - pio_outbyte( CB_SN, (unsigned char) reg_cmd_info.lbaLow ); - pio_outbyte( CB_CL, (unsigned char) ( reg_cmd_info.lbaLow >> 8 ) ); - pio_outbyte( CB_CH, (unsigned char) ( reg_cmd_info.lbaLow >> 16 ) ); - pio_outbyte( CB_DH, reg_cmd_info.dh ); - } - else - { - // for ATAPI PACKET command - pio_outbyte( CB_FR, (unsigned char) reg_cmd_info.fr ); - pio_outbyte( CB_SC, (unsigned char) reg_cmd_info.sc ); - pio_outbyte( CB_SN, (unsigned char) reg_cmd_info.sn ); - pio_outbyte( CB_CL, (unsigned char) reg_cmd_info.cl ); - pio_outbyte( CB_CH, (unsigned char) reg_cmd_info.ch ); - pio_outbyte( CB_DH, reg_cmd_info.dh ); - } -} - -//************************************************************* -// -// sub_trace_command() -- trace the end of a command. -// -//************************************************************* - -static void sub_trace_command( void ) - -{ - - reg_cmd_info.st = pio_inbyte( CB_STAT ); - reg_cmd_info.as = pio_inbyte( CB_ASTAT ); - reg_cmd_info.er = pio_inbyte( CB_ERR ); - -// !!! if you want to read back the other device registers -// !!! at the end of a command then this is the place to do -// !!! it. The code here is just and example of out this is -// !!! done on a little endian system like an x86. - -#if 0 // read back other registers - - { - unsigned long lbaHigh; - unsigned long lbaLow; - unsigned char sc48[2]; - unsigned char lba48[8]; - - lbaHigh = 0; - lbaLow = 0; - if ( reg_cmd_info.lbaSize == LBA48 ) - { - // read back ATA LBA48... - sc48[0] = pio_inbyte( CB_SC ); - lba48[0] = pio_inbyte( CB_SN ); - lba48[1] = pio_inbyte( CB_CL ); - lba48[2] = pio_inbyte( CB_CH ); - pio_outbyte( CB_DC, CB_DC_HOB ); - sc48[1] = pio_inbyte( CB_SC ); - lba48[3] = pio_inbyte( CB_SN ); - lba48[4] = pio_inbyte( CB_CL ); - lba48[5] = pio_inbyte( CB_CH ); - lba48[6] = 0; - lba48[7] = 0; - lbaHigh = * (unsigned long *) ( lba48 + 4 ); - lbaLow = * (unsigned long *) ( lba48 + 0 ); - } - else - if ( reg_cmd_info.lbaSize == LBA28 ) - { - // read back ATA LBA28 - lbaLow = pio_inbyte( CB_DH ); - lbaLow = lbaLow << 8; - lbaLow = lbaLow | pio_inbyte( CB_CH ); - lbaLow = lbaLow << 8; - lbaLow = lbaLow | pio_inbyte( CB_CL ); - lbaLow = lbaLow << 8; - lbaLow = lbaLow | pio_inbyte( CB_SN ); - } - else - { - // really no reason to read back for ATAPI - } - } - -#endif // read back other registers - -} - -//************************************************************* -// -// sub_select() - function used to select a drive. -// -// Function to select a drive making sure that BSY=0 and DRQ=0. -// -//************************************************************** - -static int sub_select( unsigned char dev ) - -{ - unsigned char status; - - // PAY ATTENTION HERE - // The caller may want to issue a command to a device that doesn't - // exist (for example, Exec Dev Diag), so if we see this, - // just select that device, skip all status checking and return. - // We assume the caller knows what they are doing! - - if ( reg_config_info[dev] < REG_CONFIG_TYPE_ATA ) - { - // select the device and return - - pio_outbyte( CB_DH, (unsigned char) ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - DELAY400NS; - return 0; - } - - // The rest of this is the normal ATA stuff for device selection - // and we don't expect the caller to be selecting a device that - // does not exist. - // We don't know which drive is currently selected but we should - // wait BSY=0 and DRQ=0. Normally both BSY=0 and DRQ=0 - // unless something is very wrong! - - while ( 1 ) - { - status = pio_inbyte( CB_STAT ); - if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == 0 ) - break; - if ( tmr_chk_timeout() ) - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 11; - reg_cmd_info.st = status; - reg_cmd_info.as = pio_inbyte( CB_ASTAT ); - reg_cmd_info.er = pio_inbyte( CB_ERR ); - return 1; - } - } - - // Here we select the drive we really want to work with by - // setting the DEV bit in the Drive/Head register. - - pio_outbyte( CB_DH, (unsigned char) ( dev ? CB_DH_DEV1 : CB_DH_DEV0 ) ); - DELAY400NS; - - // Wait for the selected device to have BSY=0 and DRQ=0. - // Normally the drive should be in this state unless - // something is very wrong (or initial power up is still in - // progress). - - while ( 1 ) - { - status = pio_inbyte( CB_STAT ); - if ( ( status & ( CB_STAT_BSY | CB_STAT_DRQ ) ) == 0 ) - break; - if ( tmr_chk_timeout() ) - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = 12; - reg_cmd_info.st = status; - reg_cmd_info.as = pio_inbyte( CB_ASTAT ); - reg_cmd_info.er = pio_inbyte( CB_ERR ); - return 1; - } - } - - // All done. The return values of this function are described in - // ATAIO.H. - - if ( reg_cmd_info.ec ) - return 1; - return 0; -} - -//************************************************************* -// -// sub_wait_poll() - wait for interrupt or poll for BSY=0 -// -//************************************************************* - -static void sub_wait_poll( unsigned char we, unsigned char pe ) - -{ - unsigned char status; - - // Wait for interrupt -or- wait for not BUSY -or- wait for time out. - - if ( we && int_use_intr_flag ) - { - if ( SYSTEM_WAIT_INTR_OR_TIMEOUT() ) // time out ? - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = we; - } - } - else - { - while ( 1 ) - { - status = pio_inbyte( CB_ASTAT ); // poll for not busy - if ( ( status & CB_STAT_BSY ) == 0 ) - break; - if ( tmr_chk_timeout() ) // time out yet ? - { - reg_cmd_info.to = 1; - reg_cmd_info.ec = pe; - break; - } - } - } -} - -//*********************************************************** -// -// functions used to read/write the BMIDE registers -// -//*********************************************************** -/* -static unsigned char pio_readBusMstrCmd( void ) - -{ - unsigned char x; - - if ( ! pio_bmide_base_addr ) - return 0; - x = * (pio_bmide_base_addr + BM_COMMAND_REG ); - return x; -} - - -static unsigned char pio_readBusMstrStatus( void ) - -{ - unsigned char x; - - if ( ! pio_bmide_base_addr ) - return 0; - x = * ( pio_bmide_base_addr + BM_STATUS_REG ); - return x; -} - - -static void pio_writeBusMstrCmd( unsigned char x ) - -{ - - if ( ! pio_bmide_base_addr ) - return; - * ( pio_bmide_base_addr + BM_COMMAND_REG ) = x; -} - - -static void pio_writeBusMstrStatus( unsigned char x ) - -{ - - if ( ! pio_bmide_base_addr ) - return; - * ( pio_bmide_base_addr + BM_STATUS_REG ) = x; -} -*/ -//************************************************************* -// -// These functions do basic IN/OUT of byte and word values: -// -// pio_inbyte() -// pio_outbyte() -// pio_inword() -// pio_outword() -// -//************************************************************* - -//static unsigned char pio_inbyte( unsigned char addr ) -// -//{ -// -// //!!! read an 8-bit ATA register -// -// return * pio_reg_addrs[ addr ]; -//} - -//************************************************************* - -//static void pio_outbyte( int addr, unsigned char data ) -// -//{ -// -// //!!! write an 8-bit ATA register -// -// * pio_reg_addrs[ addr ] = data; -//} - -//************************************************************* - -//static unsigned int pio_inword( unsigned char addr ) -// -//{ -// -// //!!! read an 8-bit ATA register (usually the ATA Data register) -// -// return * ( (unsigned int *) pio_reg_addrs[ addr ] ); -//} - -//************************************************************* - -//static void pio_outword( int addr, unsigned int data ) -// -//{ -// -// //!!! Write an 8-bit ATA register (usually the ATA Data register) -// -// * ( (unsigned int *) pio_reg_addrs[ addr ] ) = data; -//} - -//************************************************************* - -//static unsigned long pio_indword( unsigned char addr ) -// -//{ -// -// //!!! read an 8-bit ATA register (usually the ATA Data register) -// -// return * ( (unsigned long *) pio_reg_addrs[ addr ] ); -//} - -//************************************************************* - -//static void pio_outdword( int addr, unsigned long data ) -// -//{ -// -// //!!! Write an 8-bit ATA register (usually the ATA Data register) -// -// * ( (unsigned long *) pio_reg_addrs[ addr ] ) = data; -//} - -//************************************************************* -// -// These functions are normally used to transfer DRQ blocks: -// -// pio_drq_block_in() -// pio_drq_block_out() -// -//************************************************************* - -// Note: pio_drq_block_in() is the primary way perform PIO -// Data In transfers. It will handle 8-bit, 16-bit and 32-bit -// I/O based data transfers. - -static void pio_drq_block_in( unsigned char addrDataReg, - unsigned char * bufAddr, - long wordCnt ) - -{ - - // NOTE: wordCnt is the size of a DRQ data block/packet - // in words. The maximum value of wordCnt is normally: - // a) For ATA, 16384 words or 32768 bytes (64 sectors, - // only with READ/WRITE MULTIPLE commands), - // b) For ATAPI, 32768 words or 65536 bytes - // (actually 65535 bytes plus a pad byte). - - { - int pxw; - long wc; - - // adjust pio_xfer_width - don't use DWORD if wordCnt is odd. - - pxw = pio_xfer_width; - if ( ( pxw == 32 ) && ( wordCnt & 0x00000001L ) ) - pxw = 16; - - // Data transfer using INS instruction. - // Break the transfer into chunks of 32768 or fewer bytes. - - while ( wordCnt > 0 ) - { - if ( wordCnt > 16384L ) - wc = 16384; - else - wc = wordCnt; - if ( pxw == 8 ) - { - // do REP INS - pio_rep_inbyte( addrDataReg, bufAddr, wc * 2L ); - } - else - if ( pxw == 32 ) - { - // do REP INSD - pio_rep_indword( addrDataReg, bufAddr, wc / 2L ); - } - else - { - // do REP INSW - pio_rep_inword( addrDataReg, bufAddr, wc ); - } - bufAddr = bufAddr + ( wc * 2 ); - wordCnt = wordCnt - wc; - } - } - - return; -} - -//************************************************************* - -// Note: pio_drq_block_out() is the primary way perform PIO -// Data Out transfers. It will handle 8-bit, 16-bit and 32-bit -// I/O based data transfers. - -static void pio_drq_block_out( unsigned char addrDataReg, - unsigned char * bufAddr, - long wordCnt ) - -{ - - // NOTE: wordCnt is the size of a DRQ data block/packet - // in words. The maximum value of wordCnt is normally: - // a) For ATA, 16384 words or 32768 bytes (64 sectors, - // only with READ/WRITE MULTIPLE commands), - // b) For ATAPI, 32768 words or 65536 bytes - // (actually 65535 bytes plus a pad byte). - - { - int pxw; - long wc; - - // adjust pio_xfer_width - don't use DWORD if wordCnt is odd. - - pxw = pio_xfer_width; - if ( ( pxw == 32 ) && ( wordCnt & 0x00000001L ) ) - pxw = 16; - - // Data transfer using OUTS instruction. - // Break the transfer into chunks of 32768 or fewer bytes. - - while ( wordCnt > 0 ) - { - if ( wordCnt > 16384L ) - wc = 16384; - else - wc = wordCnt; - if ( pxw == 8 ) - { - // do REP OUTS - pio_rep_outbyte( addrDataReg, bufAddr, wc * 2L ); - } - else - if ( pxw == 32 ) - { - // do REP OUTSD - pio_rep_outdword( addrDataReg, bufAddr, wc / 2L ); - } - else - { - // do REP OUTSW - pio_rep_outword( addrDataReg, bufAddr, wc ); - } - bufAddr = bufAddr + ( wc * 2 ); - wordCnt = wordCnt - wc; - } - } - - return; -} - -//************************************************************* -// -// These functions transfer PIO DRQ data blocks through the ATA -// Data register. On an x86 these functions would use the -// REP INS and REP OUTS instructions. -// -// pio_rep_inbyte() -// pio_rep_outbyte() -// pio_rep_inword() -// pio_rep_outword() -// pio_rep_indword() -// pio_rep_outdword() -// -// These functions can be called directly but usually they -// are called by the pio_drq_block_in() and pio_drq_block_out() -// functions to perform I/O mode transfers. See the -// pio_xfer_width variable! -// -//************************************************************* - -static void pio_rep_inbyte( unsigned char addrDataReg, - unsigned char * bufAddr, - long byteCnt ) - -{ - - // Warning: Avoid calling this function with - // byteCnt > 32768 (transfers 32768 bytes). - // that bufOff is a value between 0 and 15 (0xf). - - //!!! repeat read an 8-bit register (ATA Data register when - //!!! ATA status is BSY=0 DRQ=1). For example: - - while ( byteCnt > 0 ) - { - * bufAddr = pio_inbyte( addrDataReg ); - bufAddr ++ ; - byteCnt -- ; - } -} - -//************************************************************* - -static void pio_rep_outbyte( unsigned char addrDataReg, - unsigned char * bufAddr, - long byteCnt ) - -{ - - // Warning: Avoid calling this function with - // byteCnt > 32768 (transfers 32768 bytes). - // that bufOff is a value between 0 and 15 (0xf). - - //!!! repeat write an 8-bit register (ATA Data register when - //!!! ATA status is BSY=0 DRQ=1). For example: - - while ( byteCnt > 0 ) - { - pio_outbyte( addrDataReg, * bufAddr ); - bufAddr ++ ; - byteCnt -- ; - } -} - -//************************************************************* - -static void pio_rep_inword( unsigned char addrDataReg, - unsigned char * bufAddr, - long wordCnt ) - -{ - - // Warning: Avoid calling this function with - // wordCnt > 16384 (transfers 32768 bytes). - - //!!! repeat read a 16-bit register (ATA Data register when - //!!! ATA status is BSY=0 DRQ=1). For example: - - while ( wordCnt > 0 ) - { - * (unsigned int *) bufAddr = pio_inword( addrDataReg ); - bufAddr += 2; - wordCnt -- ; - } -} - -//************************************************************* - -static void pio_rep_outword( unsigned char addrDataReg, - unsigned char * bufAddr, - long wordCnt ) - -{ - - // Warning: Avoid calling this function with - // wordCnt > 16384 (transfers 32768 bytes). - - //!!! repeat write a 16-bit register (ATA Data register when - //!!! ATA status is BSY=0 DRQ=1). For example: - - while ( wordCnt > 0 ) - { - pio_outword( addrDataReg, * (unsigned int *) bufAddr ); - bufAddr += 2; - wordCnt -- ; - } -} - -//************************************************************* - -static void pio_rep_indword( unsigned char addrDataReg, - unsigned char * bufAddr, - long dwordCnt ) - -{ - - // Warning: Avoid calling this function with - // dwordCnt > 8192 (transfers 32768 bytes). - - //!!! repeat read a 32-bit register (ATA Data register when - //!!! ATA status is BSY=0 DRQ=1). For example: - - while ( dwordCnt > 0 ) - { - * (unsigned long *) bufAddr = pio_indword( addrDataReg ); - bufAddr += 4; - dwordCnt -- ; - } -} - -//************************************************************* - -static void pio_rep_outdword( unsigned char addrDataReg, - unsigned char * bufAddr, - long dwordCnt ) - -{ - - // Warning: Avoid calling this function with - // dwordCnt > 8192 (transfers 32768 bytes). - - //!!! repeat write a 32-bit register (ATA Data register when - //!!! ATA status is BSY=0 DRQ=1). For example: - - while ( dwordCnt > 0 ) - { - pio_outdword( addrDataReg, * (unsigned long *) bufAddr ); - bufAddr += 4; - dwordCnt -- ; - } -} - - -//************************************************************* -// -// Command timing functions -// -//************************************************************** - - -static long tmr_cmd_start_time; // command start time - see the - // tmr_set_timeout() and - // tmr_chk_timeout() functions. - -//************************************************************* -// -// tmr_set_timeout() - get the command start time -// -//************************************************************** - -static void tmr_set_timeout( void ) - -{ - - // get the command start time - tmr_cmd_start_time = SYSTEM_READ_TIMER(); -} - -//************************************************************* -// -// tmr_chk_timeout() - check for command timeout. -// -// Gives non-zero return if command has timed out. -// -//************************************************************** - -static int tmr_chk_timeout( void ) - -{ - long curTime; - - // get current time - curTime = SYSTEM_READ_TIMER(); - - // timed out yet ? - if ( curTime >= ( tmr_cmd_start_time - + ( TMR_TIME_OUT * SYSTEM_TIMER_TICKS_PER_SECOND ) ) ) - return 1; // yes - - // no timeout yet - return 0; -} - -// end mindrvr.c diff --git a/repos/os/src/drivers/atapi/contrib/mindrvr.h b/repos/os/src/drivers/atapi/contrib/mindrvr.h deleted file mode 100644 index 12332e9c1..000000000 --- a/repos/os/src/drivers/atapi/contrib/mindrvr.h +++ /dev/null @@ -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 diff --git a/repos/os/src/drivers/atapi/endian.h b/repos/os/src/drivers/atapi/endian.h deleted file mode 100644 index 25477777a..000000000 --- a/repos/os/src/drivers/atapi/endian.h +++ /dev/null @@ -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 -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_ */ - diff --git a/repos/os/src/drivers/atapi/io.cc b/repos/os/src/drivers/atapi/io.cc deleted file mode 100644 index 5cf8603d6..000000000 --- a/repos/os/src/drivers/atapi/io.cc +++ /dev/null @@ -1,256 +0,0 @@ -/* - * \brief I/O back-end of the mindrvr driver - * \author Sebastian Sumpf - * \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 -#include -#include -#include -#include - -#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; -} diff --git a/repos/os/src/drivers/atapi/io.h b/repos/os/src/drivers/atapi/io.h deleted file mode 100644 index 0ea43e716..000000000 --- a/repos/os/src/drivers/atapi/io.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * \brief I/O back-end of the mindrvr driver - * \author Sebastian Sumpf - * \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 - -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_ */ diff --git a/repos/os/src/drivers/atapi/main.cc b/repos/os/src/drivers/atapi/main.cc deleted file mode 100644 index a878930a3..000000000 --- a/repos/os/src/drivers/atapi/main.cc +++ /dev/null @@ -1,87 +0,0 @@ -/* - * \brief Block interface for ATA driver - * \author Stefan Kalkowski - * \author Sebastian Sumpf - * \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 -#include - -/* 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(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); } -} diff --git a/repos/os/src/drivers/atapi/pio.h b/repos/os/src/drivers/atapi/pio.h deleted file mode 100644 index 0f6c8ea62..000000000 --- a/repos/os/src/drivers/atapi/pio.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * \brief I/0 interface used by MinATA driver - * \author Sebastian Sumpf - * \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_ */ diff --git a/repos/os/src/drivers/atapi/target.mk b/repos/os/src/drivers/atapi/target.mk deleted file mode 100644 index 9aaac7e3e..000000000 --- a/repos/os/src/drivers/atapi/target.mk +++ /dev/null @@ -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 diff --git a/repos/ports/run/seoul-auto.run b/repos/ports/run/seoul-auto.run index 38be800a8..0ae3c5a3b 100644 --- a/repos/ports/run/seoul-auto.run +++ b/repos/ports/run/seoul-auto.run @@ -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 diff --git a/repos/ports/run/seoul-disc.run b/repos/ports/run/seoul-disc.run index e9b0cd157..b0ba01483 100644 --- a/repos/ports/run/seoul-disc.run +++ b/repos/ports/run/seoul-disc.run @@ -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" } diff --git a/repos/ports/run/seoul-fancy.run b/repos/ports/run/seoul-fancy.run index c9b0960d6..973cd4864 100644 --- a/repos/ports/run/seoul-fancy.run +++ b/repos/ports/run/seoul-fancy.run @@ -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 diff --git a/repos/ports/run/seoul-genode.run b/repos/ports/run/seoul-genode.run index 19588423b..e96b2c36f 100644 --- a/repos/ports/run/seoul-genode.run +++ b/repos/ports/run/seoul-genode.run @@ -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 diff --git a/repos/ports/run/seoul-kernelbuild.run b/repos/ports/run/seoul-kernelbuild.run index f29789c0d..e3bdd02b7 100644 --- a/repos/ports/run/seoul-kernelbuild.run +++ b/repos/ports/run/seoul-kernelbuild.run @@ -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 diff --git a/repos/ports/run/seoul-net.run b/repos/ports/run/seoul-net.run index fb5688183..e913ac81c 100644 --- a/repos/ports/run/seoul-net.run +++ b/repos/ports/run/seoul-net.run @@ -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 diff --git a/repos/ports/run/seoul.inc b/repos/ports/run/seoul.inc index 4a4b45093..190cf4217 100644 --- a/repos/ports/run/seoul.inc +++ b/repos/ports/run/seoul.inc @@ -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 { } -append_if $use_block_ide config { - - - - - } - append_if $use_genode_iso config { @@ -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