[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Lost] ata (ATAPI-Support) und cdi/scsi.h



Patches für ata und cdi/scsi.h sind im Anhang.

Meine ata-Version war leider etwas veraltet, deswegen patcht der wieder
was weg (z.B Zeile 197 in ata.patch). Außerdem hat KDevelop auch einen
Haufen Trailing Spaces entfernt, was man jetzt auch im Patch hat.


PS: Diesmal sind die Patches wirklich im Anhang ;)
Index: atapi.c
===================================================================
--- atapi.c	(Revision 931)
+++ atapi.c	(Arbeitskopie)
@@ -1,4 +1,4 @@
-/*  
+/*
  * Copyright (c) 2007 The LOST Project. All rights reserved.
  *
  * This code is derived from software contributed to the LOST 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,8 @@
  */
 int atapi_drv_identify(struct ata_device* dev)
 {
-    uint8_t buffer[ATA_SECTOR_SIZE];
+    //uint8_t buffer[ATA_SECTOR_SIZE];
+    struct ata_identfiy_data id;
 
     // Request vorbereiten
     struct ata_request request = {
@@ -66,22 +68,84 @@
         .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)
+{
+
+}
+
+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;
+}
Index: device.c
===================================================================
--- device.c	(Revision 931)
+++ device.c	(Arbeitskopie)
@@ -1,4 +1,4 @@
-/*  
+/*
  * Copyright (c) 2007 The LOST Project. All rights reserved.
  *
  * This code is derived from software contributed to the LOST 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,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);
 
@@ -67,15 +66,7 @@
     ATA_DELAY();
     status = ata_reg_inb(controller, REG_STATUS);
 
-    // Nicht floating
-    if (status != 0xFF) {
-        return 0;
-    }
-
-    // Slave auswaehlen
-    ata_reg_outb(controller, REG_DEVICE, DEVICE_DEV(1));
-    ATA_DELAY();
-    status = ata_reg_inb(controller, REG_STATUS);
+    // Wenn alle Bits gesetzt sind, ist der Bus floating
     return (status == 0xFF);
 }
 
@@ -200,20 +191,20 @@
                 printf("ata: 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;
+            printf("ata: 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);
@@ -241,7 +232,7 @@
         cdi_ioports_free(controller->port_cmd_base, 8);
         return;
     }
-    
+
     // Da NIEN nicht ueberall sauber funktioniert, muss jetzt trotzdem schon
     // ein IRQ-Handler registriert werden. Und dafuer brauchen wir nun mal ein
     // Geraet.
@@ -270,7 +261,7 @@
         printf("ata: Floating Bus %d\n", controller->id);
         return;
     }
-    
+
     // Testen ob mindestens ein antwortendes Geraet am Bus haengt. Hier muss
     // darauf geachtet werden, dass der Master auch antworten muss, wenn zwar
     // der Slave ausgewaehlt ist, aber nicht existiert.
@@ -285,30 +276,54 @@
         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);
+
             if (dev->atapi == 0) {
+                dev->dev.storage.block_size = ATA_SECTOR_SIZE;
+                dev->atapi = 0;
+
                 // 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);
             } else {
+#ifdef ATAPI_ENABLE
+                dev->atapi = 1;
+
                 // 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->scsi->drv.devices, dev);
+#else
+                dev->dev.storage.block_size = ATA_SECTOR_SIZE;
+                dev->atapi = 0;
+
+                // Handler setzen
+                dev->read_sectors = ata_drv_read_sectors;
+                dev->write_sectors = ata_drv_write_sectors;
+
+                // Name setzen
+                asprintf((char**) &(dev->dev.storage.dev.name), "atapi%01d%01d",
+                    (uint32_t) controller->id, i);
+
+                // Geraet registrieren
+                cdi_list_push(controller->storage->drv.devices, dev);
+#endif
             }
-            
-            // Geraet registrieren
-            cdi_list_push(controller->driver->drv.devices, dev);
         } else {
             free(dev);
         }
@@ -339,19 +354,19 @@
 {
     struct ata_device* dev = (struct ata_device*) device;
     struct ata_partition* partition = NULL;
-    
+
     // Wenn der Pointer auf den Controller NULL ist, handelt es sich um eine
     // Partition
     if (dev->controller == NULL) {
         partition = (struct ata_partition*) dev;
-        dev = partition->dev;
+        dev = partition->realdev;
     }
 
     // Natuerlich nur ausfuehren wenn ein Handler eingetragen ist
     if (dev->read_sectors == NULL) {
         return -1;
     }
-    
+
     // Bei einer Partition noch den Offset dazurechnen
     if (partition == NULL) {
         return !dev->read_sectors(dev, block, count, buffer);
@@ -369,19 +384,19 @@
 {
     struct ata_device* dev = (struct ata_device*) device;
     struct ata_partition* partition = NULL;
-    
+
     // Wenn der Pointer auf den Controller NULL ist, handelt es sich um eine
     // Partition
     if (dev->controller == NULL) {
         partition = (struct ata_partition*) dev;
-        dev = partition->dev;
+        dev = partition->realdev;
     }
 
     // Natuerlich nur ausfuehren wenn ein Handler eingetragen ist
     if (dev->write_sectors == NULL) {
         return -1;
     }
-    
+
     // Bei einer Partition muss noch ein Offset drauf addiert werden
     if (partition == NULL) {
         return !dev->write_sectors(dev, block, count, buffer);
Index: device.h
===================================================================
--- device.h	(Revision 931)
+++ device.h	(Arbeitskopie)
@@ -1,4 +1,4 @@
-/*  
+/*
  * Copyright (c) 2007 The LOST Project. All rights reserved.
  *
  * This code is derived from software contributed to the LOST 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.
  */
 
