[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH v3 3/5] cdi/ata: ATAPI-Unterstuetzung (Janosch Graef)
+ cdi/ata: ATAPI-Unterstuetzung
---
src/modules/cdi/ata/ata.c | 172 +---------------------------------
src/modules/cdi/ata/atapi.c | 96 ++++++++++++++++---
src/modules/cdi/ata/device.c | 58 +++++++-----
src/modules/cdi/ata/device.h | 205 +++++++++++++++++++++++++++++++++++++++--
src/modules/cdi/ata/main.c | 48 ++++++----
src/modules/cdi/ata/request.c | 71 ++++++++++----
6 files changed, 394 insertions(+), 256 deletions(-)
diff --git a/src/modules/cdi/ata/ata.c b/src/modules/cdi/ata/ata.c
index d18089f..14e777b 100644
--- a/src/modules/cdi/ata/ata.c
+++ b/src/modules/cdi/ata/ata.c
@@ -44,172 +44,6 @@
#include "device.h"
/**
- * Resultat beim IDENTIFY DEVICE Befehl
- */
-struct ata_identfiy_data {
- struct {
- uint8_t : 7;
- uint8_t removable : 1;
- uint8_t : 7;
- uint8_t ata : 1;
- } __attribute__((packed)) general_config;
-
- uint16_t log_cyl; // Veraltet
- uint16_t : 16;
- uint16_t log_heads; // Veraltet
- uint16_t : 16;
- uint16_t : 16;
- uint16_t log_spt; // Veraltet
- uint16_t : 16;
- // 8
- uint16_t : 16;
- uint16_t : 16;
- char serial_number[20];
- // 20
- uint16_t : 16;
- uint16_t : 16;
- uint16_t : 16;
- char firmware_revision[8];
- // 27
- char model_number[40];
- uint8_t : 8; // Immer 0x80
- uint8_t max_sec_per_irq;
- // 48
- uint16_t : 16;
- struct {
- uint16_t : 8;
- uint8_t dma : 1;
- uint8_t lba : 1;
- uint8_t iordy_disabled : 1;
- uint8_t irdy_supported : 1;
- uint8_t : 1;
- uint8_t : 1; // Irgendwas mit Standbytimer
- uint8_t : 2;
- } __attribute__((packed)) capabilities;
- uint16_t : 16; // Noch ein paar Faehigkeiten,
- // die wir aber sicher nicht
- // brauchen
- uint8_t : 8;
- uint8_t pio_mode_number;
- uint16_t : 16;
- struct {
- uint8_t current_chs : 1; // Words 54-56
- uint8_t transfer_settings : 1; // Words 64-70
- uint8_t ultra_dma : 1; // Word 88
- uint16_t : 13;
- } __attribute__((packed)) valid_words;
- uint16_t cur_log_cyl; // Veraltet
- uint16_t cur_log_heads; // Veraltet
- // 56
- uint16_t cur_log_spt; // Veraltet
- uint16_t chs_capacity[2]; // Veraltet
- struct {
- uint8_t cur_sec_per_int : 8;
- uint8_t setting_valid : 1;
- uint8_t : 7;
- } __attribute__((packed)) multi_sector;
- uint32_t lba_sector_count; // LBA28
- uint16_t : 16;
- struct {
- uint8_t : 1;
- uint8_t mode0_supported : 1;
- uint8_t mode1_supported : 1;
- uint8_t mode2_supported : 1;
- uint8_t : 4;
- uint8_t mode0_selected : 1;
- uint8_t mode1_selected : 1;
- uint8_t mode2_selected : 1;
- uint8_t : 5;
- } __attribute__((packed)) multiword_dma;
- // 64
- uint8_t pio_modes_supported;
- uint8_t : 8;
- // Multiword dma Zeiten
- uint16_t mwd_time1;
- uint16_t mwd_time2;
- uint16_t mwd_time3;
- uint16_t mwd_time4;
- uint16_t : 16;
- uint16_t : 16;
- uint16_t : 16;
- // 72
- uint16_t : 16;
- uint16_t : 16;
- uint16_t : 16;
- struct {
- uint8_t max_depth : 5;
- uint16_t : 11;
- } __attribute__((packed)) queue_depth;
- uint16_t : 16;
- uint16_t : 16;
- uint16_t : 16;
- uint16_t : 16;
- // 80
- union {
- uint16_t raw;
- struct {
- uint8_t : 1;
- uint8_t ata1 : 1;
- uint8_t ata2 : 1;
- uint8_t ata3 : 1;
- uint8_t ata4 : 1;
- uint8_t ata5 : 1;
- uint8_t ata6 : 1;
- uint8_t ata7 : 1;
- uint16_t : 8;
- } __attribute__((packed)) bits;
- } major_version;
- uint16_t minor_version;
-
- union {
- uint16_t raw[2];
- struct {
- // Word 82
- uint8_t smart : 1;
- uint8_t security_mode : 1;
- uint8_t removable_media : 1;
- uint8_t power_management : 1;
- uint8_t packet : 1;
- uint8_t write_cache : 1;
- uint8_t look_ahead : 1;
- uint8_t release_int : 1;
- uint8_t service_int : 1;
- uint8_t device_reset : 1;
- uint8_t hpa : 1; // Host protected area
- uint8_t : 1;
- uint8_t write_buffer : 1;
- uint8_t read_buffer : 1;
- uint8_t nop : 1;
- uint8_t : 1;
-
- // Word 83
- uint8_t download_microcode : 1;
- uint8_t rw_dma_queued : 1;
- uint8_t cfa : 1;
- uint8_t apm : 1; // Advanced power management
- uint8_t removable_media_sn : 1; // R. Media Status notification
- uint8_t power_up_standby : 1;
- uint8_t set_features_spinup : 1;
- uint8_t : 1;
- uint8_t set_max_security : 1;
- uint8_t auto_acoustic_mngmnt: 1; // Automatic acoustic management
- uint8_t lba48 : 1;
- uint8_t dev_config_overlay : 1;
- uint8_t flush_cache : 1;
- uint8_t flush_cache_ext : 1;
- uint8_t : 2;
- } __attribute__((packed)) bits;
- } features_support;
- // 83
- uint16_t todo[17];
- // 100
- uint64_t max_lba48_address;
- // 107
- uint16_t todo2[153];
-} __attribute__((packed));
-
-
-/**
* ATA-Geraet identifizieren
*
* @return 0 Wenn das Geraet erfolgreich identifiziert wurde, != 0 sonst
@@ -245,17 +79,17 @@ int ata_drv_identify(struct ata_device* dev)
// Pruefen, welche LBA-Modi dabei sind
if (id.features_support.bits.lba48) {
dev->lba48 = 1;
- dev->storage.block_count = id.max_lba48_address;
+ dev->dev.storage.block_count = id.max_lba48_address;
}
if (id.capabilities.lba) {
dev->lba28 = 1;
- dev->storage.block_count = id.lba_sector_count;
+ dev->dev.storage.block_count = id.lba_sector_count;
}
// Wenn keiner der LBA-Modi unterstuetzt wird, muss abgebrochen werden, da
// CHS noch nicht implementiert ist.
if (!dev->lba48 && !dev->lba28) {
- printf("ata: Geraet unterstuetzt nur CHS.\n");
+ DEBUG("Geraet unterstuetzt nur CHS.\n");
return 0;
}
diff --git a/src/modules/cdi/ata/atapi.c b/src/modules/cdi/ata/atapi.c
index a596edb..ecff315 100644
--- a/src/modules/cdi/ata/atapi.c
+++ b/src/modules/cdi/ata/atapi.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2007 The tyndur Project. All rights reserved.
*
* This code is derived from software contributed to the tyndur Project
@@ -20,16 +20,16 @@
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@@ -40,6 +40,7 @@
#include "cdi/storage.h"
#include "cdi/misc.h"
#include "cdi/io.h"
+#include "cdi/scsi.h"
#include "device.h"
@@ -51,7 +52,7 @@
*/
int atapi_drv_identify(struct ata_device* dev)
{
- uint8_t buffer[ATA_SECTOR_SIZE];
+ struct ata_identfiy_data id;
// Request vorbereiten
struct ata_request request = {
@@ -66,22 +67,87 @@ int atapi_drv_identify(struct ata_device* dev)
.registers.ata.command = IDENTIFY_PACKET_DEVICE,
.block_count = 1,
.block_size = ATA_SECTOR_SIZE,
- .buffer = buffer,
+ .buffer = &id,
.error = 0
};
-
+
// Request starten
if (!ata_request(&request)) {
// Pech gehabt
return 0;
}
-
+
// Es handelt sich um ein ATAPI-Geraet
dev->atapi = 1;
- // TODO: Informationen verarbeiten
-
return 1;
}
+void atapi_init_device(struct cdi_device* device)
+{
+ struct cdi_scsi_device* scsi = (struct cdi_scsi_device*) device;
+
+ scsi->type = CDI_STORAGE;
+ cdi_scsi_device_init(scsi);
+}
+
+void atapi_remove_device(struct cdi_device* device)
+{
+
+}
+
+int atapi_request(struct cdi_scsi_device* scsi,struct cdi_scsi_packet* packet)
+{
+ struct ata_device *dev = (struct ata_device*)scsi;
+ struct ata_request request = {
+ .dev = dev,
+ .protocol = PIO,
+ .flags = {
+ .direction = WRITE,
+ .poll = 1,
+ .ata = 0, // Ich brauch nur ATA-Befehle (Packet)
+ .lba = 0 // Der Kommentar in device.h ist kein deutscher Satz!
+ },
+ .registers = {
+ .ata = {
+ .command = PACKET,
+ .lba = 0x00FFFF00 // Sonst hat bei mir nachher nichts in den
+ // LBA-Registern dringestanden und die
+ // braucht man ja fuer die Paketgroesse.
+ }
+ },
+ .block_count = 1,
+ .block_size = packet->cmdsize,
+ .blocks_done = 0,
+ .buffer = packet->command,
+ .error = 0
+ };
+
+ if (ata_request(&request))
+ {
+ struct ata_request rw_request = {
+ .dev = dev,
+ .flags = {
+ .poll = 1,
+ .lba = 1,
+ .ata = 1
+ },
+ .block_count = 1,
+ .block_size = packet->bufsize,
+ .blocks_done = 0,
+ .buffer = packet->buffer,
+ .error = 0
+ };
+
+ // Lesen bzw. Schreiben der Daten
+ // TODO: DMA
+ if (packet->direction==CDI_SCSI_READ) ata_protocol_pio_in(&rw_request);
+ else if (packet->direction==CDI_SCSI_WRITE) ata_protocol_pio_in(&rw_request);
+
+ // Sense Key zurueck
+ return (ata_reg_inb(dev->controller,REG_ERROR)>>4);
+ }
+
+ return 0xB;
+}
diff --git a/src/modules/cdi/ata/device.c b/src/modules/cdi/ata/device.c
index fcedeae..4bf4a14 100644
--- a/src/modules/cdi/ata/device.c
+++ b/src/modules/cdi/ata/device.c
@@ -40,12 +40,11 @@
#include "cdi/storage.h"
#include "cdi/misc.h"
#include "cdi/io.h"
+#include "cdi/scsi.h"
#include "device.h"
#include "libpartition.h"
-#define MAX(a, b) (a > b ? a : b)
-
// IRQ-Handler
static inline void ata_controller_irq(struct cdi_device* dev);
@@ -76,6 +75,8 @@ static int ata_bus_floating(struct ata_controller* controller)
ata_reg_outb(controller, REG_DEVICE, DEVICE_DEV(1));
ATA_DELAY(controller);
status = ata_reg_inb(controller, REG_STATUS);
+
+ // Wenn alle Bits gesetzt sind, ist der Bus floating
return (status == 0xFF);
}
@@ -182,13 +183,13 @@ void ata_parse_partitions(struct ata_device* dev)
// Die Partitionstabelle liegt im MBR
if (!dev->read_sectors(dev, 0, 1, mbr)) {
- printf("ata: Fehler beim Einlesen der Partitionstabelle");
+ DEBUG("Fehler beim Einlesen der Partitionstabelle");
return;
}
// Partitionstabelle Verarbeiten
if (!partition_table_fill(&partition_table, mbr)) {
- printf("ata: Fehler beim Verarbeiten der Partitionstabelle");
+ DEBUG("Fehler beim Verarbeiten der Partitionstabelle");
return;
}
@@ -197,23 +198,23 @@ void ata_parse_partitions(struct ata_device* dev)
if (partition_table.entries[i].used) {
// Erweiterter Eintrag => ueberspringen
if (partition_table.entries[i].type == PARTITION_TYPE_EXTENDED) {
- printf("ata: TODO Erweiterte Partitionstabelleneintraege\n");
+ DEBUG("TODO Erweiterte Partitionstabelleneintraege\n");
continue;
}
struct ata_partition* partition = malloc(sizeof(*partition));
- partition->dev = dev;
+ partition->realdev = dev;
partition->null = NULL;
partition->start = partition_table.entries[i].start;
- partition->storage.block_size = ATA_SECTOR_SIZE;
- partition->storage.block_count = partition_table.entries[i].size;
- printf("ata: Partition von %d bis %d\n", partition->start, partition->storage.block_count + partition->start - 1);
- asprintf((char**) &(partition->storage.dev.name), "ata%01d%01d_p%01d",
+ partition->dev.storage.block_size = ATA_SECTOR_SIZE;
+ partition->dev.storage.block_count = partition_table.entries[i].size;
+ DEBUG("Partition von %d bis %d\n", partition->start, partition->dev.storage.block_count + partition->start - 1);
+ asprintf((char**) &(partition->dev.storage.dev.name), "ata%01d%01d_p%01d",
(uint32_t) dev->controller->id, dev->id, cdi_list_size(dev->
partition_list));
// Geraet registrieren
- cdi_list_push(dev->controller->driver->drv.devices, partition);
+ cdi_list_push(dev->controller->storage->drv.devices, partition);
// An Partitionsliste fuer das aktuelle Geraet anhaengen
cdi_list_push(dev->partition_list, partition);
@@ -233,11 +234,11 @@ void ata_init_controller(struct ata_controller* controller)
// Ports registrieren
if (cdi_ioports_alloc(controller->port_cmd_base, 8) != 0) {
- printf("ata: Fehler beim allozieren der I/O-Ports\n");
+ DEBUG("Fehler beim allozieren der I/O-Ports\n");
return;
}
if (cdi_ioports_alloc(controller->port_ctl_base, 1) != 0) {
- printf("ata: Fehler beim allozieren der I/O-Ports\n");
+ DEBUG("Fehler beim allozieren der I/O-Ports\n");
cdi_ioports_free(controller->port_cmd_base, 8);
return;
}
@@ -267,7 +268,7 @@ void ata_init_controller(struct ata_controller* controller)
// Jetzt pruefen wir ob der Bus leer ist (mehr dazu bei ata_bus_floating).
if (ata_bus_floating(controller)) {
- printf("ata: Floating Bus %d\n", controller->id);
+ DEBUG("Floating Bus %d\n", controller->id);
return;
}
@@ -275,7 +276,7 @@ void ata_init_controller(struct ata_controller* controller)
// darauf geachtet werden, dass der Master auch antworten muss, wenn zwar
// der Slave ausgewaehlt ist, aber nicht existiert.
if (!ata_bus_responsive_drv(controller)) {
- printf("ata: No responsive drive on Bus %d\n", controller->id);
+ DEBUG("No responsive drive on Bus %d\n", controller->id);
return;
}
@@ -285,30 +286,39 @@ void ata_init_controller(struct ata_controller* controller)
struct ata_device* dev = malloc(sizeof(*dev));
dev->controller = controller;
dev->id = i;
- dev->storage.block_size = ATA_SECTOR_SIZE;
dev->partition_list = cdi_list_create();
if (ata_drv_identify(dev)) {
- printf("Bus %d Device %d: ATAPI=%d\n", (uint32_t) controller->id, i, dev->atapi);
+ DEBUG("Bus %d Device %d: ATAPI=%d\n", (uint32_t) controller->id, i, dev->atapi);
+
+#ifdef ATAPI_ENABLE
if (dev->atapi == 0) {
+#endif
+ dev->dev.storage.block_size = ATA_SECTOR_SIZE;
+
// Handler setzen
dev->read_sectors = ata_drv_read_sectors;
dev->write_sectors = ata_drv_write_sectors;
// Name setzen
- asprintf((char**) &(dev->storage.dev.name), "ata%01d%01d",
+ asprintf((char**) &(dev->dev.storage.dev.name), "ata%01d%01d",
(uint32_t) controller->id, i);
// Partitionen parsen
ata_parse_partitions(dev);
+
+ // Geraet registrieren
+ cdi_list_push(controller->storage->drv.devices, dev);
+#ifdef ATAPI_ENABLE
} else {
// Name setzen
- asprintf((char**) &(dev->storage.dev.name), "atapi%01d%01d",
+ asprintf((char**) &(dev->dev.scsi.dev.name),"atapi%01d%01d",
(uint32_t) controller->id, i);
- }
// Geraet registrieren
- cdi_list_push(controller->driver->drv.devices, dev);
+ cdi_list_push(controller->scsi->drv.devices, dev);
+ }
+#endif
} else {
free(dev);
}
@@ -324,7 +334,7 @@ void ata_remove_controller(struct ata_controller* controller)
void ata_init_device(struct cdi_device* device)
{
struct ata_device* dev = (struct ata_device*) device;
- cdi_storage_device_init(&dev->storage);
+ cdi_storage_device_init(&dev->dev.storage);
}
void ata_remove_device(struct cdi_device* device)
@@ -346,7 +356,7 @@ int ata_read_blocks(struct cdi_storage_device* device, uint64_t block,
// Partition
if (dev->controller == NULL) {
partition = (struct ata_partition*) dev;
- dev = partition->dev;
+ dev = partition->realdev;
}
// Natuerlich nur ausfuehren wenn ein Handler eingetragen ist
@@ -376,7 +386,7 @@ int ata_write_blocks(struct cdi_storage_device* device, uint64_t block,
// Partition
if (dev->controller == NULL) {
partition = (struct ata_partition*) dev;
- dev = partition->dev;
+ dev = partition->realdev;
}
// Natuerlich nur ausfuehren wenn ein Handler eingetragen ist
diff --git a/src/modules/cdi/ata/device.h b/src/modules/cdi/ata/device.h
index be1e86b..140f037 100644
--- a/src/modules/cdi/ata/device.h
+++ b/src/modules/cdi/ata/device.h
@@ -36,12 +36,17 @@
#ifndef _ATA_DEVICE_H_
#define _ATA_DEVICE_H_
+#undef DEBUG_ENABLE
+
#include <stdint.h>
#include "cdi.h"
#include "cdi/storage.h"
#include "cdi/io.h"
#include "cdi/lists.h"
+#include "cdi/scsi.h"
+
+#define ATAPI_ENABLE
#define ATA_PRIMARY_CMD_BASE 0x1F0
#define ATA_PRIMARY_CTL_BASE 0x3F6
@@ -105,20 +110,198 @@
#define CONTROL_SRST (1 << 2)
#define CONTROL_NIEN (1 << 1)
+// Debug
+#ifdef DEBUG_ENABLE
+ #define DEBUG(fmt, ...) printf("ata: " fmt, __VA_ARGS__)
+#else
+ #define DEBUG(...)
+#endif
+
+/**
+ * Resultat beim IDENTIFY DEVICE Befehl
+ */
+struct ata_identfiy_data {
+ struct {
+ uint8_t : 7;
+ uint8_t removable : 1;
+ uint8_t : 7;
+ uint8_t ata : 1;
+ } __attribute__((packed)) general_config;
+
+ uint16_t log_cyl; // Veraltet
+ uint16_t : 16;
+ uint16_t log_heads; // Veraltet
+ uint16_t : 16;
+ uint16_t : 16;
+ uint16_t log_spt; // Veraltet
+ uint16_t : 16;
+ // 8
+ uint16_t : 16;
+ uint16_t : 16;
+ char serial_number[20];
+ // 20
+ uint16_t : 16;
+ uint16_t : 16;
+ uint16_t : 16;
+ char firmware_revision[8];
+ // 27
+ char model_number[40];
+ uint8_t : 8; // Immer 0x80
+ uint8_t max_sec_per_irq;
+ // 48
+ uint16_t : 16;
+ struct {
+ uint16_t : 8;
+ uint8_t dma : 1;
+ uint8_t lba : 1;
+ uint8_t iordy_disabled : 1;
+ uint8_t irdy_supported : 1;
+ uint8_t : 1;
+ uint8_t : 1; // Irgendwas mit Standbytimer
+ uint8_t : 2;
+ } __attribute__((packed)) capabilities;
+ uint16_t : 16; // Noch ein paar Faehigkeiten,
+ // die wir aber sicher nicht
+ // brauchen
+ uint8_t : 8;
+ uint8_t pio_mode_number;
+ uint16_t : 16;
+ struct {
+ uint8_t current_chs : 1; // Words 54-56
+ uint8_t transfer_settings : 1; // Words 64-70
+ uint8_t ultra_dma : 1; // Word 88
+ uint16_t : 13;
+ } __attribute__((packed)) valid_words;
+ uint16_t cur_log_cyl; // Veraltet
+ uint16_t cur_log_heads; // Veraltet
+ // 56
+ uint16_t cur_log_spt; // Veraltet
+ uint16_t chs_capacity[2]; // Veraltet
+ struct {
+ uint8_t cur_sec_per_int : 8;
+ uint8_t setting_valid : 1;
+ uint8_t : 7;
+ } __attribute__((packed)) multi_sector;
+ uint32_t lba_sector_count; // LBA28
+ uint16_t : 16;
+ struct {
+ uint8_t : 1;
+ uint8_t mode0_supported : 1;
+ uint8_t mode1_supported : 1;
+ uint8_t mode2_supported : 1;
+ uint8_t : 4;
+ uint8_t mode0_selected : 1;
+ uint8_t mode1_selected : 1;
+ uint8_t mode2_selected : 1;
+ uint8_t : 5;
+ } __attribute__((packed)) multiword_dma;
+ // 64
+ uint8_t pio_modes_supported;
+ uint8_t : 8;
+ // Multiword dma Zeiten
+ uint16_t mwd_time1;
+ uint16_t mwd_time2;
+ uint16_t mwd_time3;
+ uint16_t mwd_time4;
+ uint16_t : 16;
+ uint16_t : 16;
+ uint16_t : 16;
+ // 72
+ uint16_t : 16;
+ uint16_t : 16;
+ uint16_t : 16;
+ struct {
+ uint8_t max_depth : 5;
+ uint16_t : 11;
+ } __attribute__((packed)) queue_depth;
+ uint16_t : 16;
+ uint16_t : 16;
+ uint16_t : 16;
+ uint16_t : 16;
+ // 80
+ union {
+ uint16_t raw;
+ struct {
+ uint8_t : 1;
+ uint8_t ata1 : 1;
+ uint8_t ata2 : 1;
+ uint8_t ata3 : 1;
+ uint8_t ata4 : 1;
+ uint8_t ata5 : 1;
+ uint8_t ata6 : 1;
+ uint8_t ata7 : 1;
+ uint16_t : 8;
+ } __attribute__((packed)) bits;
+ } major_version;
+ uint16_t minor_version;
+ union {
+ uint16_t raw[2];
+ struct {
+ // Word 82
+ uint8_t smart : 1;
+ uint8_t security_mode : 1;
+ uint8_t removable_media : 1;
+ uint8_t power_management : 1;
+ uint8_t packet : 1;
+ uint8_t write_cache : 1;
+ uint8_t look_ahead : 1;
+ uint8_t release_int : 1;
+ uint8_t service_int : 1;
+ uint8_t device_reset : 1;
+ uint8_t hpa : 1; // Host protected area
+ uint8_t : 1;
+ uint8_t write_buffer : 1;
+ uint8_t read_buffer : 1;
+ uint8_t nop : 1;
+ uint8_t : 1;
+
+ // Word 83
+ uint8_t download_microcode : 1;
+ uint8_t rw_dma_queued : 1;
+ uint8_t cfa : 1;
+ uint8_t apm : 1; // Advanced power management
+ uint8_t removable_media_sn : 1; // R. Media Status notification
+ uint8_t power_up_standby : 1;
+ uint8_t set_features_spinup : 1;
+ uint8_t : 1;
+ uint8_t set_max_security : 1;
+ uint8_t auto_acoustic_mngmnt: 1; // Automatic acoustic management
+ uint8_t lba48 : 1;
+ uint8_t dev_config_overlay : 1;
+ uint8_t flush_cache : 1;
+ uint8_t flush_cache_ext : 1;
+ uint8_t : 2;
+ } __attribute__((packed)) bits;
+ } features_support;
+ // 83
+ uint16_t todo[17];
+ // 100
+ uint64_t max_lba48_address;
+ // 107
+ uint16_t todo2[153];
+} __attribute__((packed));
struct ata_partition {
- struct cdi_storage_device storage;
+ union {
+ struct cdi_storage_device storage;
+ struct cdi_scsi_device scsi;
+ } dev;
+
// Muss auf NULL gesetzt werden
void* null;
- struct ata_device* dev;
+ struct ata_device* realdev;
// Startsektor
uint32_t start;
};
struct ata_device {
- struct cdi_storage_device storage;
+ union {
+ struct cdi_storage_device storage;
+ struct cdi_scsi_device scsi;
+ } dev;
+
// In der Partitionstruktur ist dieses Feld null, um Partitionen erkennen
// zu koennen.
struct ata_controller* controller;
@@ -129,6 +312,7 @@ struct ata_device {
uint8_t id;
// 1 wenn es sich um ein ATAPI-Gerat handelt, 0 sonst
+ // Bei ATAPI-Geraeten wir im union dev scsi verwendet, ansonsten storage
uint8_t atapi;
// 1 Wenn das Geraet lba48 unterstuetzt
@@ -145,7 +329,8 @@ struct ata_device {
};
struct ata_controller {
- struct cdi_storage_driver* driver;
+ struct cdi_storage_driver *storage;
+ struct cdi_scsi_driver *scsi;
uint8_t id;
uint16_t port_cmd_base;
@@ -191,16 +376,13 @@ struct ata_request {
enum {
IDENTIFY_DEVICE = 0xEC,
IDENTIFY_PACKET_DEVICE = 0xA1,
+ PACKET = 0xA0,
READ_SECTORS = 0x20,
WRITE_SECTORS = 0x30
} command;
uint8_t count;
uint64_t lba;
} ata;
-
- // Parameter fuer ATAPI-Operationen
- struct {
- } atapi;
} registers;
// Anzahl der Blocks die uebertragen werden sollen
@@ -225,7 +407,6 @@ struct ata_request {
} error;
};
-
void ata_init_controller(struct ata_controller* controller);
void ata_remove_controller(struct ata_controller* controller);
void ata_init_device(struct cdi_device* device);
@@ -239,6 +420,9 @@ int ata_write_blocks(struct cdi_storage_device* device, uint64_t block,
// Einen ATA-Request absenden und ausfuehren
int ata_request(struct ata_request* request);
+int ata_protocol_pio_out(struct ata_request* request);
+int ata_protocol_pio_in(struct ata_request* request);
+
// ATA-Funktionen
int ata_drv_identify(struct ata_device* dev);
int ata_drv_read_sectors(struct ata_device* dev, uint64_t start, size_t count,
@@ -248,6 +432,9 @@ int ata_drv_write_sectors(struct ata_device* dev, uint64_t start, size_t count,
// ATAPI-Funktionen
int atapi_drv_identify(struct ata_device* dev);
+void atapi_init_device(struct cdi_device* device);
+void atapi_remove_device(struct cdi_device* device);
+int atapi_request(struct cdi_scsi_device* dev,struct cdi_scsi_packet* packet);
// Auf einen IRQ warten
int ata_wait_irq(struct ata_controller* controller, uint32_t timeout);
diff --git a/src/modules/cdi/ata/main.c b/src/modules/cdi/ata/main.c
index f7a94cf..750f7b2 100644
--- a/src/modules/cdi/ata/main.c
+++ b/src/modules/cdi/ata/main.c
@@ -38,21 +38,19 @@
#include <stdio.h>
#include "cdi/storage.h"
-#include "cdi/pci.h"
#include "cdi/lists.h"
#include "device.h"
-struct ata_driver {
- struct cdi_storage_driver storage;
-};
-
-static struct ata_driver driver;
-static const char* driver_name = "ata";
+static struct cdi_storage_driver driver_storage;
+static struct cdi_scsi_driver driver_scsi;
+static const char* driver_storage_name = "ata";
+static const char* driver_scsi_name = "atapi";
static cdi_list_t controller_list = NULL;
static void ata_driver_init(void);
static void ata_driver_destroy(struct cdi_driver* driver);
+static void atapi_driver_destroy(struct cdi_driver* driver);
#ifdef CDI_STANDALONE
int main(void)
@@ -62,7 +60,8 @@ int init_ata(void)
{
cdi_init();
ata_driver_init();
- cdi_storage_driver_register((struct cdi_storage_driver*) &driver);
+ cdi_storage_driver_register((struct cdi_storage_driver*) &driver_storage);
+ cdi_scsi_driver_register((struct cdi_scsi_driver*) &driver_scsi);
#ifdef CDI_STANDALONE
cdi_run_drivers();
@@ -79,29 +78,36 @@ static void ata_driver_init()
struct ata_controller* controller;
// Konstruktor der Vaterklasse
- cdi_storage_driver_init((struct cdi_storage_driver*) &driver);
+ cdi_storage_driver_init((struct cdi_storage_driver*) &driver_storage);
+ cdi_scsi_driver_init((struct cdi_scsi_driver*) &driver_scsi);
// Namen setzen
- driver.storage.drv.name = driver_name;
+ driver_storage.drv.name = driver_storage_name;
+ driver_scsi.drv.name = driver_scsi_name;
// Funktionspointer initialisieren
- driver.storage.drv.destroy = ata_driver_destroy;
- driver.storage.drv.init_device = ata_init_device;
- driver.storage.drv.remove_device = ata_remove_device;
- driver.storage.read_blocks = ata_read_blocks;
- driver.storage.write_blocks = ata_write_blocks;
+ driver_storage.drv.destroy = ata_driver_destroy;
+ driver_storage.drv.init_device = ata_init_device;
+ driver_storage.drv.remove_device = ata_remove_device;
+ driver_storage.read_blocks = ata_read_blocks;
+ driver_storage.write_blocks = ata_write_blocks;
+
+ driver_scsi.drv.destroy = atapi_driver_destroy;
+ driver_scsi.drv.init_device = atapi_init_device;
+ driver_scsi.drv.remove_device = atapi_remove_device;
+ driver_scsi.request = atapi_request;
// Liste mit Controllern initialisieren
controller_list = cdi_list_create();
-
// Primaeren Controller vorbereiten
controller = malloc(sizeof(*controller));
controller->port_cmd_base = ATA_PRIMARY_CMD_BASE;
controller->port_ctl_base = ATA_PRIMARY_CTL_BASE;
controller->irq = ATA_PRIMARY_IRQ;
controller->id = 0;
- controller->driver = (struct cdi_storage_driver*) &driver;
+ controller->storage = (struct cdi_storage_driver*) &driver_storage;
+ controller->scsi = (struct cdi_scsi_driver*) &driver_scsi;
ata_init_controller(controller);
cdi_list_push(controller_list, controller);
@@ -111,7 +117,8 @@ static void ata_driver_init()
controller->port_ctl_base = ATA_SECONDARY_CTL_BASE;
controller->irq = ATA_SECONDARY_IRQ;
controller->id = 1;
- controller->driver = (struct cdi_storage_driver*) &driver;
+ controller->storage = (struct cdi_storage_driver*) &driver_storage;
+ controller->scsi = (struct cdi_scsi_driver*) &driver_scsi;
ata_init_controller(controller);
cdi_list_push(controller_list, controller);
}
@@ -125,3 +132,8 @@ static void ata_driver_destroy(struct cdi_driver* driver)
// TODO Alle Karten deinitialisieren
}
+
+static void atapi_driver_destroy(struct cdi_driver* driver)
+{
+ cdi_scsi_driver_destroy((struct cdi_scsi_driver*) driver);
+}
diff --git a/src/modules/cdi/ata/request.c b/src/modules/cdi/ata/request.c
index 9bd91a5..5071048 100644
--- a/src/modules/cdi/ata/request.c
+++ b/src/modules/cdi/ata/request.c
@@ -162,7 +162,7 @@ static int ata_protocol_non_data(struct ata_request* request)
// Auf IRQ warten
if (ata_wait_irq(ctrl, ATA_IRQ_TIMEOUT)) {
request->error = IRQ_TIMEOUT;
- printf("ata: non_data IRQ-Timeout\n");
+ DEBUG("non_data IRQ-Timeout\n");
return 0;
}
@@ -192,10 +192,11 @@ static int ata_protocol_non_data(struct ata_request* request)
* sollen.
* Nach Kapitel 11 in der ATA7-Spec
*/
-static int ata_protocol_pio_in(struct ata_request* request)
+int ata_protocol_pio_in(struct ata_request* request)
{
struct ata_device* dev = request->dev;
struct ata_controller* ctrl = dev->controller;
+ size_t packet_size = 0;
// Aktueller Status im Protokol
enum {
@@ -217,10 +218,16 @@ static int ata_protocol_pio_in(struct ata_request* request)
// Auf IRQ warten
if (ata_wait_irq(ctrl, ATA_IRQ_TIMEOUT)) {
request->error = IRQ_TIMEOUT;
- printf("ata: pio_in IRQ-Timeout\n");
+ DEBUG("pio_in IRQ-Timeout\n");
return 0;
}
+ if (request->flags.ata && packet_size==0) // ATAPI
+ {
+ // Paketgroesse einlesen, da sonst unendlich viel gelesen wird
+ packet_size = ata_reg_inb(ctrl,REG_LBA_MID)|(ata_reg_inb(ctrl,REG_LBA_HIG)<<8);
+ }
+
// Jetzt muss der Status ueberprueft werden
state = CHECK_STATUS;
break;
@@ -233,7 +240,7 @@ static int ata_protocol_pio_in(struct ata_request* request)
// gelaufen.
if ((status & (STATUS_BSY | STATUS_DRQ)) == 0) {
// TODO: Fehlerbehandlung
- printf("ata: pio_in unerwarteter Status: 0x%x\n", status);
+ DEBUG("pio_in unerwarteter Status: 0x%x\n", status);
return 0;
} else if ((status & STATUS_BSY) == STATUS_BSY) {
// Wenn das Busy-Flag gesetzt ist, muss gewartet werden,
@@ -252,7 +259,6 @@ static int ata_protocol_pio_in(struct ata_request* request)
uint16_t* buffer = (uint16_t*) (request->buffer + (request->
blocks_done * request->block_size));
- // Einen Block einlesen
ata_insw(ata_reg_base(ctrl, REG_DATA) + REG_DATA, buffer,
request->block_size / 2);
@@ -260,10 +266,17 @@ static int ata_protocol_pio_in(struct ata_request* request)
request->blocks_done++;
// Naechste Transaktion ausfindig machen
- if (request->blocks_done >= request->block_count) {
+ if (!request->flags.ata &&
+ request->blocks_done >= request->block_count) {
// Wenn alle Blocks gelesen wurden ist der Transfer
// abgeschlossen.
return 1;
+ } else if (request->flags.ata &&
+ request->blocks_done*request->block_size>=packet_size)
+ {
+ // Wenn alle Bytes des ATAPI-Paketes gelesen wurden
+ // ist der Transfer abgeschlossen
+ return 1;
} else if (request->flags.poll) {
// Wenn gepollt wird, muss jetzt gewartet werden, bis der
// Status wieder stimmt um den naechsten Block zu lesen.
@@ -282,10 +295,11 @@ static int ata_protocol_pio_in(struct ata_request* request)
* Verarbeitet einen ATA-Request bei dem Daten ueber PIO geschrieben werden
* sollen
*/
-static int ata_protocol_pio_out(struct ata_request* request)
+int ata_protocol_pio_out(struct ata_request* request)
{
struct ata_device* dev = request->dev;
struct ata_controller* ctrl = dev->controller;
+ size_t packet_size = 0;
// Aktueller Status im Protokol
enum {
@@ -301,10 +315,17 @@ static int ata_protocol_pio_out(struct ata_request* request)
// Auf IRQ warten
if (ata_wait_irq(ctrl, ATA_IRQ_TIMEOUT)) {
request->error = IRQ_TIMEOUT;
- printf("ata: pio_out IRQ-Timeout\n");
+ DEBUG("pio_out IRQ-Timeout\n");
return 0;
}
+ if (request->flags.ata && packet_size==0) // ATAPI
+ {
+ // Paketgroesse einlesen, da sonst unendlich viel geschrieben wird
+ packet_size = ata_reg_inb(ctrl,REG_LBA_MID)|(ata_reg_inb(ctrl,REG_LBA_HIG)<<8);
+ DEBUG("packet_size = %d\n",packet_size);
+ }
+
// Jetzt muss der Status ueberprueft werden
state = CHECK_STATUS;
break;
@@ -312,18 +333,26 @@ static int ata_protocol_pio_out(struct ata_request* request)
case CHECK_STATUS: {
uint8_t status = ata_reg_inb(ctrl, REG_STATUS);
- // Status ueberpruefen
- // Wenn DRQ und BSY geloescht wurden ist irgendetwas schief
- // gelaufen, falls der Befehl noch nicht zu Ende ist
- if ((status & (STATUS_BSY | STATUS_DRQ)) == 0) {
- if (request->blocks_done != request->block_count) {
- // TODO: Fehlerbehandlung
- printf("ata: pio_out unerwarteter Status: 0x%x\n",
- status);
- return 0;
- } else {
- return 1;
- }
+ if (request->flags.ata &&
+ request->blocks_done * request->block_size>=packet_size)
+ {
+ // Das Paket wurde vollstaendig gelesen. DRQ wird nicht
+ // gesetzt, deswegen muss so beendet werden.
+ return 1;
+ }
+ else if (!request->flags.ata &&
+ request->blocks_done==request->block_count)
+ {
+ // Der Buffer wurde komplett gelesen. Dies sollte bei
+ // ATAPI nicht passieren!
+ return 1;
+ }
+ else if ((status & (STATUS_BSY | STATUS_DRQ)) == 0)
+ {
+ // TODO: Fehlerbehandlung
+ DEBUG("pio_out unerwarteter Status: 0x%x\n", status);
+ return 0;
+
} else if ((status & STATUS_BSY) == STATUS_BSY) {
// Wenn das Busy-Flag gesetzt ist, muss gewartet werden,
// bis es geloescht wird.
@@ -375,7 +404,7 @@ int ata_request(struct ata_request* request)
// printf("ata: [%d:%d] Request command=%x count=%x lba=%llx protocol=%x\n", request->dev->controller->id, request->dev->id, request->registers.ata.command, request->registers.ata.count, request->registers.ata.lba, request->protocol);
// Befehl ausfuehren
if (!ata_request_command(request)) {
- printf("ata: Fehler bei der Befehlsausfuehrung\n");
+ DEBUG("Fehler bei der Befehlsausfuehrung\n");
return 0;
}
--
1.5.4.5