Added Thomas Kurschel's scsi_periph module.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7766 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-06-06 23:14:52 +00:00
parent 9d506c43b8
commit b59852c818
13 changed files with 2030 additions and 0 deletions

View File

@ -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
;

View File

@ -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 <string.h>
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;
}

View File

@ -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 <blkman.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#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;
}

View File

@ -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 <string.h>
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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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 <blkman.h>
/** 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);
}
}

View File

@ -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 <dl_list.h>
#include <malloc.h>
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;
}

View File

@ -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 <scsi.h>
#include <string.h>
#include <stdlib.h>
// 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);
}

View File

@ -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 <blkman.h>
#include <string.h>
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);
}

View File

@ -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 <module.h>
#include <string.h>
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

View File

@ -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 <stddef.h>
#include <bus/scsi/scsi_periph.h>
#include <blkman.h>
#include <device_manager.h>
#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

View File

@ -0,0 +1,89 @@
#ifndef _WRAPPER_H
#define _WRAPPER_H
#include <KernelExport.h>
#include <lock.h>
// 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 */