diff --git a/src/add-ons/kernel/generic/scsi_periph/Jamfile b/src/add-ons/kernel/generic/scsi_periph/Jamfile new file mode 100644 index 0000000000..0f514479a7 --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/Jamfile @@ -0,0 +1,14 @@ +SubDir OBOS_TOP src add-ons kernel generic scsi_periph ; + +UsePrivateHeaders kernel ; + +KernelAddon scsi_periph : kernel generic : + block.c + device_icons.c + device.c + error_handling.c + handle.c + io.c + removable.c + scsi_periph.c + ; diff --git a/src/add-ons/kernel/generic/scsi_periph/block.c b/src/add-ons/kernel/generic/scsi_periph/block.c new file mode 100644 index 0000000000..ef02e3b88a --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/block.c @@ -0,0 +1,95 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI Peripheral Driver + + Handling of block device (currently, only a capacity check is provided) +*/ + + +#include "scsi_periph_int.h" +#include + + +status_t +periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request) +{ + scsi_res_read_capacity capacity_res; + scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb; + uint64 capacity; + uint32 block_size; + status_t res; + + SHOW_FLOW(3, "%p, %p", device, request); + + // driver doesn't support capacity callback - seems to be no block + // device driver, so ignore + if (device->callbacks->set_capacity == NULL) + return B_OK; + + request->flags = SCSI_DIR_IN; + + request->data = (char *)&capacity_res; + request->data_len = sizeof(capacity_res); + request->cdb_len = sizeof(scsi_cmd_read_capacity); + request->timeout = device->std_timeout; + request->sort = -1; + request->sg_list = NULL; + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = SCSI_OP_READ_CAPACITY; + // we don't set PMI (partial medium indicator) as we want the whole capacity; + // in this case, all other parameters must be zero + + res = periph_safe_exec(device, request); + + if (res == B_DEV_MEDIA_CHANGED) { + // in this case, the error handler has already called check_capacity + // recursively, so we ignore our (invalid) result + SHOW_FLOW0( 3, "ignore result because medium change" ); + return B_DEV_MEDIA_CHANGED; + } + + ACQUIRE_BEN(&device->mutex); + + if (res == B_OK && request->data_resid == 0) { + capacity = (capacity_res.top_LBA << 24) + | (capacity_res.high_LBA << 16) + | (capacity_res.mid_LBA << 8) + | capacity_res.low_LBA; + + // the command returns the index of the _last_ block, + // i.e. the size is one larger + ++capacity; + + block_size = (capacity_res.top_block_size << 24) + | (capacity_res.high_block_size << 16) + | (capacity_res.mid_block_size << 8) + | capacity_res.low_block_size; + } else { + capacity = 0; + block_size = 0; + } + + SHOW_FLOW(3, "capacity = %Ld, block_size = %ld", capacity, block_size); + + device->callbacks->set_capacity(device->periph_device, + capacity, block_size); + +/* device->byte2blk_shift = log2( device->block_size ); + if( device->byte2blk_shift < 0 ) { + // this may be too restrictive... + device->capacity = -1; + return ERR_DEV_GENERAL; + }*/ + + RELEASE_BEN(&device->mutex); + + SHOW_FLOW(3, "done (%s)", strerror(res)); + + return res; +} + diff --git a/src/add-ons/kernel/generic/scsi_periph/device.c b/src/add-ons/kernel/generic/scsi_periph/device.c new file mode 100644 index 0000000000..92e1fa7b67 --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/device.c @@ -0,0 +1,103 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI Peripheral Driver + + Basic handling of device. +*/ + + +#include "scsi_periph_int.h" + +#include + +#include +#include +#include + +#define SCSI_PERIPH_STD_TIMEOUT 10 + + +char * +periph_compose_device_name(pnp_node_handle node, const char *prefix) +{ + uint8 path_id, target_id, target_lun; + + if (pnp->get_attr_uint8(node, SCSI_BUS_PATH_ID_ITEM, &path_id, true) != B_OK + || pnp->get_attr_uint8(node, SCSI_DEVICE_TARGET_ID_ITEM, &target_id, true) != B_OK + || pnp->get_attr_uint8(node, SCSI_DEVICE_TARGET_LUN_ITEM, &target_lun, true) != B_OK) + return NULL; + + { + char name_buffer[100]; + sprintf(name_buffer, "%s/%d/%d/%d/raw", prefix, path_id, target_id, target_lun); + + return strdup(name_buffer); + } +} + + +status_t +periph_register_device(periph_device_cookie periph_device, scsi_periph_callbacks *callbacks, + scsi_device scsi_device, scsi_device_interface *scsi, pnp_node_handle node, + bool removable, scsi_periph_device *driver) +{ + scsi_periph_device_info *device; + status_t res; + + SHOW_FLOW0( 3, "" ); + + device = (scsi_periph_device_info *)malloc(sizeof(*device)); + if (device == NULL) + return B_NO_MEMORY; + + memset(device, 0, sizeof(*device)); + + if (INIT_BEN(&device->mutex, "SCSI_PERIPH") != B_OK) { + res = B_NO_MEMORY; + goto err1; + } + + device->scsi_device = scsi_device; + device->scsi = scsi; + device->periph_device = periph_device; + device->removal_requested = false; + device->callbacks = callbacks; + device->node = node; + device->removable = removable; + device->std_timeout = SCSI_PERIPH_STD_TIMEOUT; + + // set some default options + device->next_tag_action = 0; + device->rw10_enabled = true; + + // launch sync daemon + res = register_kernel_daemon(periph_sync_queue_daemon, device, 60*10); + if (res != B_OK) + goto err2; + + *driver = device; + + SHOW_FLOW0(3, "done"); + + return B_OK; + +err2: + DELETE_BEN(&device->mutex); +err1: + free(device); + return res; +} + + +status_t +periph_unregister_device(scsi_periph_device_info *device) +{ + unregister_kernel_daemon(periph_sync_queue_daemon, device); + free(device); + + return B_OK; +} diff --git a/src/add-ons/kernel/generic/scsi_periph/device_icons.c b/src/add-ons/kernel/generic/scsi_periph/device_icons.c new file mode 100644 index 0000000000..13493b2132 --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/device_icons.c @@ -0,0 +1,393 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI Peripheral Driver + + Icons for various types of peripheral devices. +*/ + + +#include "scsi_periph_int.h" +#include + + +const char icon_disk[32*32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x0f, 0x00, 0xff, 0xff, + 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, + 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, + 0x00, 0x3f, 0x3f, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0xff, 0xff, + 0x00, 0x15, 0x15, 0x3f, 0x3f, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, + 0x00, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, + 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, + 0x00, 0x15, 0x15, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, + 0x1a, 0x1a, 0x3f, 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, + 0x00, 0x15, 0x15, 0x39, 0x35, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f, 0x1a, 0x1a, 0x1a, + 0x1a, 0x3f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, + 0x00, 0x15, 0x15, 0x35, 0x35, 0x2b, 0x2b, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f, 0x1a, + 0x3f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x3f, + 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1a, + 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1a, + 0x15, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1a, + 0x15, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x1a, + 0x15, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x1a, + 0x15, 0x0f, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1a, + 0x15, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +const char icon_disk_mini[16*16] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x00, 0xff, + 0xff, 0x00, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x0f, 0x00, 0xff, + 0x00, 0x3f, 0x3f, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x0f, 0x0f, 0x00, 0xff, + 0x00, 0x15, 0x15, 0x3f, 0x3f, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x3f, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, + 0x00, 0x15, 0x15, 0x15, 0x15, 0x3f, 0x3f, 0x1a, 0x1a, 0x3f, 0x0e, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, + 0x00, 0x15, 0x35, 0x2b, 0x15, 0x15, 0x15, 0x3f, 0x3f, 0x0e, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0xff, + 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15, 0x0f, 0x0f, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x0f, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +const char icon_removable[32*32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x13, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x13, 0x13, 0x00, + 0x13, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x13, 0x13, 0x00, 0x13, + 0x13, 0x13, 0x13, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x10, 0x10, 0x00, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x13, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0x10, 0x15, 0x00, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x10, 0x10, 0x13, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0x15, 0x15, 0x00, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x10, 0x10, 0x13, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x10, 0x15, 0x00, 0x23, 0x23, 0x23, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x10, 0x13, 0x13, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x10, 0x15, 0x15, 0x00, 0x00, 0x23, 0x23, 0x23, 0x23, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x10, 0x13, 0x00, 0x1f, 0x13, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x10, 0x15, 0x15, 0x15, 0x1f, 0x1f, 0x00, 0x00, 0x23, 0x23, + 0x23, 0x23, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x10, 0x00, 0x1f, 0x13, 0x13, 0x3f, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x13, 0x13, 0x10, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1f, 0x1f, 0x00, 0x00, + 0x23, 0x23, 0x23, 0x23, 0x15, 0x15, 0x15, 0x15, 0x00, 0x1f, 0x13, 0x13, 0x3f, 0x0a, 0x00, 0x10, + 0xff, 0xff, 0x00, 0x13, 0x13, 0x10, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1f, 0x1f, + 0x00, 0x00, 0x23, 0x23, 0x23, 0x23, 0x23, 0x00, 0x1f, 0x13, 0x13, 0x3f, 0x0a, 0x0a, 0x00, 0x10, + 0xff, 0x00, 0x13, 0x13, 0x13, 0x10, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x1f, 0x1f, 0x00, 0x00, 0x23, 0x23, 0x00, 0x1f, 0x10, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, + 0x00, 0x13, 0x13, 0x13, 0x13, 0x13, 0x10, 0x15, 0x15, 0x15, 0x15, 0x00, 0x0a, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x1f, 0x1f, 0x00, 0x00, 0x1f, 0x10, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, + 0x00, 0x3f, 0x3f, 0x13, 0x13, 0x13, 0x13, 0x10, 0x15, 0x15, 0x00, 0x00, 0x3f, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x10, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, + 0x00, 0x10, 0x10, 0x3f, 0x3f, 0x13, 0x13, 0x13, 0x10, 0x00, 0x00, 0x3f, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x10, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, + 0x00, 0x10, 0x10, 0x10, 0x10, 0x3f, 0x3f, 0x13, 0x13, 0x10, 0x10, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x15, 0x15, 0x15, 0x10, 0x10, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x3f, 0x3f, 0x13, 0x13, 0x10, 0x10, 0x10, 0x15, 0x15, + 0x10, 0x10, 0x10, 0x13, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x3f, 0x3f, 0x13, 0x13, 0x13, 0x10, 0x10, + 0x13, 0x13, 0x13, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x10, 0x00, 0x0a, 0x0a, 0x3f, 0x3f, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x3f, 0x3f, 0x13, + 0x13, 0x13, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x3f, + 0x3f, 0x3f, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x10, 0x0a, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x10, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +const char icon_removable_mini[16*16] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x13, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x13, 0x13, 0x00, 0x10, 0x13, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x13, 0x13, 0x00, 0x15, 0x15, 0x15, 0x10, 0x13, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x13, 0x10, 0x00, 0x23, 0x15, 0x15, 0x15, 0x15, 0x15, 0x10, 0x00, 0x00, 0x00, + 0xff, 0x00, 0x13, 0x10, 0x15, 0x15, 0x00, 0x00, 0x23, 0x15, 0x15, 0x15, 0x00, 0x15, 0x0a, 0x00, + 0x00, 0x13, 0x10, 0x15, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0x23, 0x00, 0x13, 0x0a, 0x0a, 0x00, + 0x00, 0x3f, 0x13, 0x10, 0x15, 0x00, 0x3f, 0x15, 0x15, 0x15, 0x00, 0x15, 0x0a, 0x0a, 0x00, 0x10, + 0x00, 0x10, 0x3f, 0x3f, 0x00, 0x3f, 0x15, 0x15, 0x15, 0x10, 0x15, 0x0a, 0x0a, 0x00, 0x10, 0xff, + 0x00, 0x00, 0x10, 0x10, 0x3f, 0x3f, 0x10, 0x10, 0x10, 0x15, 0x0a, 0x0a, 0x00, 0x0e, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x10, 0x0a, 0x3f, 0x3f, 0x15, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +const char icon_floppy[32*32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x0e, + 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x00, 0x0f, + 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x04, 0x00, 0x00, + 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x04, 0x00, 0x2d, 0x2e, + 0x2d, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x04, 0x00, 0x3f, 0x3f, 0x2d, + 0x2e, 0x2d, 0xd2, 0x00, 0x00, 0x0e, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x04, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0xd2, 0xd2, 0xd2, 0xd2, 0x00, 0x00, 0x0e, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x04, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0xd2, 0xd2, 0xd2, 0xd2, 0x00, 0x00, 0x0e, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x04, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xd2, 0xd2, 0x00, 0x17, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0e, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x0a, 0x0b, 0x17, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x17, 0x0b, 0x0a, 0x0b, 0x00, 0x0f, 0x0f, 0x0e, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x0a, 0x0b, 0x0b, 0x0a, 0x18, 0x17, 0x00, 0x00, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x17, 0x0b, 0x0a, 0x0b, 0x04, 0x00, 0x0f, 0x0f, 0x0f, 0xff, + 0xff, 0xff, 0x00, 0x0a, 0x0b, 0x0a, 0x0b, 0x0b, 0x0a, 0x0b, 0x0b, 0x0a, 0x18, 0x17, 0x00, 0x00, + 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x17, 0x0b, 0x0a, 0x0b, 0x04, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, + 0xff, 0x00, 0x0a, 0x0b, 0x0a, 0x0b, 0x15, 0x00, 0x00, 0x0b, 0x0b, 0x0a, 0x0b, 0x0a, 0x18, 0x17, + 0x00, 0x00, 0x3f, 0x00, 0x17, 0x0b, 0x0a, 0x0b, 0x04, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, + 0x00, 0x0a, 0x0b, 0x0a, 0x0b, 0x15, 0x00, 0x18, 0x17, 0x00, 0x00, 0x0b, 0x0a, 0x0b, 0x0b, 0x0a, + 0x18, 0x17, 0x00, 0x17, 0x0b, 0x0b, 0x0a, 0x04, 0x05, 0x00, 0x0f, 0x0e, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x3f, 0x3f, 0x0a, 0x15, 0x00, 0x18, 0x17, 0x04, 0x0b, 0x17, 0x00, 0x00, 0x0b, 0x0b, 0x0a, + 0x0b, 0x0b, 0x17, 0x0b, 0x0a, 0x0b, 0x04, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x15, 0x15, 0x3f, 0x00, 0x17, 0x17, 0x05, 0x00, 0x04, 0x17, 0x18, 0x17, 0x00, 0x00, 0x0b, + 0x0a, 0x0b, 0x0a, 0x0b, 0x0b, 0x04, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x15, 0x00, 0x3f, 0x3f, 0x00, 0x04, 0x17, 0x18, 0x17, 0x17, 0x18, 0x17, 0x00, + 0x0b, 0x0a, 0x0b, 0x0b, 0x04, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x3f, 0x3f, 0x17, 0x17, 0x18, 0x17, 0x17, 0x00, 0x18, + 0x0a, 0x0b, 0x0b, 0x04, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x3f, 0x3f, 0x17, 0x17, 0x00, 0x18, 0x0a, + 0x0b, 0x0b, 0x04, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x3f, 0x00, 0x17, 0x0b, 0x0a, + 0x0b, 0x04, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x00, 0x3f, 0x3f, 0x0a, + 0x04, 0x05, 0x00, 0x0f, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x15, 0x04, + 0x05, 0x00, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x04, + 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +const char icon_floppy_mini[16*16] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x0e, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x2d, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x3f, 0x2d, 0x2e, 0x2d, 0x00, 0x00, 0x0e, 0x0f, 0x0f, 0xff, + 0xff, 0xff, 0x00, 0x0a, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0xd2, 0xd2, 0xd2, 0x00, 0x00, 0x0e, 0x0f, + 0xff, 0x00, 0x0a, 0x0b, 0x0a, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x0a, 0x00, 0x0f, 0x0f, + 0x00, 0x0b, 0x0a, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, 0x3f, 0x00, 0x0a, 0x04, 0x00, 0x0f, 0x0f, + 0x00, 0x3f, 0x00, 0x17, 0x17, 0x00, 0x00, 0x0b, 0x0b, 0x00, 0x0a, 0x04, 0x00, 0x0f, 0x0f, 0xff, + 0x00, 0x15, 0x00, 0x3f, 0x3f, 0x17, 0x17, 0x00, 0x0b, 0x0b, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x15, 0x15, 0x3f, 0x3f, 0x00, 0x0a, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x15, 0x00, 0x0a, 0x05, 0x00, 0x0f, 0x0e, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +const char icon_cd[32*32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1d, 0x1e, 0x1e, 0x19, 0x1a, 0x19, 0x1a, 0x1a, + 0x1a, 0x1a, 0x1a, 0x1d, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x19, 0x1a, 0x19, 0x1a, 0x19, 0x1a, 0x1a, + 0x1a, 0x1a, 0x19, 0x3f, 0x3f, 0x19, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x1d, 0x1e, 0x3f, 0x3f, 0x3f, 0x3f, 0x19, 0x1a, 0x19, 0x1a, 0x1a, 0x1a, + 0x1a, 0x19, 0x1a, 0x3f, 0x19, 0x1a, 0x19, 0x3f, 0x1e, 0x1e, 0x00, 0x0e, 0x0e, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x1d, 0x1a, 0x19, 0x1a, 0x3f, 0x3f, 0x3f, 0x3f, 0x19, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x3f, 0x3f, 0x19, 0x3f, 0x3f, 0x1a, 0x19, 0x1a, 0x1d, 0x00, 0x0f, 0x0e, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x1d, 0x1a, 0x19, 0x1a, 0x19, 0x1a, 0x3f, 0x14, 0x14, 0x1e, 0x1e, 0x1e, 0x1d, + 0x1e, 0x1e, 0x14, 0x14, 0x3f, 0x1a, 0x19, 0x1a, 0x19, 0x1a, 0x1e, 0x00, 0x0e, 0x0f, 0xff, 0xff, + 0xff, 0x00, 0x60, 0x60, 0x41, 0x41, 0x19, 0x1a, 0x19, 0x1a, 0x14, 0x1e, 0x1d, 0x09, 0x00, 0x00, + 0x08, 0x1e, 0x3f, 0x14, 0x19, 0x1a, 0x19, 0x1a, 0x41, 0x41, 0x60, 0x60, 0x00, 0x0f, 0x0f, 0xff, + 0xff, 0x00, 0x60, 0x60, 0x41, 0x41, 0x44, 0x44, 0xd8, 0x14, 0x1e, 0x1e, 0x00, 0x0f, 0x0f, 0x0f, + 0x0f, 0x08, 0x1e, 0x1e, 0x14, 0xd8, 0x44, 0x44, 0x41, 0x41, 0x60, 0x60, 0x00, 0x0f, 0x0f, 0xff, + 0xff, 0x00, 0x60, 0x60, 0x41, 0x41, 0x44, 0x44, 0xd8, 0x14, 0x1e, 0x1d, 0x00, 0x0f, 0xff, 0xff, + 0xff, 0x00, 0x1e, 0x1d, 0x14, 0xd8, 0x44, 0x44, 0x41, 0x41, 0x60, 0x60, 0x00, 0x0e, 0x0f, 0xff, + 0xff, 0x00, 0x60, 0x60, 0x41, 0x41, 0x19, 0x1a, 0x19, 0x1a, 0x14, 0x1e, 0x1d, 0x09, 0x00, 0x00, + 0x08, 0x1e, 0x1e, 0x14, 0x19, 0x19, 0x1a, 0x19, 0x41, 0x41, 0x60, 0x60, 0x00, 0x0f, 0x0f, 0xff, + 0xff, 0xff, 0x00, 0x1a, 0x19, 0x1a, 0x19, 0x1a, 0x19, 0x1a, 0x14, 0x14, 0x1e, 0x1e, 0x1e, 0x1d, + 0x1e, 0x1e, 0x14, 0x14, 0x3f, 0x19, 0x19, 0x19, 0x1a, 0x19, 0x1a, 0x00, 0x0f, 0x0f, 0x0f, 0xff, + 0xff, 0xff, 0x00, 0x1d, 0x1d, 0x1a, 0x19, 0x1a, 0x1a, 0x3f, 0x19, 0x3f, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0x19, 0x3f, 0x3f, 0x3f, 0x3f, 0x19, 0x19, 0x3f, 0x1d, 0x00, 0x0f, 0x0f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x1d, 0x1e, 0x1a, 0x3f, 0x3f, 0x1a, 0x19, 0x3f, 0x3f, 0x1a, 0x19, 0x19, + 0x19, 0x19, 0x1a, 0x19, 0x3f, 0x3f, 0x3f, 0x3f, 0x1d, 0x1e, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x3f, 0x1d, 0x1a, 0x19, 0x3f, 0x3f, 0x19, 0x1a, 0x19, 0x19, + 0x19, 0x19, 0x1a, 0x19, 0x1a, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1d, 0x1e, 0x1e, 0x19, 0x1a, 0x19, 0x19, 0x19, + 0x19, 0x19, 0x1a, 0x1d, 0x1e, 0x1e, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, + 0x1e, 0x1e, 0x1e, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +const char icon_cd_mini[16*16] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1d, 0x00, 0x00, 0x0f, 0xff, 0xff, + 0xff, 0x00, 0x1d, 0x1e, 0x1a, 0x1a, 0x18, 0x18, 0x18, 0x19, 0x19, 0x1e, 0x1e, 0x00, 0x0f, 0xff, + 0x00, 0x60, 0x41, 0x1a, 0x3f, 0x14, 0x1d, 0x00, 0x1d, 0x14, 0x3f, 0x19, 0x41, 0x60, 0x00, 0x0f, + 0x00, 0x60, 0x41, 0x44, 0xd8, 0x1e, 0x00, 0xff, 0x00, 0x1e, 0xd8, 0x44, 0x41, 0x60, 0x00, 0x0f, + 0x00, 0x60, 0x41, 0x44, 0x18, 0x14, 0x1e, 0x00, 0x1e, 0x14, 0x1d, 0x44, 0x41, 0x60, 0x00, 0x0f, + 0x00, 0x1d, 0x1a, 0x19, 0x19, 0x3f, 0x18, 0x18, 0x18, 0x3f, 0x1d, 0x1a, 0x19, 0x1d, 0x00, 0x0f, + 0xff, 0x00, 0x1d, 0x1e, 0x3f, 0x19, 0x19, 0x18, 0x18, 0x18, 0x3f, 0x1d, 0x1d, 0x00, 0x0f, 0x0f, + 0xff, 0xff, 0x00, 0x00, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1d, 0x00, 0x00, 0x0f, 0x0f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static struct { + const char *large; + const char *small; +} icons[] = { + { icon_disk, icon_disk_mini }, + { icon_removable, icon_removable_mini }, + { icon_floppy, icon_floppy_mini }, + { icon_cd, icon_cd_mini } +}; + + +status_t +periph_get_icon(icon_type type, device_icon *data) +{ + SHOW_FLOW( 3, "%d", type ); + + if (type < 0 || type >= sizeof(icons) / sizeof(icons[0])) + return B_BAD_INDEX; + + switch (data->icon_size) { + case 32: + memcpy(data->icon_data, icons[type].large, 32*32); + return B_OK; + + case 16: + memcpy(data->icon_data, icons[type].small, 16*16); + return B_OK; + + default: + return B_BAD_VALUE; + } +} + diff --git a/src/add-ons/kernel/generic/scsi_periph/device_icons.h b/src/add-ons/kernel/generic/scsi_periph/device_icons.h new file mode 100644 index 0000000000..0e8f142f1e --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/device_icons.h @@ -0,0 +1,9 @@ +#ifndef __DEVICE_ICONS_H__ +#define __DEVICE_ICONS_H__ + +const char icon_removable[32*32]; +const char icon_disc[32*32]; +const char icon_removable_mini[16*16]; +const char icon_disc_mini[16*16]; + +#endif diff --git a/src/add-ons/kernel/generic/scsi_periph/dl_list.h b/src/add-ons/kernel/generic/scsi_periph/dl_list.h new file mode 100644 index 0000000000..36a0d22da9 --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/dl_list.h @@ -0,0 +1,88 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Macros for double linked lists +*/ + +#ifndef _DL_LIST_H +#define _DL_LIST_H + +#define REMOVE_DL_LIST( item, head, prefix ) \ + do { \ + if( item->prefix##prev ) \ + item->prefix##prev->prefix##next = item->prefix##next; \ + else \ + head = item->prefix##next; \ +\ + if( item->prefix##next ) \ + item->prefix##next->prefix##prev = item->prefix##prev; \ + } while( 0 ) + +#define ADD_DL_LIST_HEAD( item, head, prefix ) \ + do { \ + item->prefix##next = head; \ + item->prefix##prev = NULL; \ +\ + if( (head) ) \ + (head)->prefix##prev = item; \ +\ + (head) = item; \ + } while( 0 ) + +#define REMOVE_CDL_LIST( item, head, prefix ) \ + do { \ + item->prefix##next->prefix##prev = item->prefix##prev; \ + item->prefix##prev->prefix##next = item->prefix##next; \ + \ + if( item == (head) ) { \ + if( item->prefix##next != item ) \ + (head) = item->prefix##next; \ + else \ + (head) = NULL; \ + } \ + } while( 0 ) + +#define ADD_CDL_LIST_TAIL( item, type, head, prefix ) \ + do { \ + type *old_head = head; \ + \ + if( old_head ) { \ + type *first, *last; \ + \ + first = old_head; \ + last = first->prefix##prev; \ + \ + item->prefix##next = first; \ + item->prefix##prev = last; \ + first->prefix##prev = item; \ + last->prefix##next = item; \ + } else { \ + head = item; \ + item->prefix##next = item->prefix##prev = item; \ + } \ + } while( 0 ) + +#define ADD_CDL_LIST_HEAD( item, type, head, prefix ) \ + do { \ + type *old_head = head; \ + \ + head = item; \ + if( old_head ) { \ + type *first, *last; \ + \ + first = old_head; \ + last = first->prefix##prev; \ + \ + item->prefix##next = first; \ + item->prefix##prev = last; \ + first->prefix##prev = item; \ + last->prefix##next = item; \ + } else { \ + item->prefix##next = item->prefix##prev = item; \ + } \ + } while( 0 ) + +#endif diff --git a/src/add-ons/kernel/generic/scsi_periph/error_handling.c b/src/add-ons/kernel/generic/scsi_periph/error_handling.c new file mode 100644 index 0000000000..116e6fcb36 --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/error_handling.c @@ -0,0 +1,326 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI Peripheral Driver + + Error handling +*/ + +#include "scsi_periph_int.h" + +#include + + +/** decode sense data and generate error code */ + +static +err_res check_sense(scsi_periph_device_info *device, scsi_ccb *request) +{ + scsi_sense *sense = (scsi_sense *)request->sense; + + if ((request->subsys_status & SCSI_AUTOSNS_VALID) == 0) { + SHOW_ERROR0(2, "No auto-sense (but there should be)"); + + // shouldn't happen (cam_status should be CAM_AUTOSENSE_FAIL + // as we asked for autosense) + return MK_ERROR(err_act_fail, B_ERROR); + } + + if (SCSI_MAX_SENSE_SIZE - request->sense_resid + < (int)offsetof(scsi_sense, add_sense_length) + 1) { + SHOW_ERROR(2, "sense too short (%d bytes)", SCSI_MAX_SENSE_SIZE - request->sense_resid); + + // that's a bit too short + return MK_ERROR(err_act_fail, B_ERROR); + } + + switch (sense->error_code) { + case SCSIS_DEFERRED_ERROR: + // we are doomed - some previous request turned out to have failed + // we neither know which one nor can we resubmit it + SHOW_ERROR0(2, "encountered DEFERRED ERROR - bye, bye"); + return MK_ERROR(err_act_ok, B_OK); + + case SCSIS_CURR_ERROR: + // we start with very specific and finish very general error infos + switch ((sense->asc << 8) | sense->ascq) { + case SCSIS_ASC_AUDIO_PLAYING: + SHOW_INFO0(2, "busy because playing audio"); + + // we need something like "busy" + return MK_ERROR(err_act_fail, B_DEV_NOT_READY); + + case SCSIS_ASC_LUN_NEED_INIT: + SHOW_INFO0(2, "LUN needs init"); + + // reported by some devices that are idle and spun down + // sending START UNIT should awake them + return MK_ERROR(err_act_start, B_NO_INIT); + + case SCSIS_ASC_LUN_NEED_MANUAL_HELP: + SHOW_ERROR0(2, "LUN needs manual help"); + + return MK_ERROR(err_act_fail, B_DEV_NOT_READY); + + case SCSIS_ASC_LUN_FORMATTING: + SHOW_INFO0(2, "LUN is formatting"); + + // we could wait, but as formatting normally takes quite long, + // we give up without any further retries + return MK_ERROR(err_act_fail, B_DEV_NOT_READY); + + case SCSIS_ASC_MEDIUM_CHANGED: + SHOW_FLOW0(3, "Medium changed"); + periph_media_changed(device, request); + return MK_ERROR(err_act_fail, B_DEV_MEDIA_CHANGED); + + case SCSIS_ASC_WRITE_ERR_AUTOREALLOC: + SHOW_ERROR0(2, "Recovered write error - block got reallocated automatically"); + return MK_ERROR(err_act_ok, B_OK); + + case SCSIS_ASC_ID_RECOV: + SHOW_ERROR0(2, "Recovered ID with ECC"); + return MK_ERROR(err_act_ok, B_OK); + + case SCSIS_ASC_REMOVAL_REQUESTED: + SHOW_INFO0(2, "Removal requested"); + ACQUIRE_BEN(&device->mutex); + device->removal_requested = true; + RELEASE_BEN(&device->mutex); + + return MK_ERROR(err_act_retry, B_DEV_MEDIA_CHANGE_REQUESTED); + + case SCSIS_ASC_LUN_BECOMING_READY: + SHOW_INFO0(2, "Becoming ready"); + // wait a bit - the device needs some time + snooze(100000); + return MK_ERROR(err_act_many_retries, B_DEV_NOT_READY); + + case SCSIS_ASC_WAS_RESET: + SHOW_INFO0(2, "Unit was reset"); + // TBD: need a better error code here + // as some earlier command led to the reset, we are innocent + return MK_ERROR(err_act_retry, B_DEV_NOT_READY); + } + + switch (sense->asc) { + case SCSIS_ASC_DATA_RECOV_NO_ERR_CORR >> 8: + case SCSIS_ASC_DATA_RECOV_WITH_CORR >> 8: + // these are the groups of recovered data with or without correction + // we should print at least a warning here + SHOW_ERROR(0, "Recovered data, asc=0x%2x, ascq=0x%2x", + sense->asc, sense->ascq); + return MK_ERROR(err_act_ok, B_OK); + + case SCSIS_ASC_WRITE_PROTECTED >> 8: + SHOW_ERROR0( 2, "Write protected" ); + + // isn't there any proper "write protected" error code? + return MK_ERROR(err_act_fail, B_READ_ONLY_DEVICE); + + case SCSIS_ASC_NO_MEDIUM >> 8: + SHOW_FLOW0(2, "No medium"); + return MK_ERROR(err_act_fail, B_DEV_NO_MEDIA); + } + + // we issue this info very late, so we don't clutter syslog with + // messages about changed or missing media + SHOW_ERROR(3, "0x%04x", (sense->asc << 8) | sense->ascq); + + switch (sense->sense_key) { + case SCSIS_KEY_NO_SENSE: + SHOW_ERROR0(2, "No sense"); + + // we thought there was an error, huh? + return MK_ERROR(err_act_ok, B_OK); + + case SCSIS_KEY_RECOVERED_ERROR: + SHOW_ERROR0(2, "Recovered error"); + + // we should probably tell about that; perhaps tomorrow + return MK_ERROR(err_act_ok, B_OK); + + case SCSIS_KEY_NOT_READY: + return MK_ERROR(err_act_retry, B_DEV_NOT_READY); + + case SCSIS_KEY_MEDIUM_ERROR: + SHOW_ERROR0(2, "Medium error"); + return MK_ERROR( err_act_retry, B_DEV_RECALIBRATE_ERROR); + + case SCSIS_KEY_HARDWARE_ERROR: + SHOW_ERROR0(2, "Hardware error"); + return MK_ERROR(err_act_retry, B_DEV_SEEK_ERROR); + + case SCSIS_KEY_ILLEGAL_REQUEST: + SHOW_ERROR0(2, "Illegal request"); + return MK_ERROR(err_act_invalid_req, B_ERROR); + + case SCSIS_KEY_UNIT_ATTENTION: + SHOW_ERROR0(2, "Unit attention"); + return MK_ERROR( err_act_retry, B_DEV_NOT_READY); + + case SCSIS_KEY_DATA_PROTECT: + SHOW_ERROR0(2, "Data protect"); + + // we could set "permission denied", but that's probably + // irritating to the user + return MK_ERROR(err_act_fail, B_NOT_ALLOWED); + + case SCSIS_KEY_BLANK_CHECK: + SHOW_ERROR0(2, "Is blank"); + + return MK_ERROR(err_act_fail, B_DEV_UNREADABLE); + + case SCSIS_KEY_VENDOR_SPECIFIC: + return MK_ERROR(err_act_fail, B_ERROR); + + case SCSIS_KEY_COPY_ABORTED: + // we don't use copy, so this is really wrong + return MK_ERROR(err_act_fail, B_ERROR); + + case SCSIS_KEY_ABORTED_COMMAND: + // proper error code? + return MK_ERROR(err_act_retry, B_ERROR); + + case SCSIS_KEY_EQUAL: + case SCSIS_KEY_MISCOMPARE: + // we don't search, so this is really wrong + return MK_ERROR(err_act_fail, B_ERROR); + + case SCSIS_KEY_VOLUME_OVERFLOW: + // not the best return code, but this error doesn't apply + // to devices we currently support + return MK_ERROR(err_act_fail, B_DEV_SEEK_ERROR); + + case SCSIS_KEY_RESERVED: + default: + return MK_ERROR(err_act_fail, B_ERROR); + } + + default: + // shouldn't happen - there are only 2 error codes defined + SHOW_ERROR(2, "Invalid sense type (0x%x)", sense->error_code); + return MK_ERROR(err_act_fail, B_ERROR); + } +} + + +/** check scsi status, using sense if available */ + +static err_res +check_scsi_status(scsi_periph_device_info *device, scsi_ccb *request) +{ + SHOW_FLOW(3, "%d", request->device_status & SCSI_STATUS_MASK); + + switch (request->device_status & SCSI_STATUS_MASK) { + case SCSI_STATUS_GOOD: + // shouldn't happen (cam_status should be CAM_REQ_CMP) + return MK_ERROR(err_act_ok, B_OK); + + case SCSI_STATUS_CHECK_CONDITION: + return check_sense(device, request); + + case SCSI_STATUS_QUEUE_FULL: + // SIM should have automatically requeued request, fall through + case SCSI_STATUS_BUSY: + // take deep breath and try again + snooze(1000000); + return MK_ERROR(err_act_retry, B_DEV_TIMEOUT); + + case SCSI_STATUS_COMMAND_TERMINATED: + return MK_ERROR(err_act_retry, B_INTERRUPTED); + + default: + return MK_ERROR(err_act_retry, B_ERROR); + } +} + + +/** check result of request + * 1. check SCSI subsystem problems + * 2. if request hit device, check SCSI status + * 3. if request got executed, check sense + */ + +err_res +periph_check_error(scsi_periph_device_info *device, scsi_ccb *request) +{ + SHOW_FLOW(4, "%d", request->subsys_status & SCSI_SUBSYS_STATUS_MASK); + + switch (request->subsys_status & SCSI_SUBSYS_STATUS_MASK) { + // everything is ok + case SCSI_REQ_CMP: + return MK_ERROR(err_act_ok, B_OK); + + // no device + case SCSI_LUN_INVALID: + case SCSI_TID_INVALID: + case SCSI_PATH_INVALID: + case SCSI_DEV_NOT_THERE: + case SCSI_NO_HBA: + SHOW_ERROR0(2, "No device"); + return MK_ERROR(err_act_fail, B_DEV_BAD_DRIVE_NUM); + + // device temporary unavailable + case SCSI_SEL_TIMEOUT: + case SCSI_BUSY: + case SCSI_SCSI_BUSY: + case SCSI_HBA_ERR: + case SCSI_MSG_REJECT_REC: + case SCSI_NO_NEXUS: + case SCSI_FUNC_NOTAVAIL: + case SCSI_RESRC_UNAVAIL: + // take a deep breath and hope device becomes ready + snooze(1000000); + return MK_ERROR(err_act_retry, B_DEV_TIMEOUT); + + // data transmission went wrong + case SCSI_DATA_RUN_ERR: + case SCSI_UNCOR_PARITY: + SHOW_ERROR0(2, "Data transmission failed"); + // retry immediately + return MK_ERROR(err_act_retry, B_DEV_READ_ERROR); + + // request broken + case SCSI_REQ_INVALID: + SHOW_ERROR0(2, "Invalid request"); + return MK_ERROR(err_act_fail, B_ERROR); + + // request aborted + case SCSI_REQ_ABORTED: + case SCSI_SCSI_BUS_RESET: + case SCSI_REQ_TERMIO: + case SCSI_UNEXP_BUSFREE: + case SCSI_BDR_SENT: + case SCSI_CMD_TIMEOUT: + case SCSI_IID_INVALID: + case SCSI_UNACKED_EVENT: + case SCSI_IDE: + case SCSI_SEQUENCE_FAIL: + // take a small breath and retry + snooze(100000); + return MK_ERROR(err_act_retry, B_DEV_TIMEOUT); + + // device error + case SCSI_REQ_CMP_ERR: + return check_scsi_status(device, request); + + // device error, but we don't know what happened + case SCSI_AUTOSENSE_FAIL: + SHOW_ERROR0(2, "Auto-sense failed, don't know what really happened"); + return MK_ERROR(err_act_fail, B_ERROR); + + // should not happen, give up + case SCSI_BUS_RESET_DENIED: + case SCSI_PROVIDE_FAIL: + case SCSI_UA_TERMIO: + case SCSI_CDB_RECVD: + case SCSI_LUN_ALLREADY_ENAB: + // supposed to fall through + default: + return MK_ERROR(err_act_fail, B_ERROR); + } +} diff --git a/src/add-ons/kernel/generic/scsi_periph/handle.c b/src/add-ons/kernel/generic/scsi_periph/handle.c new file mode 100644 index 0000000000..232a839851 --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/handle.c @@ -0,0 +1,71 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI Peripheral Driver + + Basic handling of file handles. +*/ + + +#include "scsi_periph_int.h" + +#include +#include + + +status_t +periph_handle_open(scsi_periph_device_info *device, periph_handle_cookie periph_handle, + scsi_periph_handle_info **res_handle) +{ + scsi_periph_handle_info *handle; + +// SHOW_FLOW( 3, "device=%p", device ); + + handle = (scsi_periph_handle_info *)malloc(sizeof(*handle)); + if (handle == NULL) + return B_NO_MEMORY; + + handle->periph_handle = periph_handle; + handle->device = device; + handle->pending_error = B_OK; + + ACQUIRE_BEN(&device->mutex); + ADD_DL_LIST_HEAD(handle, device->handles, ); + RELEASE_BEN(&device->mutex); + + *res_handle = handle; + +// SHOW_FLOW( 3, "handle=%p", handle ); + + return B_OK; +} + + +status_t +periph_handle_close(scsi_periph_handle_info *handle) +{ +// SHOW_FLOW( 3, "handle=%p", handle ); + return B_OK; +} + + +status_t +periph_handle_free(scsi_periph_handle_info *handle) +{ + scsi_periph_device_info *device = handle->device; + +// SHOW_FLOW( 3, "handle=%p, device=%p", handle, handle->device ); + + ACQUIRE_BEN(&device->mutex); + REMOVE_DL_LIST(handle, device->handles, ); + RELEASE_BEN(&device->mutex); + + free(handle); + +// SHOW_FLOW0( 3, "done" ); + + return B_OK; +} diff --git a/src/add-ons/kernel/generic/scsi_periph/io.c b/src/add-ons/kernel/generic/scsi_periph/io.c new file mode 100644 index 0000000000..38c4a6fbc6 --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/io.c @@ -0,0 +1,326 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI Disk Driver + + Everything doing the real input/output stuff. +*/ + +#include "scsi_periph_int.h" +#include + +#include +#include + + +// we don't want to inline this function - it's just not worth it +static int periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *vecs, + off_t pos, size_t num_blocks, uint32 block_size, size_t *bytes_transferred, + int preferred_ccb_size, bool write); + + +status_t +periph_read(scsi_periph_handle_info *handle, const phys_vecs *vecs, off_t pos, + size_t num_blocks, uint32 block_size, size_t *bytes_transferred, int preferred_ccb_size) +{ + return periph_read_write(handle, vecs, pos, num_blocks, block_size, + bytes_transferred, preferred_ccb_size, false); +} + + +status_t +periph_write(scsi_periph_handle_info *handle, const phys_vecs *vecs, off_t pos, + size_t num_blocks, uint32 block_size, size_t *bytes_transferred, int preferred_ccb_size) +{ + return periph_read_write(handle, vecs, pos, num_blocks, block_size, + bytes_transferred, preferred_ccb_size, true); +} + + +/** universal read/write function */ + +static int +periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *vecs, + off_t pos64, size_t num_blocks, uint32 block_size, size_t *bytes_transferred, + int preferred_ccb_size, bool write) +{ + scsi_periph_device_info *device = handle->device; + scsi_ccb *request; + err_res res; + int retries = 0; + int err; + uint32 pos = pos64; + + // don't test rw10_enabled restrictions - this flag may get changed + request = device->scsi->alloc_ccb(device->scsi_device); + + if (request == NULL) + return B_NO_MEMORY; + + do { + size_t num_bytes; + bool is_rw10; + + request->flags = write ? SCSI_DIR_OUT : SCSI_DIR_IN; + + // make sure we avoid 10 byte commands if they aren't supported + if( !device->rw10_enabled || preferred_ccb_size == 6) { + // restricting transfer is OK - the block manager will + // take care of transferring the rest + if (num_blocks > 0x100) + num_blocks = 0x100; + + // no way to break the 21 bit address limit + if (pos64 > 0x200000) { + err = B_BAD_VALUE; + goto abort; + } + + // don't allow transfer cross the 24 bit address limit + // (I'm not sure whether this is allowed, but this way we + // are sure to not ask for trouble) + num_blocks = min(num_blocks, 0x100000 - pos); + } + + num_bytes = num_blocks * block_size; + + request->data = NULL; + request->sg_list = vecs->vec; + request->data_len = num_bytes; + request->sg_cnt = vecs->num; + request->sort = pos; + request->timeout = device->std_timeout; + // see whether daemon instructed us to post an ordered command; + // reset flag after read + SHOW_FLOW( 3, "flag=%x, next_tag=%x, ordered: %s", + (int)request->flags, (int)device->next_tag_action, + (request->flags & SCSI_ORDERED_QTAG) != 0 ? "yes" : "no" ); + + // use shortest commands whenever possible + if (pos + num_blocks < 0x200000 && num_blocks <= 0x100) { + scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)request->cdb; + + is_rw10 = false; + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = write ? SCSI_OP_WRITE_6 : SCSI_OP_READ_6; + cmd->high_LBA = (pos >> 16) & 0x1f; + cmd->mid_LBA = (pos >> 8) & 0xff; + cmd->low_LBA = pos & 0xff; + cmd->length = num_blocks; + + request->cdb_len = sizeof(*cmd); + } else { + scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb; + + is_rw10 = true; + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = write ? SCSI_OP_WRITE_10 : SCSI_OP_READ_10; + cmd->RelAdr = 0; + cmd->FUA = 0; + cmd->DPO = 0; + + cmd->top_LBA = (pos >> 24) & 0xff; + cmd->high_LBA = (pos >> 16) & 0xff; + cmd->mid_LBA = (pos >> 8) & 0xff; + cmd->low_LBA = pos & 0xff; + + cmd->high_length = (num_blocks >> 8) & 0xff; + cmd->low_length = num_blocks & 0xff; + + request->cdb_len = sizeof(*cmd); + } + + // last chance to detect errors that occured during concurrent accesses + err = handle->pending_error; + + if (err) + goto abort; + + device->scsi->async_io(request); + + acquire_sem(request->completion_sem); + + // ask generic peripheral layer what to do now + res = periph_check_error(device, request); + + switch (res.action) { + case err_act_ok: + *bytes_transferred = num_bytes - request->data_resid; + break; + + case err_act_start: + res = periph_send_start_stop(device, request, 1, device->removable); + if (res.action == err_act_ok) + res.action = err_act_retry; + break; + + case err_act_invalid_req: + // if this was a 10 byte command, the device probably doesn't + // support them, so disable them and retry + if (is_rw10) { + atomic_and(&device->rw10_enabled, 0); + res.action = err_act_retry; + } else + res.action = err_act_fail; + break; + } + } while((res.action == err_act_retry && retries++ < 3) + || (res.action == err_act_many_retries && retries++ < 30)); + + device->scsi->free_ccb(request); + + // peripheral layer only created "read" error, so we have to + // map them to "write" errors if this was a write request + if (res.error_code == B_DEV_READ_ERROR && write) + return B_DEV_WRITE_ERROR; + + return res.error_code; + +abort: + device->scsi->free_ccb(request); + return err; +} + + +static status_t +inquiry(scsi_periph_device_info *device, scsi_inquiry *inquiry) +{ + scsi_res_inquiry *device_inquiry = NULL; + size_t inquiry_len; + + if (pnp->get_attr_raw(device->node, SCSI_DEVICE_INQUIRY_ITEM, + (void **)&device_inquiry, &inquiry_len, true) != B_OK) + return B_ERROR; + + memcpy(inquiry, device_inquiry, min(inquiry_len, sizeof(scsi_inquiry))); + free(device_inquiry); + + return B_OK; +} + + +static status_t +prevent_allow(scsi_periph_device_info *device, bool prevent) +{ + scsi_cmd_prevent_allow cmd; + + SHOW_FLOW0(0, ""); + + memset(&cmd, 0, sizeof(cmd)); + cmd.opcode = SCSI_OP_PREVENT_ALLOW; + cmd.prevent = prevent; + + return periph_simple_exec(device, (uint8 *)&cmd, sizeof(cmd), NULL, 0, 0); +} + + +/** !!!keep this in sync with scsi_raw driver!!! */ + +static status_t +raw_command(scsi_periph_device_info *device, raw_device_command *cmd) +{ + scsi_ccb *request; + + SHOW_FLOW0(0, ""); + + request = device->scsi->alloc_ccb(device->scsi_device); + if (request == NULL) + return B_NO_MEMORY; + + request->flags = 0; + + if (cmd->flags & B_RAW_DEVICE_DATA_IN) + request->flags |= SCSI_DIR_IN; + else + request->flags |= SCSI_DIR_OUT; + + request->data = cmd->data; + request->sg_list = NULL; + request->data_len = cmd->data_length; + request->sort = -1; + request->timeout = cmd->timeout; + + memcpy(request->cdb, cmd->command, SCSI_MAX_CDB_SIZE); + request->cdb_len = cmd->command_length; + + device->scsi->sync_io(request); + + // TBD: should we call standard error handler here, or may the + // actions done there (like starting the unit) confuse the application? + + cmd->cam_status = request->subsys_status; + cmd->scsi_status = request->device_status; + + if ((request->subsys_status & SCSI_AUTOSNS_VALID) != 0 && cmd->sense_data) { + memcpy(cmd->sense_data, request->sense, + min(cmd->sense_data_length, SCSI_MAX_SENSE_SIZE - request->sense_resid)); + } + + if ((cmd->flags & B_RAW_DEVICE_REPORT_RESIDUAL) != 0) { + // this is a bit strange, see Be's sample code where I pinched this from; + // normally, residual means "number of unused bytes left" + // but here, we have to return "number of used bytes", which is the opposite + cmd->data_length = cmd->data_length - request->data_resid; + cmd->sense_data_length = SCSI_MAX_SENSE_SIZE - request->sense_resid; + } + + device->scsi->free_ccb(request); + + return B_OK; +} + + +status_t +periph_ioctl(scsi_periph_handle_info *handle, int op, void *buf, size_t len) +{ + switch (op) { + case B_GET_MEDIA_STATUS: { + status_t res; + + if (!handle->device->removable) + return B_BAD_VALUE; + + res = periph_get_media_status(handle); + SHOW_FLOW(2, "%s", strerror(res)); + + *(status_t *)buf = res; + + return B_OK; + } + + case B_SCSI_INQUIRY: + return inquiry(handle->device, (scsi_inquiry *)buf); + + case B_SCSI_PREVENT_ALLOW: + return prevent_allow(handle->device, *(bool *)buf); + + case B_RAW_DEVICE_COMMAND: + return raw_command(handle->device, buf); + + default: + SHOW_ERROR(4, "Unknown ioctl: %x", op); + return B_BAD_VALUE; + } +} + + +/** kernel daemon + * once in a minute, it sets a flag so that the next command is executed + * ordered; this way, we avoid starvation of SCSI commands inside the + * SCSI queuing system - the ordered command waits for all previous + * commands and thus no command can starve longer then a minute + */ + +void +periph_sync_queue_daemon(void *arg, int iteration) +{ + scsi_periph_device_info *device = (scsi_periph_device_info *)arg; + + SHOW_FLOW0(3, "Setting ordered flag for next R/W access"); + atomic_or(&device->next_tag_action, SCSI_ORDERED_QTAG); +} diff --git a/src/add-ons/kernel/generic/scsi_periph/removable.c b/src/add-ons/kernel/generic/scsi_periph/removable.c new file mode 100644 index 0000000000..2d6209fb1f --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/removable.c @@ -0,0 +1,232 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI Peripheral Driver + + Handling of removable media. +*/ + + +#include "scsi_periph_int.h" + +#include +#include + + +void +periph_media_changed(scsi_periph_device_info *device, scsi_ccb *request) +{ + uint32 backup_flags; + uint8 backup_cdb[SCSI_MAX_CDB_SIZE]; + uchar backup_cdb_len; + int64 backup_sort; + bigtime_t backup_timeout; + uchar *backup_data; + const physical_entry *backup_sg_list; + uint16 backup_sg_cnt; + uint32 backup_data_len; + + // if there is no hook, the driver doesn't handle removal devices + if (!device->removable) { + SHOW_ERROR0( 1, "Driver doesn't support medium changes, but there occured one!?" ); + return; + } + + // when medium has changed, tell all handles + periph_media_changed_public(device); + + // the peripheral driver may need a fresh ccb; sadly, we cannot allocate one + // as this may lead to a deadlock if all ccb are in use already; thus, we + // have to backup all relevant data of current ccb and use it instead of a + // new one - not pretty but working (and performance is not an issue in this + // path) + backup_flags = request->flags; + memcpy(backup_cdb, request->cdb, SCSI_MAX_CDB_SIZE); + backup_cdb_len = request->cdb_len; + backup_sort = request->sort; + backup_timeout = request->timeout; + backup_data = request->data; + backup_sg_list = request->sg_list; + backup_sg_cnt = request->sg_cnt; + backup_data_len = request->data_len; + + if (device->callbacks->media_changed != NULL) + device->callbacks->media_changed(device->periph_device, request); + + request->flags = backup_flags; + memcpy(request->cdb, backup_cdb, SCSI_MAX_CDB_SIZE); + request->cdb_len = backup_cdb_len; + request->sort = backup_sort; + request->timeout = backup_timeout; + request->data = backup_data; + request->sg_list = backup_sg_list; + request->sg_cnt = backup_sg_cnt; + request->data_len = backup_data_len; +} + + +void +periph_media_changed_public(scsi_periph_device_info *device) +{ + scsi_periph_handle_info *handle; + + ACQUIRE_BEN(&device->mutex); + + // when medium has changed, tell all handles + // (this must be atomic for each handle!) + for (handle = device->handles; handle; handle = handle->next) + handle->pending_error = B_DEV_MEDIA_CHANGED; + + RELEASE_BEN(&device->mutex); +} + + +/** send TUR */ + +static err_res +send_tur(scsi_periph_device_info *device, scsi_ccb *request) +{ + scsi_cmd_tur *cmd = (scsi_cmd_tur *)request->cdb; + + request->flags = SCSI_DIR_NONE | SCSI_ORDERED_QTAG; + + request->data = NULL; + request->sg_list = NULL; + request->data_len = 0; + request->timeout = device->std_timeout; + request->sort = -1; + request->sg_list = NULL; + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = SCSI_OP_TUR; + + request->cdb_len = sizeof(*cmd); + + device->scsi->sync_io(request); + + return periph_check_error(device, request); +} + + +/** wait until device is ready */ + +static err_res +wait_for_ready(scsi_periph_device_info *device, scsi_ccb *request) +{ + int retries = 0; + + while (true) { + err_res res; + + // we send TURs until the device is OK or all hope is lost + res = send_tur(device, request); + + switch (res.action) { + case err_act_ok: + return MK_ERROR(err_act_ok, B_OK); + + case err_act_retry: + if (++retries >= 3) + return MK_ERROR(err_act_fail, res.error_code); + break; + + case err_act_many_retries: + if (++retries >= 30) + return MK_ERROR(err_act_fail, res.error_code); + break; + + default: + SHOW_FLOW( 3, "action: %x, error: %x", (int)res.action, (int)res.error_code); + return res; + } + } +} + + +status_t +periph_get_media_status(scsi_periph_handle_info *handle) +{ + scsi_periph_device_info *device = handle->device; + scsi_ccb *request; + err_res res; + status_t err; + + ACQUIRE_BEN(&device->mutex); + + // removal requests are returned to exactly one handle + // (no real problem, as noone check medias status "by mistake") + if (device->removal_requested) { + device->removal_requested = false; + err = B_DEV_MEDIA_CHANGE_REQUESTED; + goto err; + } + + // if there is a pending error (read: media has changed), return once per handle + err = handle->pending_error; + if (err != B_OK) { + handle->pending_error = B_OK; + goto err; + } + + SHOW_FLOW0( 3, "" ); + + RELEASE_BEN(&device->mutex); + + // finally, ask the device itself + + request = device->scsi->alloc_ccb(device->scsi_device); + if (request == NULL) + return B_NO_MEMORY; + + res = wait_for_ready(device, request); + + device->scsi->free_ccb(request); + + SHOW_FLOW(3, "error_code: %x", (int)res.error_code); + + return res.error_code; + +err: + RELEASE_BEN(&device->mutex); + return err; +} + + +/** send START/STOP command to device + * start - true for start, false for stop + * with_LoEj - if true, then lock drive on start and eject on stop + */ + +err_res +periph_send_start_stop(scsi_periph_device_info *device, scsi_ccb *request, + bool start, bool with_LoEj) +{ + scsi_cmd_ssu *cmd = (scsi_cmd_ssu *)request->cdb; + + // this must be ordered, so all previous commands are really finished + request->flags = SCSI_DIR_NONE | SCSI_ORDERED_QTAG; + + request->data = NULL; + request->sg_list = NULL; + request->data_len = 0; + request->timeout = device->std_timeout; + request->sort = -1; + request->sg_list = NULL; + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = SCSI_OP_START_STOP; + // we don't want to poll; we give a long timeout instead + // (well - the default timeout _is_ large) + cmd->immed = 0; + cmd->start = start; + cmd->LoEj = with_LoEj; + + request->cdb_len = sizeof(*cmd); + + device->scsi->sync_io(request); + + return periph_check_error(device, request); +} diff --git a/src/add-ons/kernel/generic/scsi_periph/scsi_periph.c b/src/add-ons/kernel/generic/scsi_periph/scsi_periph.c new file mode 100644 index 0000000000..88ba83772f --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/scsi_periph.c @@ -0,0 +1,174 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI Peripheral Driver + + Main file. +*/ + +#include "scsi_periph_int.h" + +#include + +#include + + +device_manager_info *pnp; + + +status_t +periph_simple_exec(scsi_periph_device_info *device, void *cdb, uchar cdb_len, + void *data, size_t data_len, int ccb_flags) +{ + scsi_ccb *ccb; + status_t res; + + SHOW_FLOW0( 0, "" ); + + ccb = device->scsi->alloc_ccb(device->scsi_device); + if (ccb == NULL) + return B_NO_MEMORY; + + ccb->flags = ccb_flags; + + memcpy(ccb->cdb, cdb, cdb_len); + ccb->cdb_len = cdb_len; + + ccb->sort = -1; + ccb->timeout = device->std_timeout; + + ccb->data = data; + ccb->sg_list = NULL; + ccb->data_len = data_len; + + res = periph_safe_exec(device, ccb); + + device->scsi->free_ccb(ccb); + + return res; +} + + +status_t +periph_safe_exec(scsi_periph_device_info *device, scsi_ccb *request) +{ + err_res res; + int retries = 0; + + do { + device->scsi->sync_io(request); + + // ask generic peripheral layer what to do now + res = periph_check_error(device, request); + + if (res.action == err_act_start) { + // backup request, as we need it temporarily for sending "start" + // (we cannot allocate a new cdb as there may be no more cdb and + // waiting for one to become empty may lead to deadlock if everyone + // does that) + uint32 backup_flags; + uint8 backup_cdb[SCSI_MAX_CDB_SIZE]; + uchar backup_cdb_len; + int64 backup_sort; + bigtime_t backup_timeout; + uchar *backup_data; + const physical_entry *backup_sg_list; + uint16 backup_sg_cnt; + uint32 backup_data_len; + + backup_flags = request->flags; + memcpy(backup_cdb, request->cdb, SCSI_MAX_CDB_SIZE); + backup_cdb_len = request->cdb_len; + backup_sort = request->sort; + backup_timeout = request->timeout; + backup_data = request->data; + backup_sg_list = request->sg_list; + backup_sg_cnt = request->sg_cnt; + backup_data_len = request->data_len; + + SHOW_INFO0( 2, "Sending start to init LUN" ); + + res = periph_send_start_stop(device, request, 1, device->removable); + + request->flags = backup_flags; + memcpy(request->cdb, backup_cdb, SCSI_MAX_CDB_SIZE); + request->cdb_len = backup_cdb_len; + request->sort = backup_sort; + request->timeout = backup_timeout; + request->data = backup_data; + request->sg_list = backup_sg_list; + request->sg_cnt = backup_sg_cnt; + request->data_len = backup_data_len; + + if (res.action == err_act_ok) + res.action = err_act_retry; + } + } while ((res.action == err_act_retry && retries++ < 3) + || (res.action == err_act_many_retries && retries++ < 30)); + + return res.error_code; +} + + +static status_t +std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + case B_MODULE_UNINIT: + return B_OK; + + default: + return B_ERROR; + } +} + + +module_dependency module_dependencies[] = { + { DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp }, + {} +}; + + +scsi_periph_interface scsi_periph_module = { + { + SCSI_PERIPH_MODULE_NAME, + 0, + std_ops + }, + + periph_register_device, + periph_unregister_device, + + periph_safe_exec, + periph_simple_exec, + + periph_handle_open, + periph_handle_close, + periph_handle_free, + + periph_read, + periph_write, + periph_ioctl, + periph_check_capacity, + + periph_media_changed_public, + periph_check_error, + periph_send_start_stop, + periph_get_media_status, + + periph_compose_device_name, + periph_get_icon +}; + + +#if !_BUILDING_kernel && !BOOT +_EXPORT +scsi_periph_interface *modules[] = { + &scsi_periph_module, + NULL +}; +#endif diff --git a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h new file mode 100644 index 0000000000..2b6b841a23 --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h @@ -0,0 +1,110 @@ +/* +** Copyright 2002, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +#ifndef __SCSI_PERIPH_INT_H__ +#define __SCSI_PERIPH_INT_H__ + +#include +#include +#include +#include +#include "wrapper.h" + + +typedef struct scsi_periph_device_info { + struct scsi_periph_handle_info *handles; + + scsi_device scsi_device; + scsi_device_interface *scsi; + periph_device_cookie periph_device; + pnp_node_handle node; + + bool removal_requested; + + bool removable; // true, if device is removable + + int32 rw10_enabled; // 10 byte r/w commands supported; access must be atomic + int32 next_tag_action; // queuing flag for next r/w command; access must be atomic + + benaphore mutex; + int std_timeout; + + scsi_periph_callbacks *callbacks; +} scsi_periph_device_info; + +typedef struct scsi_periph_handle_info { + scsi_periph_device_info *device; + struct scsi_periph_handle_info *next, *prev; + + int pending_error; // error to be reported on all accesses + // (used to block access after medium change until + // B_GET_MEDIA_STATUS is called) + periph_handle_cookie periph_handle; +} scsi_periph_handle_info; + +extern device_manager_info *pnp; + + +// removable.c + +void periph_media_changed(scsi_periph_device_info *device, scsi_ccb *ccb); +void periph_media_changed_public(scsi_periph_device_info *device); +status_t periph_get_media_status(scsi_periph_handle_info *handle); +err_res periph_send_start_stop(scsi_periph_device_info *device, scsi_ccb *request, + bool start, bool with_LoEj); + + +// error_handling.c + +err_res periph_check_error(scsi_periph_device_info *device, scsi_ccb *request); + + +// handle.c + +status_t periph_handle_open(scsi_periph_device_info *device, periph_handle_cookie periph_handle, + scsi_periph_handle_info **res_handle); +status_t periph_handle_close(scsi_periph_handle_info *handle); +status_t periph_handle_free(scsi_periph_handle_info *handle); + + +// block.c + +status_t periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *ccb); + + +// device.c + +status_t periph_register_device(periph_device_cookie periph_device, + scsi_periph_callbacks *callbacks, scsi_device scsi_device, scsi_device_interface *scsi, + pnp_node_handle node, bool removable, scsi_periph_device *driver); +status_t periph_unregister_device(scsi_periph_device_info *driver); +char *periph_compose_device_name(pnp_node_handle device_node, const char *prefix); + + +// io.c + +status_t periph_read(scsi_periph_handle_info *handle, const phys_vecs *vecs, + off_t pos, size_t num_blocks, uint32 block_size, size_t *bytes_transferred, + int preferred_ccb_size); +status_t periph_write(scsi_periph_handle_info *handle, const phys_vecs *vecs, + off_t pos, size_t num_blocks, uint32 block_size, size_t *bytes_transferred, + int preferred_ccb_size); +status_t periph_ioctl(scsi_periph_handle_info *handle, int op, + void *buf, size_t len); +void periph_sync_queue_daemon(void *arg, int iteration); + + +// scsi_periph.c + +status_t periph_safe_exec(scsi_periph_device_info *device, scsi_ccb *request); +status_t periph_simple_exec(scsi_periph_device_info *device, void *cdb, + uchar cdb_len, void *data, size_t data_len, int ccb_flags); + + +// device_icons.c + +status_t periph_get_icon(icon_type type, device_icon *data); + +#endif diff --git a/src/add-ons/kernel/generic/scsi_periph/wrapper.h b/src/add-ons/kernel/generic/scsi_periph/wrapper.h new file mode 100644 index 0000000000..6793cb73be --- /dev/null +++ b/src/add-ons/kernel/generic/scsi_periph/wrapper.h @@ -0,0 +1,89 @@ +#ifndef _WRAPPER_H +#define _WRAPPER_H + +#include +#include + + +// benaphores + +#define INIT_BEN(x, prefix) benaphore_init(x, prefix) +#define DELETE_BEN(x) benaphore_destroy(x) +#define ACQUIRE_BEN(x) benaphore_lock(x) +#define RELEASE_BEN(x) benaphore_unlock(x) + +// debug output + +#ifdef DEBUG_WAIT_ON_MSG +# define DEBUG_WAIT snooze( DEBUG_WAIT_ON_MSG ); +#else +# define DEBUG_WAIT +#endif + +#ifdef DEBUG_WAIT_ON_ERROR +# define DEBUG_WAIT_ERROR snooze( DEBUG_WAIT_ON_ERROR ); +#else +# define DEBUG_WAIT_ERROR +#endif + +#ifndef DEBUG_MAX_LEVEL_FLOW +# define DEBUG_MAX_LEVEL_FLOW 4 +#endif + +#ifndef DEBUG_MAX_LEVEL_INFO +# define DEBUG_MAX_LEVEL_INFO 4 +#endif + +#ifndef DEBUG_MAX_LEVEL_ERROR +# define DEBUG_MAX_LEVEL_ERROR 4 +#endif + +#ifndef DEBUG_MSG_PREFIX +# define DEBUG_MSG_PREFIX "" +#endif + +#ifndef debug_level_flow +# define debug_level_flow 3 +#endif + +#ifndef debug_level_info +# define debug_level_info 2 +#endif + +#ifndef debug_level_error +# define debug_level_error 1 +#endif + +#define FUNC_NAME DEBUG_MSG_PREFIX __FUNCTION__ ": " + +#define SHOW_FLOW(seriousness, format, param...) \ + do { if( seriousness <= debug_level_flow && seriousness <= DEBUG_MAX_LEVEL_FLOW ) { \ + dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT \ + }} while( 0 ) + +#define SHOW_FLOW0(seriousness, format) \ + do { if( seriousness <= debug_level_flow && seriousness <= DEBUG_MAX_LEVEL_FLOW ) { \ + dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT \ + }} while( 0 ) + +#define SHOW_INFO(seriousness, format, param...) \ + do { if( seriousness <= debug_level_info && seriousness <= DEBUG_MAX_LEVEL_INFO ) { \ + dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT \ + }} while( 0 ) + +#define SHOW_INFO0(seriousness, format) \ + do { if( seriousness <= debug_level_info && seriousness <= DEBUG_MAX_LEVEL_INFO ) { \ + dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT \ + }} while( 0 ) + +#define SHOW_ERROR(seriousness, format, param...) \ + do { if( seriousness <= debug_level_error && seriousness <= DEBUG_MAX_LEVEL_ERROR ) { \ + dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT_ERROR \ + }} while( 0 ) + +#define SHOW_ERROR0(seriousness, format) \ + do { if( seriousness <= debug_level_error && seriousness <= DEBUG_MAX_LEVEL_ERROR ) { \ + dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT_ERROR \ + }} while( 0 ) + +#endif /* _BENAPHORE_H */