@@ -42,7 +42,10 @@
 #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
 #define ATA_PRIMARY_IRQ         14
@@ -51,7 +54,7 @@
 #define ATA_SECONDARY_CTL_BASE  0x376
 #define ATA_SECONDARY_IRQ       15
 
-#define ATA_DELAY()             
+#define ATA_DELAY()
 
 // Hinweis: Worst Case nach ATA-Spec waeren 30 Sekunden
 #define ATA_IDENTIFY_TIMEOUT    5000
@@ -96,37 +99,209 @@
                                 STATUS_DRQ | STATUS_ERR)
 
 // Befehle
-#define COMMAND_IDENTIFY        0xEC
+//#define COMMAND_IDENTIFY        0xEC
 
 // Control Register
 #define CONTROL_HOB             (1 << 7)
 #define CONTROL_SRST            (1 << 2)
 #define CONTROL_NIEN            (1 << 1)
 
+/**
+ * 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;
-    
+
     // Liste mit den Partitionen
     cdi_list_t                  partition_list;
 
     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
@@ -134,7 +309,7 @@
 
     // 1 Wenn das Geraet lba28 unterstuetzt
     uint8_t                     lba28;
-    
+
     // Funktionen fuer den Zugriff auf dieses Geraet
     int (*read_sectors) (struct ata_device* dev, uint64_t start, size_t count,
         void* dest);
@@ -143,7 +318,8 @@
 };
 
 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;
@@ -160,7 +336,7 @@
 
 struct ata_request {
     struct ata_device* dev;
-    
+
     enum {
         NON_DATA,
         PIO
@@ -172,13 +348,13 @@
             READ,
             WRITE
         } direction;
-        
+
         // 1 fuer Polling; 0 fuer Interrupts
         uint8_t poll;
-        
+
         // 1 fuer ATAPI; 0 fuer ata
         uint8_t ata;
-        
+
         // 1 Wenn das LBA-Bit im Geraeteregister
         uint8_t lba;
     } flags;
@@ -189,21 +365,18 @@
             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
     uint16_t block_count;
-    
+
     // Groesse eines Blocks
     uint16_t block_size;
 
@@ -213,7 +386,7 @@
     // Puffer in den die Daten geschrieben werden sollen/aus dem sie gelesen
     // werden sollen.
     void* buffer;
-    
+
     // Moegliche Fehler
     enum {
         NO_ERROR = 0,
@@ -223,7 +396,6 @@
     } 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);
@@ -237,6 +409,9 @@
 // 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,
@@ -246,6 +421,9 @@
 
 // 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);
@@ -280,7 +458,7 @@
 /**
  * Byte in Kontrollerregister schreiben
  */
-static inline void ata_reg_outb(struct ata_controller* controller, 
+static inline void ata_reg_outb(struct ata_controller* controller,
     uint8_t reg, uint8_t value)
 {
     uint16_t base = ata_reg_base(controller, reg);
@@ -313,7 +491,7 @@
 static inline void ata_drv_select(struct ata_device* dev)
 {
     ata_reg_outb(dev->controller, REG_DEVICE, DEVICE_DEV(dev->id));
-    ATA_DELAY();  
+    ATA_DELAY();
 }
 
 
Index: main.c
===================================================================
--- main.c	(Revision 931)
+++ main.c	(Arbeitskopie)
@@ -1,4 +1,4 @@
-/*  
+/*
  * Copyright (c) 2007 The LOST Project. All rights reserved.
  *
  * This code is derived from software contributed to the LOST 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.
  */
 
@@ -43,16 +43,15 @@
 
 #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,11 +61,12 @@
 {
     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();
-#endif    
+#endif
 
     return 0;
 }
@@ -79,39 +79,47 @@
     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);
-    
+
     // Sekundaeren Controller vorbereiten
     controller = malloc(sizeof(*controller));
     controller->port_cmd_base = ATA_SECONDARY_CMD_BASE;
     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 +133,8 @@
 
     // TODO Alle Karten deinitialisieren
 }
