[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH v3 4/5] cdi/scsi: Unterstuetzung fuer CD-ROM-Laufwerke
+ cdi/scsi: Unterstuetzung fuer CD-ROM-Laufwerke
---
doc/COPYRIGHT | 23 ++++
src/modules/cdi/include/cdi.h | 3 +
src/modules/cdi/include/cdi/scsi.h | 6 +
src/modules/cdi/lib/scsi/disk.c | 253 ++++++++++++++++++++++++++++++++++++
src/modules/cdi/lib/scsi/driver.c | 12 ++
src/modules/cdi/lib/storage.c | 4 +-
6 files changed, 299 insertions(+), 2 deletions(-)
create mode 100644 src/modules/cdi/lib/scsi/disk.c
diff --git a/doc/COPYRIGHT b/doc/COPYRIGHT
index 66abeb4..a69002f 100644
--- a/doc/COPYRIGHT
+++ b/doc/COPYRIGHT
@@ -129,3 +129,26 @@ Parts of tyndur are derived from ZLib and are distributed under the Zlib terms:
Portions of this software are copyright (c) 2007 The FreeType
Project (www.freetype.org). All rights reserved.
+
+Parts of tyndur are derived from software under the following license:
+
+ 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.
diff --git a/src/modules/cdi/include/cdi.h b/src/modules/cdi/include/cdi.h
index 5fb7025..c6215a6 100644
--- a/src/modules/cdi/include/cdi.h
+++ b/src/modules/cdi/include/cdi.h
@@ -32,6 +32,9 @@ struct cdi_device {
cdi_device_type_t type;
const char* name;
struct cdi_driver* driver;
+
+ // tyndur-spezifisch
+ void* backdev;
};
struct cdi_driver {
diff --git a/src/modules/cdi/include/cdi/scsi.h b/src/modules/cdi/include/cdi/scsi.h
index 9f5b0e7..7b80975 100644
--- a/src/modules/cdi/include/cdi/scsi.h
+++ b/src/modules/cdi/include/cdi/scsi.h
@@ -52,6 +52,12 @@ struct cdi_scsi_device {
/// Geraetetyp, der ueber SCSI angesteuert wird
cdi_device_type_t type;
+ /**
+ * tyndur-spezifisch: Frontend-Geraet (z.B. CDI_STORAGE-Geraet, das ueber
+ * SCSI angesteuert wird)
+ */
+ void* frontdev;
+
};
/// SCSI-Treiber
diff --git a/src/modules/cdi/lib/scsi/disk.c b/src/modules/cdi/lib/scsi/disk.c
new file mode 100644
index 0000000..e82d0d7
--- /dev/null
+++ b/src/modules/cdi/lib/scsi/disk.c
@@ -0,0 +1,253 @@
+/*
+ * 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>
+
+extern int lostio_mst_if_newdev(struct cdi_storage_device* device);
+
+#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_storage_device* device,
+ uint64_t start, uint64_t count, void* buffer);
+
+static int cdi_scsi_disk_write(struct cdi_storage_device* device,
+ uint64_t start, uint64_t count, void* buffer);
+
+struct cdi_storage_driver cdi_scsi_disk_driver = {
+ .read_blocks = cdi_scsi_disk_read,
+ .write_blocks = cdi_scsi_disk_write,
+};
+
+// 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_storage_device* device,
+ uint64_t start, uint64_t count, void* buffer)
+{
+ struct cdi_scsi_device* dev = device->dev.backdev;
+
+ while (count--) {
+ if (cdrom_read_sector(dev, start, buffer)) {
+ return -1;
+ }
+ start ++;
+ buffer += 2048;
+ }
+
+ return 0;
+}
+
+static int cdi_scsi_disk_write(struct cdi_storage_device* device,
+ uint64_t start, uint64_t count, void* buffer)
+{
+ return -1;
+}
+
+int cdi_scsi_disk_init(struct cdi_scsi_device* device)
+{
+ struct cdi_storage_device* frontdev;
+ uint32_t num_sectors = 0, sector_size = 0;
+
+ if (cdrom_init(device)) {
+ return -1;
+ }
+
+ frontdev = calloc(1, sizeof(*frontdev));
+ frontdev->dev.driver = (struct cdi_driver*) &cdi_scsi_disk_driver;
+ frontdev->dev.type = CDI_STORAGE;
+ frontdev->dev.name = device->dev.name;
+
+ cdrom_capacity(device, &num_sectors, §or_size);
+ frontdev->block_size = sector_size;
+ frontdev->block_count = num_sectors;
+
+ frontdev->dev.backdev = device;
+ device->frontdev = frontdev;
+
+ // LostIO-Verzeichnisknoten anlegen
+ lostio_mst_if_newdev(frontdev);
+
+ return 0;
+}
diff --git a/src/modules/cdi/lib/scsi/driver.c b/src/modules/cdi/lib/scsi/driver.c
index 63e1e8c..22d7843 100644
--- a/src/modules/cdi/lib/scsi/driver.c
+++ b/src/modules/cdi/lib/scsi/driver.c
@@ -16,6 +16,8 @@
#include "cdi/scsi.h"
+int cdi_scsi_disk_init(struct cdi_scsi_device* device);
+
/**
* Initialisiert die Datenstrukturen fuer einen SCSI-Treiber
*/
@@ -40,6 +42,16 @@ void cdi_scsi_driver_destroy(struct cdi_scsi_driver* driver)
*/
void cdi_scsi_device_init(struct cdi_scsi_device* device)
{
+ switch (device->type) {
+ case CDI_STORAGE:
+ cdi_scsi_disk_init(device);
+ break;
+
+ default:
+ printf("Kein Frontend fuer SCSI-Geraete des Typs %d\n",
+ device->type);
+ break;
+ }
}
/**
diff --git a/src/modules/cdi/lib/storage.c b/src/modules/cdi/lib/storage.c
index df84be1..88a4528 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_storage_device* device);
static size_t lostio_mst_read_handler(lostio_filehandle_t* fh,
void* buf, size_t blocksize, size_t blockcount);
@@ -210,7 +210,7 @@ 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_storage_device* device)
{
// Slash vor Pfad angaengen
char path[strlen(device->dev.name) + 2];
--
1.5.4.5