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

[tyndur-devel] [PATCH] cdi: CD-ROM-Unterstuetzung



+ cdi: Storage: Zusaetzliche Funktionen get_size() und get_block_size(), da SCSI-Geraete die Variablen nicht haben
+ cdi: SCSI: Grundfunktionalitaet
+ cdi: SCSI: Storage-Backend scsi/disk (momentan nur fuer CD-ROM geeignet)
* cdi: Storage nimmt jetzt auch SCSI-Geraete
* cdi: Storage-Treiber und -Geraete werden einzeln initialisiert
* ata/floppy: An geaenderte Interfaces geanpasst
---
 src/modules/cdi/ata/atapi.c           |    3 +
 src/modules/cdi/ata/device.c          |   19 ++-
 src/modules/cdi/ata/device.h          |    6 +-
 src/modules/cdi/ata/main.c            |    4 +-
 src/modules/cdi/floppy/device.c       |   29 +++-
 src/modules/cdi/floppy/device.h       |    6 +-
 src/modules/cdi/floppy/main.c         |    8 +-
 src/modules/cdi/include/cdi.h         |    3 +-
 src/modules/cdi/include/cdi/scsi.h    |   86 +++++++++++
 src/modules/cdi/include/cdi/storage.h |   19 ++-
 src/modules/cdi/lib/cdi.c             |    1 +
 src/modules/cdi/lib/scsi/disk.c       |  264 +++++++++++++++++++++++++++++++++
 src/modules/cdi/lib/scsi/driver.c     |   56 +++++++
 src/modules/cdi/lib/storage.c         |   89 ++++++++----
 14 files changed, 546 insertions(+), 47 deletions(-)
 create mode 100644 src/modules/cdi/include/cdi/scsi.h
 create mode 100644 src/modules/cdi/lib/scsi/disk.c
 create mode 100644 src/modules/cdi/lib/scsi/driver.c

diff --git a/src/modules/cdi/ata/atapi.c b/src/modules/cdi/ata/atapi.c
index 67dc140..ecff315 100644
--- a/src/modules/cdi/ata/atapi.c
+++ b/src/modules/cdi/ata/atapi.c
@@ -86,7 +86,10 @@ int atapi_drv_identify(struct ata_device* dev)
 
 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)
diff --git a/src/modules/cdi/ata/device.c b/src/modules/cdi/ata/device.c
index f9ccf21..b9763d4 100644
--- a/src/modules/cdi/ata/device.c
+++ b/src/modules/cdi/ata/device.c
@@ -333,6 +333,8 @@ 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->dev.storage);
 }
 
 void ata_remove_device(struct cdi_device* device)
@@ -344,7 +346,7 @@ void ata_remove_device(struct cdi_device* device)
 /**
  * Blocks von einem ATA(PI) Geraet lesen
  */