+
+static void atapi_driver_destroy(struct cdi_driver* driver)
+{
+    cdi_scsi_driver_destroy((struct cdi_scsi_driver*) driver);
+}
Index: ata.c
===================================================================
--- ata.c	(Revision 931)
+++ ata.c	(Arbeitskopie)
@@ -1,4 +1,4 @@
-/*  
+/*
  * Copyright (c) 2007 The LOST Project. All rights reserved.
  *
  * This code is derived from software contributed to the LOST 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.
  */
 
@@ -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
@@ -234,22 +68,22 @@
 
         .error = 0
     };
-    
+
     // Request starten
     if (!ata_request(&request)) {
         // Wenn ein Fehler aufgetreten ist, koennen wir es noch mit einem
         // IDENTIFY PACKET DEVICE probieren.
         return atapi_drv_identify(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
@@ -300,7 +134,7 @@
         } else {
             current_count = count_left;
         }
-        
+
         // Request vorbereiten
         request.dev = dev;
         // TODO: DMA, UltraDMA...
@@ -319,7 +153,7 @@
             request.flags.direction = WRITE;
             request.registers.ata.command = WRITE_SECTORS;
         }
-        
+
         // Achtung: Beim casten nach uint8_t wird bei 256 Sektoren eine 0.
         // Das macht aber nichts, da in der Spezifikation festgelegt ist,
         // dass 256 Sektoren gelesen werden sollen, wenn im count-Register
@@ -333,10 +167,10 @@
         request.buffer = current_buffer;
 
         request.error = NO_ERROR;
-        
+
         // TODO: LBA48
         // TODO: CHS
-        
+
         // Request ausfuehren
         if (!ata_request(&request)) {
             result = 0;
Index: request.c
===================================================================
--- request.c	(Revision 931)
+++ request.c	(Arbeitskopie)
@@ -1,4 +1,4 @@
-/*  
+/*
  * Copyright (c) 2007 The LOST Project. All rights reserved.
  *
  * This code is derived from software contributed to the LOST 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.
  */
 
@@ -65,13 +65,13 @@
         time += 10;
         cdi_sleep_ms(10);
     }
-    
+
     // Dem Geraet etwas Zeit geben
     ATA_DELAY();
 
     // Jetzt koennen wir warten bis die gewuenschten Bits gesetzt sind
     while (((ata_reg_inb(ctrl, REG_STATUS) & bits) != bits) &&
-        (time < timeout)) 
+        (time < timeout))
     {
         time += 10;
         cdi_sleep_ms(10);
@@ -91,7 +91,7 @@
     struct ata_device* dev = request->dev;
     struct ata_controller* ctrl = dev->controller;
     uint8_t control;
-    
+
     // IRQ-Zaehler zuruecksetzen, egal ob er gebraucht wird oder nicht, stoert
     // ja niemanden
     ctrl->irq_cnt = 0;
@@ -103,7 +103,7 @@
         request->error = DEVICE_READY_TIMEOUT;
         return 0;
     }
