diff --git a/headers/os/drivers/Drivers.h b/headers/os/drivers/Drivers.h index 904f33279c..3484dbfdf7 100644 --- a/headers/os/drivers/Drivers.h +++ b/headers/os/drivers/Drivers.h @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008, Haiku Inc. All Rights Reserved. + * Copyright 2002-2011, Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _DRIVERS_DRIVERS_H @@ -105,6 +105,7 @@ enum { B_GET_PATH_FOR_DEVICE, /* get the absolute path of the device */ B_GET_ICON_NAME, /* get an icon name identifier */ B_GET_VECTOR_ICON, /* retrieves the device's vector icon */ + B_GET_DEVICE_NAME, /* get name, string buffer */ B_GET_NEXT_OPEN_DEVICE = 1000, /* obsolete, will be removed */ B_ADD_FIXED_DRIVER, /* obsolete, will be removed */ @@ -172,4 +173,5 @@ typedef struct { } #endif + #endif /* _DRIVERS_DRIVERS_H */ diff --git a/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp b/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp index 8ff706023d..969ed2b328 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp @@ -338,6 +338,16 @@ ATAChannel::ExecuteIO(scsi_ccb *ccb) } +status_t +ATAChannel::Control(uint8 targetID, uint32 opcode, void *buffer, size_t length) +{ + if (targetID < fDeviceCount && fDevices[targetID] != NULL) + return fDevices[targetID]->Control(opcode, buffer, length); + + return B_BAD_VALUE; +} + + status_t ATAChannel::SelectDevice(uint8 device) { diff --git a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp index ce67d0bcd4..e8d509cba7 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp @@ -369,6 +369,28 @@ ATADevice::GetRestrictions(bool *noAutoSense, uint32 *maxBlocks) } +status_t +ATADevice::Control(uint32 opcode, void *buffer, size_t length) +{ + if (opcode == B_GET_DEVICE_NAME) { + // Swap words + char name[sizeof(fInfoBlock.model_number)]; + memcpy(name, fInfoBlock.model_number, sizeof(name)); + swap_words(name, sizeof(name)); + + // Remove trailing spaces + int32 nameLength = sizeof(name) - 2; + while (nameLength > 0 && name[nameLength - 1] == ' ') + nameLength--; + + // TODO: make string prettier, ie. "WDC" -> "Western Digital", ... + return user_strlcpy((char*)buffer, name, + min_c((size_t)nameLength + 1, length)) >= 0 ? B_OK : B_BAD_ADDRESS; + } + return B_BAD_VALUE; +} + + status_t ATADevice::Select() { diff --git a/src/add-ons/kernel/bus_managers/ata/ATAModule.cpp b/src/add-ons/kernel/bus_managers/ata/ATAModule.cpp index 8e7021ae32..82d6fae452 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAModule.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATAModule.cpp @@ -157,8 +157,8 @@ static status_t ata_sim_control(scsi_sim_cookie cookie, uchar targetID, uint32 op, void *buffer, size_t length) { - // TODO implement - return B_BAD_VALUE; + ATAChannel *channel = (ATAChannel *)cookie; + return channel->Control(targetID, op, buffer, length); } diff --git a/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h b/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h index 8f01a4fba7..59cb14a8d5 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h +++ b/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h @@ -76,6 +76,8 @@ public: void GetRestrictions(uint8 targetID, bool *isATAPI, bool *noAutoSense, uint32 *maxBlocks); status_t ExecuteIO(scsi_ccb *ccb); + status_t Control(uint8 targetID, uint32 op, void *buffer, + size_t length); // ATA stuff status_t SelectDevice(uint8 index); @@ -181,6 +183,7 @@ public: void GetRestrictions(bool *noAutoSense, uint32 *maxBlocks); + status_t Control(uint32 op, void *buffer, size_t length); // ATA stuff virtual bool IsATAPI() const { return false; } diff --git a/src/add-ons/kernel/generic/scsi_periph/io.cpp b/src/add-ons/kernel/generic/scsi_periph/io.cpp index 98348f47d1..c110e9dbcd 100644 --- a/src/add-ons/kernel/generic/scsi_periph/io.cpp +++ b/src/add-ons/kernel/generic/scsi_periph/io.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2004-2010, Haiku, Inc. All Rights Reserved. - * Copyright 2002/03, Thomas Kurschel. All rights reserved. + * Copyright 2004-2011, Haiku, Inc. All Rights Reserved. + * Copyright 2002-03, Thomas Kurschel. All rights reserved. * * Distributed under the terms of the MIT License. */ @@ -272,18 +272,50 @@ periph_ioctl(scsi_periph_handle_info *handle, int op, void *buffer, size_t length) { switch (op) { - case B_GET_MEDIA_STATUS: { - status_t res = B_OK; + case B_GET_MEDIA_STATUS: + { + status_t status = B_OK; if (handle->device->removable) - res = periph_get_media_status(handle); + status = periph_get_media_status(handle); - SHOW_FLOW(2, "%s", strerror(res)); + SHOW_FLOW(2, "%s", strerror(status)); - *(status_t *)buffer = res; + *(status_t *)buffer = status; return B_OK; } + case B_GET_DEVICE_NAME: + { + // TODO: this should be written as an attribute to the node + // Try driver further up first + if (handle->device->scsi->ioctl != NULL) { + status_t status = handle->device->scsi->ioctl( + handle->device->scsi_device, op, buffer, length); + if (status == B_OK) + return B_OK; + } + + // If that fails, get SCSI vendor/product + const char* vendor; + if (gDeviceManager->get_attr_string(handle->device->node, + SCSI_DEVICE_VENDOR_ITEM, &vendor, true) == B_OK) { + char name[B_FILE_NAME_LENGTH]; + strlcpy(name, vendor, sizeof(name)); + + const char* product; + if (gDeviceManager->get_attr_string(handle->device->node, + SCSI_DEVICE_PRODUCT_ITEM, &product, true) == B_OK) { + strlcat(name, " ", sizeof(name)); + strlcat(name, product, sizeof(name)); + } + + return user_strlcpy((char*)buffer, name, length) >= 0 + ? B_OK : B_BAD_ADDRESS; + } + return B_ERROR; + } + case B_SCSI_INQUIRY: return inquiry(handle->device, (scsi_inquiry *)buffer); diff --git a/src/system/kernel/disk_device_manager/KDiskDevice.cpp b/src/system/kernel/disk_device_manager/KDiskDevice.cpp index 7f704d68c4..b074b4d1c0 100644 --- a/src/system/kernel/disk_device_manager/KDiskDevice.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDevice.cpp @@ -397,6 +397,10 @@ KDiskDevice::_InitPartitionData() * fDeviceData.geometry.cylinder_count * fDeviceData.geometry.head_count; fPartitionData.flags |= B_PARTITION_IS_DEVICE; + + char name[B_FILE_NAME_LENGTH]; + if (ioctl(fFD, B_GET_DEVICE_NAME, name, sizeof(name)) == B_OK) + fPartitionData.name = strdup(name); }