-int ata_read_blocks(struct cdi_storage_device* device, uint64_t block,
+int ata_read_blocks(struct cdi_device* device, uint64_t block,
     uint64_t count, void* buffer)
 {
     struct ata_device* dev = (struct ata_device*) device;
@@ -374,7 +376,7 @@ int ata_read_blocks(struct cdi_storage_device* device, uint64_t block,
 /**
  * Blocks auf ein ATA(PI) Geraet schreiben
  */
-int ata_write_blocks(struct cdi_storage_device* device, uint64_t block,
+int ata_write_blocks(struct cdi_device* device, uint64_t block,
     uint64_t count, void* buffer)
 {
     struct ata_device* dev = (struct ata_device*) device;
@@ -401,3 +403,16 @@ int ata_write_blocks(struct cdi_storage_device* device, uint64_t block,
     }
 }
 
+uint64_t ata_get_size(struct cdi_device* device)
+{
+    struct cdi_storage_device* storage = (struct cdi_storage_device*) device;
+
+    return storage->block_size * storage->block_count;
+}
+
+uint64_t ata_get_block_size(struct cdi_device* device)
+{
+    struct cdi_storage_device* storage = (struct cdi_storage_device*) device;
+
+    return storage->block_size;
+}
diff --git a/src/modules/cdi/ata/device.h b/src/modules/cdi/ata/device.h
index 140f037..eaa890a 100644
--- a/src/modules/cdi/ata/device.h
+++ b/src/modules/cdi/ata/device.h
@@ -411,11 +411,13 @@ void ata_init_controller(struct ata_controller* controller);
 void ata_remove_controller(struct ata_controller* controller);
 void ata_init_device(struct cdi_device* device);
 void ata_remove_device(struct cdi_device* device);
-int ata_read_blocks(struct cdi_storage_device* device, uint64_t block,
+int ata_read_blocks(struct cdi_device* device, uint64_t block,
     uint64_t count, void* buffer);
-int ata_write_blocks(struct cdi_storage_device* device, uint64_t block,
+int ata_write_blocks(struct cdi_device* device, uint64_t block,
     uint64_t count, void* buffer);
 
+uint64_t ata_get_size(struct cdi_device* device);
+uint64_t ata_get_block_size(struct cdi_device* device);
 
 // Einen ATA-Request absenden und ausfuehren
 int ata_request(struct ata_request* request);
diff --git a/src/modules/cdi/ata/main.c b/src/modules/cdi/ata/main.c
index 750f7b2..18e7225 100644
--- a/src/modules/cdi/ata/main.c
+++ b/src/modules/cdi/ata/main.c
@@ -80,7 +80,7 @@ static void ata_driver_init()
     // Konstruktor der Vaterklasse
     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_storage_name;
     driver_scsi.drv.name = driver_scsi_name;
@@ -91,6 +91,8 @@ static void ata_driver_init()
     driver_storage.drv.remove_device    = ata_remove_device;
     driver_storage.read_blocks          = ata_read_blocks;
     driver_storage.write_blocks         = ata_write_blocks;
+    driver_storage.get_size             = ata_get_size;
+    driver_storage.get_block_size       = ata_get_block_size;
 
     driver_scsi.drv.destroy             = atapi_driver_destroy;
     driver_scsi.drv.init_device         = atapi_init_device;
diff --git a/src/modules/cdi/floppy/device.c b/src/modules/cdi/floppy/device.c
index 6614e1e..4435630 100644
--- a/src/modules/cdi/floppy/device.c
+++ b/src/modules/cdi/floppy/device.c
@@ -796,6 +796,8 @@ void floppy_init_device(struct cdi_device* device)
 
     dev->dev.block_size = FLOPPY_SECTOR_SIZE(dev);
     dev->dev.block_count = FLOPPY_SECTOR_COUNT(dev);
+
+    cdi_storage_device_init(&dev->dev);
 }
 
 /**
@@ -808,7 +810,7 @@ void floppy_remove_device(struct cdi_device* device)
 /**
  * Sektoren einlesen
  */
-int floppy_read_blocks(struct cdi_storage_device* dev, uint64_t block,
+int floppy_read_blocks(struct cdi_device* dev, uint64_t block,
     uint64_t count, void* buffer)
 {
     struct floppy_device* device = (struct floppy_device*) dev;
@@ -823,7 +825,7 @@ int floppy_read_blocks(struct cdi_storage_device* dev, uint64_t block,
         // Wenn das schief geht, wird mehrmals probiert
         for (j = 0; (j < 5) && (result != 0); j++) {
             result = floppy_drive_sector_read(device, (uint32_t) block + i,
-                buffer + i * dev->block_size);
+                buffer + i * device->dev.block_size);
         }
     }
 
@@ -833,7 +835,7 @@ int floppy_read_blocks(struct cdi_storage_device* dev, uint64_t block,
 /**
  * Sektoren schreiben
  */
-int floppy_write_blocks(struct cdi_storage_device* dev, uint64_t block,
+int floppy_write_blocks(struct cdi_device* dev, uint64_t block,
     uint64_t count, void* buffer)
 {
     struct floppy_device* device = (struct floppy_device*) dev;
@@ -848,13 +850,32 @@ int floppy_write_blocks(struct cdi_storage_device* dev, uint64_t block,
         // Wenn das schief geht, wird mehrmals probiert
         for (j = 0; (j < 5) && (result != 0); j++) {
             result = floppy_drive_sector_write(device, (uint32_t) block + i,
-                buffer + i * dev->block_size);
+                buffer + i * device->dev.block_size);
         }
     }
 
     return result;
 }
 
+/**
+ * Gibt die Groesse des Mediums zurueck
+ */
+uint64_t floppy_get_size(struct cdi_device* device)
+{
+    struct cdi_storage_device* storage = (struct cdi_storage_device*) device;
+
+    return storage->block_size * storage->block_count;
+}
+
+/**
+ * Gibt die Sektorgroesse des Mediums zurueck
+ */
+uint64_t floppy_get_block_size(struct cdi_device* device)
+{
+    struct cdi_storage_device* storage = (struct cdi_storage_device*) device;
+
+    return storage->block_size;
+}
 
 /**
  * IRQ-Handler fuer den Kontroller; Erhoeht nur den IRQ-Zaehler in der
diff --git a/src/modules/cdi/floppy/device.h b/src/modules/cdi/floppy/device.h
index 24d16f9..6c3bfcf 100644
--- a/src/modules/cdi/floppy/device.h
+++ b/src/modules/cdi/floppy/device.h
@@ -137,10 +137,12 @@ int floppy_init_controller(struct floppy_controller* controller);
 
 void floppy_init_device(struct cdi_device* device);
 void floppy_remove_device(struct cdi_device* device);
-int floppy_read_blocks(struct cdi_storage_device* device, uint64_t block,
+int floppy_read_blocks(struct cdi_device* device, uint64_t block,
     uint64_t count, void* buffer);
-int floppy_write_blocks(struct cdi_storage_device* device, uint64_t block,
+int floppy_write_blocks(struct cdi_device* device, uint64_t block,
     uint64_t count, void* buffer);
+uint64_t floppy_get_size(struct cdi_device* device);
+uint64_t floppy_get_block_size(struct cdi_device* device);
 
 void floppy_handle_interrupt(struct cdi_device* device);
 
diff --git a/src/modules/cdi/floppy/main.c b/src/modules/cdi/floppy/main.c
index 435ff1f..aa32ed5 100644
--- a/src/modules/cdi/floppy/main.c
+++ b/src/modules/cdi/floppy/main.c
@@ -87,7 +87,7 @@ static int floppy_driver_init(struct floppy_driver* driver)
 
     // Konstruktor der Vaterklasse
     cdi_storage_driver_init((struct cdi_storage_driver*) driver);
-    
+
     // Namen setzen
     driver->storage.drv.name = driver_name;
 
@@ -95,9 +95,11 @@ static int floppy_driver_init(struct floppy_driver* driver)
     driver->storage.drv.destroy         = floppy_driver_destroy;
     driver->storage.drv.init_device     = floppy_init_device;
     driver->storage.drv.remove_device   = floppy_remove_device;
-    driver->storage.read_blocks         = floppy_read_blocks; 
+    driver->storage.read_blocks         = floppy_read_blocks;
     driver->storage.write_blocks        = floppy_write_blocks;
-    
+    driver->storage.get_size            = floppy_get_size;
+    driver->storage.get_block_size      = floppy_get_block_size;
+
     // Geraete erstellen (TODO: Was wenn eines oder beide nicht vorhanden
     // sind?)
     for (i = 0; i < 2; i++) {
diff --git a/src/modules/cdi/include/cdi.h b/src/modules/cdi/include/cdi.h
index 42e4643..5fb7025 100644
--- a/src/modules/cdi/include/cdi.h
+++ b/src/modules/cdi/include/cdi.h
@@ -23,7 +23,8 @@
 typedef enum {
     CDI_UNKNOWN         = 0,
     CDI_NETWORK         = 1,
-    CDI_STORAGE         = 2
+    CDI_STORAGE         = 2,
+    CDI_SCSI            = 3,
 } cdi_device_type_t;
 
 struct cdi_driver;
diff --git a/src/modules/cdi/include/cdi/scsi.h b/src/modules/cdi/include/cdi/scsi.h
new file mode 100644
index 0000000..78f0c30
--- /dev/null
+++ b/src/modules/cdi/include/cdi/scsi.h
@@ -0,0 +1,86 @@
+#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;
+
+    // Geraetetyp, der ueber SCSI angesteuert wird
+    cdi_device_type_t type;
+
+};
+
+// 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);
+
+/**
+ * Initialisiert ein neues SCSI-Geraet
+ *
+ * Der Typ der Geraetes muss bereits gesetzt sein
+ */
+void cdi_scsi_device_init(struct cdi_scsi_device* device);
+
+#endif
diff --git a/src/modules/cdi/include/cdi/storage.h b/src/modules/cdi/include/cdi/storage.h
index 73ae245..781a158 100644
--- a/src/modules/cdi/include/cdi/storage.h
+++ b/src/modules/cdi/include/cdi/storage.h
@@ -40,7 +40,7 @@ struct cdi_storage_driver {
      *
      * @return 0 bei Erfolg, -1 im Fehlerfall.
      */
-    int (*read_blocks)(struct cdi_storage_device* device, uint64_t start,
+    int (*read_blocks)(struct cdi_device* device, uint64_t start,
         uint64_t count, void* buffer);
     
     /**
@@ -53,8 +53,18 @@ struct cdi_storage_driver {
      *
      * @return 0 bei Erfolg, -1 im Fehlerfall
      */
-    int (*write_blocks)(struct cdi_storage_device* device, uint64_t start,
+    int (*write_blocks)(struct cdi_device* device, uint64_t start,
         uint64_t count, void* buffer);
+
+    /**
+     * Gibt die Groesse des Mediums in Bytes zurueck
+     */
+    uint64_t (*get_size)(struct cdi_device* device);
+
+    /**
+     * Gibt die Blockgroesse des Geraets in Bytes zurueck
+     */
+    uint64_t (*get_block_size)(struct cdi_device* device);
 };
 
 
@@ -75,6 +85,11 @@ void cdi_storage_driver_destroy(struct cdi_storage_driver* driver);
  */
 void cdi_storage_driver_register(struct cdi_storage_driver* driver);
 
+/**
+ * Initialisiert einen Massenspeicher
+ */
+void cdi_storage_device_init(struct cdi_storage_device* device);
+
 #endif
 
 /*\@}*/
diff --git a/src/modules/cdi/lib/cdi.c b/src/modules/cdi/lib/cdi.c
index d8c7819..487887e 100644
--- a/src/modules/cdi/lib/cdi.c
+++ b/src/modules/cdi/lib/cdi.c
@@ -86,6 +86,7 @@ void cdi_run_drivers(void)
 
         for (j = 0; (device = cdi_list_get(driver->devices, j)); j++) {
             device->driver = driver;
+            device->type = driver->type;
 
             if (driver->init_device) {
                 driver->init_device(device);
diff --git a/src/modules/cdi/lib/scsi/disk.c b/src/modules/cdi/lib/scsi/disk.c
new file mode 100644
index 0000000..9bd5a74
--- /dev/null
+++ b/src/modules/cdi/lib/scsi/disk.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2008 Mathias Gottschlag
+ * Copyright (C) 2009 Kevin Wolf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <cdi/lists.h>
+#include <cdi/scsi.h>
+#include <cdi/storage.h>
+
+#define big_endian_word(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8))
+#define big_endian_dword(x) \
+    ((big_endian_word((x) & 0xFFFF) << 16) | \
+    (big_endian_word((x) >> 16)))
+
+static int cdi_scsi_disk_read(struct cdi_device* device,
+    uint64_t start, uint64_t count, void* buffer);
+
+static int cdi_scsi_disk_write(struct cdi_device* device,
+    uint64_t start, uint64_t count, void* buffer);
+
+static uint64_t cdi_scsi_disk_get_size(struct cdi_device* device);
+static uint64_t cdi_scsi_disk_get_block_size(struct cdi_device* device);
+
+struct cdi_storage_driver cdi_scsi_disk_driver = {
+    .read_blocks    = cdi_scsi_disk_read,
+    .write_blocks   = cdi_scsi_disk_write,
+    .get_size       = cdi_scsi_disk_get_size,
+    .get_block_size = cdi_scsi_disk_get_block_size,
+};
+
+// TODO: This is kind of incomplete... -.-
+// FIXME Das ist alles sehr CD-ROM-spezifisch hartkodiert...
+
+union cdrom_command
+{
+	struct
+	{
+		uint8_t opcode;
+		uint8_t reserved0;
+		uint32_t address;
+		uint8_t reserved1;
+		uint16_t length;
+		uint8_t reserved2;
+	} __attribute__ ((packed)) dfl;
+	struct
+	{
+		uint8_t opcode;
+		uint8_t reserved0;
+		uint32_t address;
+		uint32_t length;
+		uint16_t reserved1;
+	} __attribute__ ((packed)) ext;
+};
+
+static int cdrom_read_sector(
+    struct cdi_scsi_device *device, uint32_t sector, char *buffer)
+{
+	struct cdi_scsi_packet packet;
+    struct cdi_scsi_driver* drv = (struct cdi_scsi_driver*) device->dev.driver;
+    union cdrom_command* cmd = (union cdrom_command*) &packet.command;
+
+	memset(&packet, 0, sizeof(packet));
+	packet.direction = CDI_SCSI_READ;
+	packet.buffer = buffer;
+	packet.bufsize = 2048;
+	packet.cmdsize = 12;
+
+	cmd->ext.opcode = 0xA8;
+	cmd->ext.address = big_endian_dword(sector);
+	cmd->ext.length = 0x01000000;
+
+	if (drv->request(device, &packet)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int cdrom_capacity(struct cdi_scsi_device *device,
+    uint32_t* num_sectors, uint32_t* sector_size)
+{
+    uint32_t buffer[32];
+	struct cdi_scsi_packet packet;
+    struct cdi_scsi_driver* drv = (struct cdi_scsi_driver*) device->dev.driver;
+    union cdrom_command* cmd = (union cdrom_command*) &packet.command;
+
+	memset(&packet, 0, sizeof(packet));
+	packet.direction = CDI_SCSI_READ;
+	packet.buffer = buffer;
+	packet.bufsize = sizeof(buffer);
+	packet.cmdsize = 12;
+
+	cmd->ext.opcode = 0x25;
+
+	if (drv->request(device, &packet)) {
+		return -1;
+	}
+
+    *num_sectors = big_endian_dword(buffer[0]);
+    *sector_size = big_endian_dword(buffer[1]);
+
+	return 0;
+}
+
+#if 0
+static int cdrom_lock_device(FsSCSIDevice *device, int index, int lock)
+{
+	// Lock drive
+	FsSCSIPacket packet;
+	memset(&packet, 0, sizeof(FsSCSIPacket));
+	packet.direction = CDI_SCSI_NO_DATA;
+	((union cdrom_command*)packet.command)->dfl.opcode = 0x1E;
+	packet.command[4] = 1;
+	packet.buffer = 0;
+	packet.length = 0;
+	packet.commandsize = 12;
+	uint32_t status = device->request(device, &packet);
+	if (status)
+	{
+		kePrint("cdrom %d: Lock failed, %x\n", index, status);
+		fsCloseSCSIDevice(device);
+		return KE_ERROR_UNKNOWN;
+	}
+	return 0;
+}
+
+static void cdrom_sense(FsSCSIDevice *device, uint32_t index)
+{
+	char sense_data[18];
+	FsSCSIPacket packet;
+	packet.direction = CDI_SCSI_READ;
+	packet.buffer = sense_data;
+	packet.length = 18;
+	packet.commandsize = 12;
+	((union cdrom_command*)packet.command)->dfl.opcode = 0x12;
+}
+#endif
+
+int cdrom_init(struct cdi_scsi_device* device)
+{
+	// Send inquiry command
+    struct cdi_scsi_driver* drv = (struct cdi_scsi_driver*) device->dev.driver;
+	struct cdi_scsi_packet packet;
+	uint32_t status;
+	unsigned char inqdata[96];
+
+	memset(&packet, 0, sizeof(packet));
+	memset(inqdata, 0xF0, sizeof(inqdata));
+
+	packet.direction = CDI_SCSI_READ;
+	packet.buffer = inqdata;
+	packet.bufsize = 96;
+	packet.cmdsize = 12;
+
+	((union cdrom_command*)packet.command)->dfl.opcode = 0x12;
+	packet.command[4] = 96;
+	status = drv->request(device, &packet);
+	if (status)
+	{
+		return -1;
+	}
+
+#if 0
+	if (cdrom_lock_device(device, index, 1))
+		return KE_ERROR_UNKNOWN;
+#endif
+
+	// Start drive
+	packet.direction = CDI_SCSI_NODATA;
+	((union cdrom_command*)packet.command)->dfl.opcode = 0x1B;
+	packet.buffer = 0;
+	packet.bufsize = 0;
+	packet.command[4] = 0;
+	packet.command[4] = 3;
+	packet.cmdsize = 12;
+
+	status = drv->request(device, &packet);
+	if (status)
+	{
+		printf("cdrom %d: Start failed, %x\n", index, status);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int cdi_scsi_disk_read(struct cdi_device* device,
+    uint64_t start, uint64_t count, void* buffer)
+{
+    struct cdi_scsi_device* dev = (struct cdi_scsi_device*) device;
+
+    while (count--) {
+        if (cdrom_read_sector(dev, start, buffer)) {
+            return -1;
+        }
+        start ++;
+        buffer += 2048;
+    }
+
+    return 0;
+}
+
+static int cdi_scsi_disk_write(struct cdi_device* device,
+    uint64_t start, uint64_t count, void* buffer)
+{
+    return -1;
+}
+
+static uint64_t cdi_scsi_disk_get_size(struct cdi_device* device)
+{
+    struct cdi_scsi_device* dev = (struct cdi_scsi_device*) device;
+    uint32_t num_sectors, sector_size;
+
+
+    // TODO Einmal beim Initialisieren eines Mediums einlesen und dann bei
+    // jedem Aufruf wiederverwenden
+    cdrom_capacity(dev, &num_sectors, &sector_size);
+
+    return num_sectors * sector_size;
+}
+
+static uint64_t cdi_scsi_disk_get_block_size(struct cdi_device* device)
+{
+    struct cdi_scsi_device* dev = (struct cdi_scsi_device*) device;
+    uint32_t num_sectors, sector_size;
+
+
+    // TODO s.o.
+    cdrom_capacity(dev, &num_sectors, &sector_size);
+
+    return sector_size;
+}
+
+int lostio_mst_if_newdev(struct cdi_device* device);
+
+void cdi_scsi_disk_init(struct cdi_scsi_device* device)
+{
+    if (cdrom_init(device) == 0) {
+        // LostIO-Verzeichnisknoten anlegen
+        lostio_mst_if_newdev(&device->dev);
+    }
+}
diff --git a/src/modules/cdi/lib/scsi/driver.c b/src/modules/cdi/lib/scsi/driver.c
new file mode 100644
index 0000000..745bd25
--- /dev/null
+++ b/src/modules/cdi/lib/scsi/driver.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2009 Kevin Wolf
+ *
+ * This program is free software. It comes without any warranty, to
+ * the extent permitted by applicable law. You can redistribute it
+ * and/or modify it under the terms of the Do What The Fuck You Want
+ * To Public License, Version 2, as published by Sam Hocevar. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <lostio.h>
+
+#include "cdi/scsi.h"
+
+extern void cdi_scsi_disk_init(struct cdi_scsi_device* device);
+
+/**
+ * Initialisiert die Datenstrukturen fuer einen SCSI-Treiber
+ */
+void cdi_scsi_driver_init(struct cdi_scsi_driver* driver)
+{
+    driver->drv.type = CDI_SCSI;
+    cdi_driver_init((struct cdi_driver*) driver);
+}
+
+/**
+ * Deinitialisiert die Datenstrukturen fuer einen SCSI-Treiber
+ */
+void cdi_scsi_driver_destroy(struct cdi_scsi_driver* driver)
+{
+    cdi_driver_destroy((struct cdi_driver*) driver);
+}
+
+/**
+ * Initialisiert ein neues SCSI-Geraet
+ *
+ * Der Typ der Geraetes muss bereits gesetzt sein
+ */
+void cdi_scsi_device_init(struct cdi_scsi_device* device)
+{
+    if (device->type == CDI_STORAGE) {
+        cdi_scsi_disk_init(device);
+    }
+}
+
+/**
+ * Registiert den Treiber fuer SCSI-Geraete
+ */
+void cdi_scsi_driver_register(struct cdi_scsi_driver* driver)
+{
+    cdi_driver_register((struct cdi_driver*) driver);
+}
diff --git a/src/modules/cdi/lib/storage.c b/src/modules/cdi/lib/storage.c
index 9dd9746..16e4a7e 100644
--- a/src/modules/cdi/lib/storage.c
+++ b/src/modules/cdi/lib/storage.c
@@ -17,7 +17,7 @@
 #include "cdi/storage.h"
 
 static void lostio_mst_if_init(void);
-static int lostio_mst_if_newdev(struct cdi_storage_device* device);
+int lostio_mst_if_newdev(struct cdi_device* device);
 
 static size_t lostio_mst_read_handler(lostio_filehandle_t* fh,
     void* buf, size_t blocksize, size_t blockcount);
@@ -63,8 +63,6 @@ void cdi_storage_driver_destroy(struct cdi_storage_driver* driver)
 void cdi_storage_driver_register(struct cdi_storage_driver* driver)
 {
     static int initialized = 0;
-    int i;
-    struct cdi_storage_device* device;
 
     cdi_driver_register((struct cdi_driver*) driver);
 
@@ -72,11 +70,32 @@ void cdi_storage_driver_register(struct cdi_storage_driver* driver)
         lostio_mst_if_init();
         initialized = 1;
     }
+}
+
+/**
+ * Initialisiert einen Massenspeicher
+ */
+void cdi_storage_device_init(struct cdi_storage_device* device)
+{
+    device->dev.type = CDI_STORAGE;
 
     // Geraeteknoten fuer LostIO erstellen
-    for (i = 0; (device = cdi_list_get(driver->drv.devices, i)); i++) {
-        lostio_mst_if_newdev(device);
+    lostio_mst_if_newdev(&device->dev);
+}
+
+extern struct cdi_storage_driver cdi_scsi_disk_driver;
+
+static struct cdi_storage_driver* get_storage_drv(struct cdi_device* dev)
+{
+    struct cdi_storage_driver* driver = NULL;
+
+    if (dev->type == CDI_STORAGE) {
+        driver = (struct cdi_storage_driver*) dev->driver;
+    } else if (dev->type == CDI_SCSI) {
+        driver = &cdi_scsi_disk_driver;
     }
+
+    return driver;
 }
 
 /**
@@ -86,12 +105,12 @@ void cdi_storage_driver_register(struct cdi_storage_driver* driver)
  * @param size Anzahl der zu lesenden Bytes
  * @param dest Buffer
  */
-int cdi_storage_read(struct cdi_storage_device* device, uint64_t pos,
+int cdi_storage_read(struct cdi_device* device, uint64_t pos,
     size_t size, void* dest)
 {
-    struct cdi_storage_driver* driver = (struct cdi_storage_driver*) device->
-        dev.driver;
-    size_t block_size = device->block_size;
+    struct cdi_storage_driver* driver = get_storage_drv(device);
+    size_t block_size = driver->get_block_size(device);
+
     // Start- und Endblock
     uint64_t block_read_start = pos / block_size;
     uint64_t block_read_end = (pos + size) / block_size;
@@ -128,13 +147,12 @@ int cdi_storage_read(struct cdi_storage_device* device, uint64_t pos,
  * @param size Anzahl der zu schreibendes Bytes
  * @param src Buffer
  */
-int cdi_storage_write(struct cdi_storage_device* device, uint64_t pos,
+int cdi_storage_write(struct cdi_device* device, uint64_t pos,
     size_t size, void* src)
 {
-    struct cdi_storage_driver* driver = (struct cdi_storage_driver*) device->
-        dev.driver;
-    
-    size_t block_size = device->block_size;
+    struct cdi_storage_driver* driver = get_storage_drv(device);
+    size_t block_size = driver->get_block_size(device);
+
     uint64_t block_write_start = pos / block_size;
     uint8_t buffer[block_size];
     size_t offset;
@@ -206,15 +224,17 @@ static void lostio_mst_if_init()
 /**
  * Erstellt den Dateisystemknoten fuer ein Geraet.
  */
-static int lostio_mst_if_newdev(struct cdi_storage_device* device)
+int lostio_mst_if_newdev(struct cdi_device* device)
 {
+    struct cdi_storage_driver* driver = get_storage_drv(device);
+
     // Slash vor Pfad angaengen
-    char path[strlen(device->dev.name) + 2];
-    strcpy(path + 1, device->dev.name);
+    char path[strlen(device->name) + 2];
+    strcpy(path + 1, device->name);
     *path = '/';
 
-    if (vfstree_create_node(path, CDI_LOSTIO_TYPE_MST, device->block_size *
-        device->block_count, (void*) device, 0) == FALSE)
+    if (vfstree_create_node(path, CDI_LOSTIO_TYPE_MST,
+        driver->get_size(device), (void*) device, 0) == FALSE)
     {
         return -1;
     }
@@ -227,13 +247,19 @@ static int lostio_mst_if_newdev(struct cdi_storage_device* device)
 static size_t lostio_mst_read_handler(lostio_filehandle_t* fh,
     void* buf, size_t blocksize, size_t blockcount)
 {
-    struct cdi_storage_device* device = (struct cdi_storage_device*) fh->node->
-        data;
+    struct cdi_device* device = (struct cdi_device*) fh->node->data;
+    struct cdi_storage_driver* drv = get_storage_drv(device);
+
     size_t size = blocksize * blockcount;
+    size_t devsize = drv->get_size(device);
 
     // Groesse anpassen, wenn ueber das Medium hinaus gelesen werden soll
-    if (size > (device->block_count * device->block_size - fh->pos)) {
-        size = device->block_count * device->block_size - fh->pos;
+    if (size > (devsize - fh->pos)) {
+        size = devsize - fh->pos;
+        if (size == 0) {
+            fh->flags |= LOSTIO_FLAG_EOF;
+            return 0;
+        }
     }
 
     // In den uebergebenen Buffer einlesen
@@ -253,14 +279,16 @@ static size_t lostio_mst_read_handler(lostio_filehandle_t* fh,
 static size_t lostio_mst_write_handler(lostio_filehandle_t* fh,
     size_t blocksize, size_t blockcount, void* data)
 {
-    struct cdi_storage_device* device = (struct cdi_storage_device*) fh->node->
-        data;
+    struct cdi_device* device = (struct cdi_device*) fh->node->data;
+    struct cdi_storage_driver* drv = get_storage_drv(device);
+
     size_t size = blocksize * blockcount;
+    size_t devsize = drv->get_size(device);
     size_t result = size;
 
     // Groesse anpassen, wenn ueber das Medium hinaus geschrieben werden soll
-    if (size > (device->block_count * device->block_size - fh->pos)) {
-        size = device->block_count * device->block_size - fh->pos;
+    if (size > (devsize - fh->pos)) {
+        size = devsize - fh->pos;
     }
 
     // Daten schreiben
@@ -279,10 +307,11 @@ static size_t lostio_mst_write_handler(lostio_filehandle_t* fh,
 static int lostio_mst_seek_handler(lostio_filehandle_t* fh, uint64_t offset,
     int origin)
 {
-    struct cdi_storage_device* device = (struct cdi_storage_device*) fh->node->
-        data;
+    struct cdi_device* device = (struct cdi_device*) fh->node->data;
+    struct cdi_storage_driver* drv = get_storage_drv(device);
+
     uint64_t new_pos = fh->pos;
-    uint64_t size = device->block_size * device->block_count;
+    uint64_t size = drv->get_size(device);
 
     switch (origin)  {
         case SEEK_SET:
-- 
1.5.4.5