-    
+
     // Device Register schreiben
     // TODO: nicht lba?
     ata_reg_outb(ctrl, REG_DEVICE, (request->flags.lba << 6) | (request->dev->
@@ -120,7 +120,7 @@
 
     // Count-Register schrieben
     ata_reg_outb(ctrl, REG_SEC_CNT, request->registers.ata.count);
-    
+
     // LBA Register schreiben
     ata_reg_outb(ctrl, REG_LBA_LOW, request->registers.ata.lba & 0xFF);
     ata_reg_outb(ctrl, REG_LBA_MID, (request->registers.ata.lba >> 8) & 0xFF);
@@ -140,13 +140,13 @@
 {
     struct ata_device* dev = request->dev;
     struct ata_controller* ctrl = dev->controller;
-    
+
     // Aktueller Status im Protokol
     enum {
         IRQ_WAIT,
         CHECK_STATUS
     } state;
-    
+
     // Der Anfangsstatus haengt davon ab, ob gepollt werden soll oder nicht.
     if  (request->flags.poll) {
         state = CHECK_STATUS;
@@ -167,10 +167,10 @@
                 // Jetzt muss der Status ueberprueft werden
                 state = CHECK_STATUS;
                 break;
-            
+
             case CHECK_STATUS: {
                 uint8_t status = ata_reg_inb(ctrl, REG_STATUS);
-                
+
                 // Status ueberpruefen
                 if ((status & STATUS_BSY) == STATUS_BSY) {
                     // Wenn das Busy-Flag gesetzt ist, muss gewartet werden,
@@ -190,18 +190,19 @@
  * 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 {
         IRQ_WAIT,
         CHECK_STATUS,
         TRANSFER_DATA
     } state;
-    
+
     // Der Anfangsstatus haengt davon ab, ob gepollt werden soll oder nicht.
     if  (request->flags.poll) {
         state = CHECK_STATUS;
@@ -219,13 +220,19 @@
                     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;
-            
+
             case CHECK_STATUS: {
                 uint8_t status = ata_reg_inb(ctrl, REG_STATUS);
-                
+
                 // Status ueberpruefen
                 // Wenn DRQ und BSY geloescht wurden ist irgendetwas schief
                 // gelaufen.
@@ -250,7 +257,7 @@
                 uint16_t i;
                 uint16_t* buffer = (uint16_t*) (request->buffer + (request->
                     blocks_done * request->block_size));
-                
+
                 // Einen Block einlesen
                 for (i = 0; i < request->block_size / 2; i++) {
                     buffer[i] = ata_reg_inw(ctrl, REG_DATA);
@@ -258,12 +265,19 @@
 
                 // Anzahl der gelesenen Block erhoehen
                 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,11 +296,12 @@
  * 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 {
         IRQ_WAIT,
@@ -305,25 +320,41 @@
                     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);
+                    printf("ata: packet_size = %d\n",packet_size);
+                }
+
                 // Jetzt muss der Status ueberprueft werden
                 state = CHECK_STATUS;
                 break;
-            
+
             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
+                    printf("ata: 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.
@@ -342,7 +373,7 @@
                 uint16_t i;
                 uint16_t* buffer = (uint16_t*) (request->buffer + (request->
                     blocks_done * request->block_size));
-                
+
                 // Einen Block schreiben
                 for (i = 0; i < request->block_size / 2; i++) {
                     ata_reg_outw(ctrl, REG_DATA, buffer[i]);
@@ -350,7 +381,7 @@
 
                 // Anzahl der geschriebenen Block erhoehen
                 request->blocks_done++;
-                
+
                 // Naechste Transaktion ausfindig machen
                 if (request->flags.poll) {
                     // Wenn gepollt wird, muss jetzt gewartet werden, bis der
@@ -388,7 +419,7 @@
                 return 0;
             }
             break;
-        
+
         case PIO:
             if ((request->flags.direction == READ) &&
                 (!ata_protocol_pio_in(request)))
--- /dev/null	2008-06-06 21:39:59.000000000 +0200
+++ cdi/scsi.h	2008-10-06 16:02:24.000000000 +0200
@@ -0,0 +1,74 @@
+#ifndef _CDI_SCSI_H_
+#define _CDI_SCSI_H_
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "cdi.h"
+
+// SCSI-Paket
+struct cdi_scsi_packet {
+  // Buffer zum Senden oder Empfangen von Daten
+  void *buffer;
+
+  // Groesse des Buffers
+  size_t bufsize;
+
+  // Ob gelesen oder geschrieben werden soll
+  enum {
+    CDI_SCSI_NODATA,
+    CDI_SCSI_READ,
+    CDI_SCSI_WRITE,
+  } direction;
+
+  // SCSI Command
+  uint8_t command[16];
+
+  // Groesse des SCSI Commands
+  size_t cmdsize;
+};
+
+// SCSI-Geraet
+struct cdi_scsi_device {
+  struct cdi_device dev;
+};
+
+// SCSI-Driver
+struct cdi_scsi_driver {
+  struct cdi_driver drv;
+
+  int (*request)(struct cdi_scsi_device *device,struct cdi_scsi_packet *packet);
+};
+
+/**
+ * Ein SCSI-Paket allozieren
+ *
+ * @param size Benoetigte Groesse
+ *
+ * @return Pointer auf das Paket oder NULL im Fehlerfall
+ */
+struct cdi_scsi_packet* cdi_scsi_packet_alloc(size_t size);
+
+/**
+ * Ein SCSI-Paket freigeben
+ *
+ * @param packet Pointer auf das Paket
+ */
+void cdi_scsi_packet_free(struct cdi_scsi_packet* packet);
+
+/**
+ * Initialisiert die Datenstrukturen fuer einen SCSI-Treiber
+ */
+void cdi_scsi_driver_init(struct cdi_scsi_driver* driver);
+
+/**
+ * Deinitialisiert die Datenstrukturen fuer einen SCSI-Treiber
+ */
+void cdi_scsi_driver_destroy(struct cdi_scsi_driver* driver);
+
+/**
+ * Registiert einen SCSI-Treiber
+ */
+void cdi_scsi_driver_register(struct cdi_scsi_driver* driver);
+
+#endif