* Cleaned up SCSI headers a bit.

* scsi_cmds.h declared several variables instead of naming enums.
* the CD-ROM standard retrieval was broken (always checked index 0).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21105 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-05-10 14:13:37 +00:00
parent 4cad5aba3b
commit 6be1e37d94
23 changed files with 993 additions and 1142 deletions
+15 -17
View File
@@ -1,11 +1,11 @@
/*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _SCSI_BUSMANAGER_H_
#define _SCSI_BUSMANAGER_H_
#ifndef _SCSI_BUSMANAGER_H
#define _SCSI_BUSMANAGER_H
/*
SCSI bus manager interface
@@ -26,7 +26,7 @@
Something about requests involving data transfer: you can either specify
the virtual address in <data> of CCB (in which case it must be continuous),
or store a pointer to a S/G list that contains physical addresses in
<sg_list>/<sg_cnt>. If <sg_list> is non-Null, <data> is ignored.
<sg_list>/<sg_count>. If <sg_list> is non-Null, <data> is ignored.
The S/G list must be in kernel space because the request can be executed
in a different thread context. This is also the reason why the S/G list has
to contain physical addresses. For obvious reason, the data buffer specified
@@ -108,8 +108,7 @@ typedef struct scsi_device_info *scsi_device;
// structure of one scsi i/o CCB (command control block)
typedef struct scsi_ccb
{
typedef struct scsi_ccb {
struct scsi_ccb *next, *prev; // internal
uchar subsys_status; // Returned subsystem status
@@ -126,14 +125,14 @@ typedef struct scsi_ccb
sem_id completion_sem;
uint8 cdb[SCSI_MAX_CDB_SIZE]; // command data block
uchar cdb_len; // length of command in bytes
uchar cdb_length; // length of command in bytes
int64 sort; // value of command to sort on (<0 means n/a)
bigtime_t timeout; // timeout - 0 = use default
uchar *data; // pointer to data
const physical_entry *sg_list; // SG list
uint16 sg_cnt; // number of SG entries
uint32 data_len; // length of data
const physical_entry *sg_list; // scatter/gather list
uint16 sg_count; // number of S/G entries
uint32 data_length; // length of data
int32 data_resid; // data transfer residual length: 2's comp
uchar sense[SCSI_MAX_SENSE_SIZE]; // autosense data
@@ -151,10 +150,10 @@ typedef struct scsi_ccb
// original data before command emulation was applied
uint8 orig_cdb[SCSI_MAX_CDB_SIZE];
uchar orig_cdb_len;
const physical_entry *orig_sg_list;
uint16 orig_sg_cnt;
uint32 orig_data_len;
uchar orig_cdb_length;
const physical_entry *orig_sg_list;
uint16 orig_sg_count;
uint32 orig_data_length;
// private SIM data
uchar sim_state; // set to zero when request is submitted first time
@@ -249,8 +248,7 @@ typedef struct scsi_ccb
// Path inquiry, extended by BeOS XPT_EXTENDED_PATH_INQ parameters
typedef struct
{
typedef struct {
uchar version_num; /* Version number for the SIM/HBA */
uchar hba_inquiry; /* Mimic of INQ byte 7 for the HBA */
uchar hba_misc; /* Misc HBA feature flags */
@@ -457,4 +455,4 @@ typedef struct scsi_sim_interface {
} scsi_sim_interface;
#endif /* _SCSI_BUSMANAGER_H_ */
#endif /* _SCSI_BUSMANAGER_H */
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -1,11 +1,13 @@
/*
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _SCSI_PERIPH_H
#define _SCSI_PERIPH_H
/*
Part of Open SCSI Peripheral Driver
Use this module to minimize work required to write a SCSI
peripheral driver.
@@ -15,8 +17,6 @@
- detection of medium capacity
*/
#ifndef __SCSI_PERIPH_H__
#define __SCSI_PERIPH_H__
#include <bus/SCSI.h>
#include <block_io.h>
@@ -161,4 +161,4 @@ typedef struct scsi_periph_interface {
#define SCSI_PERIPH_MODULE_NAME "generic/scsi_periph/v1"
#endif
#endif /* _SCSI_PERIPH_H */
+21 -26
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
@@ -26,10 +26,10 @@
#define IDE_ATAPI_BUFFER_SIZE 512
/** Set sense according to error reported by device
* return: true - device reported error
*/
/*!
Set sense according to error reported by device
return: true - device reported error
*/
static bool
check_packet_error(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -88,8 +88,7 @@ check_packet_error(ide_device_info *device, ide_qrequest *qrequest)
}
/** IRQ handler of packet transfer (executed as DPC) */
/*! IRQ handler of packet transfer (executed as DPC) */
void
packet_dpc(ide_qrequest *qrequest)
{
@@ -248,7 +247,7 @@ packet_dpc(ide_qrequest *qrequest)
SHOW_FLOW(3, "finished: %d of %d left",
(int)qrequest->request->data_resid,
(int)qrequest->request->data_len);
(int)qrequest->request->data_length);
finish_checksense(qrequest);
return;
@@ -263,8 +262,7 @@ err:
}
/** Create taskfile for ATAPI packet */
/*! Create taskfile for ATAPI packet */
static bool
create_packet_taskfile(ide_device_info *device, ide_qrequest *qrequest,
bool write)
@@ -278,16 +276,15 @@ create_packet_taskfile(ide_device_info *device, ide_qrequest *qrequest,
device->tf.packet.dma = qrequest->uses_dma;
device->tf.packet.ovl = 0;
device->tf.packet.byte_count_0_7 = request->data_len & 0xff;
device->tf.packet.byte_count_8_15 = request->data_len >> 8;
device->tf.packet.byte_count_0_7 = request->data_length & 0xff;
device->tf.packet.byte_count_8_15 = request->data_length >> 8;
device->tf.packet.command = IDE_CMD_PACKET;
return true;
}
/** Send ATAPI packet */
/*! Send ATAPI packet */
void
send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write)
{
@@ -304,12 +301,12 @@ send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write)
dprintf( "%x ", device->packet[i] );
}*/
SHOW_FLOW( 3, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x (len=%d)",
SHOW_FLOW(3, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x (len=%d)",
device->packet[0], device->packet[1], device->packet[2],
device->packet[3], device->packet[4], device->packet[5],
device->packet[6], device->packet[7], device->packet[8],
device->packet[9], device->packet[10], device->packet[11],
qrequest->request->cdb_len );
qrequest->request->cdb_length);
//snooze( 1000000 );
@@ -322,11 +319,11 @@ send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write)
// report how much data is transmitted, and this information is
// crucial for the SCSI protocol)
// special offer: let READ_CD commands use DMA too
qrequest->uses_dma = device->DMA_enabled &&
(scsi_cmd == SCSI_OP_READ_6 || scsi_cmd == SCSI_OP_WRITE_6 ||
scsi_cmd == SCSI_OP_READ_10 || scsi_cmd == SCSI_OP_WRITE_10 ||
scsi_cmd == SCSI_OP_READ_12 || scsi_cmd == SCSI_OP_WRITE_12 ||
scsi_cmd == SCSI_OP_READ_CD );
qrequest->uses_dma = device->DMA_enabled
&& (scsi_cmd == SCSI_OP_READ_6 || scsi_cmd == SCSI_OP_WRITE_6
|| scsi_cmd == SCSI_OP_READ_10 || scsi_cmd == SCSI_OP_WRITE_10
|| scsi_cmd == SCSI_OP_READ_12 || scsi_cmd == SCSI_OP_WRITE_12
|| scsi_cmd == SCSI_OP_READ_CD);
// try preparing DMA, if that fails, fall back to PIO
if (qrequest->uses_dma) {
@@ -437,8 +434,7 @@ err_setup:
}
/** Execute SCSI I/O for atapi devices */
/*! Execute SCSI I/O for atapi devices */
void
atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -449,7 +445,7 @@ atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest)
// ATAPI command packets are 12 bytes long;
// if the command is shorter, remaining bytes must be padded with zeros
memset(device->packet, 0, sizeof(device->packet));
memcpy(device->packet, request->cdb, request->cdb_len);
memcpy(device->packet, request->cdb, request->cdb_length);
if (request->cdb[0] == SCSI_OP_REQUEST_SENSE && device->combined_sense) {
// we have a pending emulated sense - return it on REQUEST SENSE
@@ -466,8 +462,7 @@ atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest)
}
/** prepare device info for ATAPI device */
/*! Prepare device info for ATAPI device */
bool
prep_atapi(ide_device_info *device)
{
+17 -24
View File
@@ -1,13 +1,12 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open IDE bus manager
//! DMA helper functions
DMA helper functions
*/
#include "ide_internal.h"
@@ -65,10 +64,9 @@ configure_dma(ide_device_info *device)
}
/** abort DMA transmission
* must be called _before_ start_dma_wait
*/
/*! Abort DMA transmission
must be called _before_ start_dma_wait
*/
void
abort_dma(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -80,11 +78,10 @@ abort_dma(ide_device_info *device, ide_qrequest *qrequest)
}
/** prepare DMA transmission
* on return, DMA engine waits for device to transmit data
* warning: doesn't set sense data on error
*/
/*! Prepare DMA transmission
on return, DMA engine waits for device to transmit data
warning: doesn't set sense data on error
*/
bool
prepare_dma(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -93,8 +90,7 @@ prepare_dma(ide_device_info *device, ide_qrequest *qrequest)
status_t res;
res = bus->controller->prepare_dma(bus->channel_cookie, request->sg_list,
request->sg_cnt, qrequest->is_write);
request->sg_count, qrequest->is_write);
if (res != B_OK)
return false;
@@ -102,8 +98,7 @@ prepare_dma(ide_device_info *device, ide_qrequest *qrequest)
}
/** start waiting for DMA to be finished */
/*! Start waiting for DMA to be finished */
void
start_dma_wait(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -116,8 +111,7 @@ start_dma_wait(ide_device_info *device, ide_qrequest *qrequest)
}
/** start waiting for DMA to be finished with bus lock not hold */
/*! Start waiting for DMA to be finished with bus lock not hold */
void
start_dma_wait_no_lock(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -128,8 +122,7 @@ start_dma_wait_no_lock(ide_device_info *device, ide_qrequest *qrequest)
}
/** finish dma transmission after device has fired IRQ */
/*! Finish dma transmission after device has fired IRQ */
bool
finish_dma(ide_device_info *device)
{
+36 -40
View File
@@ -1,13 +1,11 @@
/*
* Copyright 2004-2006, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2004-2007, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
General SCSI emulation routines
*/
//! General SCSI emulation routines
#include "ide_internal.h"
@@ -18,15 +16,14 @@
#include <string.h>
/** Emulate REQUEST SENSE */
/*! Emulate REQUEST SENSE */
void
ide_request_sense(ide_device_info *device, ide_qrequest *qrequest)
{
scsi_ccb *request = qrequest->request;
scsi_cmd_request_sense *cmd = (scsi_cmd_request_sense *)request->cdb;
scsi_sense sense;
uint32 transfer_size;
uint32 transferSize;
// cannot use finish_checksense here, as data is not copied into autosense buffer
// but into normal data buffer, SCSI result is GOOD and CAM status is REQ_CMP
@@ -36,15 +33,15 @@ ide_request_sense(ide_device_info *device, ide_qrequest *qrequest)
else
memset(&sense, 0, sizeof(sense));
copy_sg_data(request, 0, cmd->alloc_length, &sense, sizeof(sense), false);
copy_sg_data(request, 0, cmd->allocation_length, &sense, sizeof(sense), false);
// reset sense information on read
device->combined_sense = 0;
transfer_size = min(sizeof(sense), cmd->alloc_length);
transfer_size = min(transfer_size, request->data_len);
transferSize = min(sizeof(sense), cmd->allocation_length);
transferSize = min(transferSize, request->data_length);
request->data_resid = request->data_len - transfer_size;
request->data_resid = request->data_length - transferSize;
// normally, all flags are set to "success", but for Request Sense
// this would have overwritten the sense we want to read
@@ -53,57 +50,56 @@ ide_request_sense(ide_device_info *device, ide_qrequest *qrequest)
}
/** copy data between request data and buffer
* request - request to copy data from/to
* offset - offset of data in request
* allocation_length- limit of request's data buffer according to CDB
* buffer - data to copy data from/to
* size - number of bytes to copy
* to_buffer - true: copy from request to buffer
* false: copy from buffer to request
* return: true, if data of request was large enough
*/
/*! Copy data between request data and buffer
request - request to copy data from/to
offset - offset of data in request
allocation_length- limit of request's data buffer according to CDB
buffer - data to copy data from/to
size - number of bytes to copy
to_buffer - true: copy from request to buffer
false: copy from buffer to request
return: true, if data of request was large enough
*/
bool
copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length,
void *buffer, int size, bool to_buffer)
copy_sg_data(scsi_ccb *request, uint offset, uint allocationLength,
void *buffer, int size, bool toBuffer)
{
const physical_entry *sg_list = request->sg_list;
int sg_cnt = request->sg_cnt;
int req_size;
const physical_entry *sgList = request->sg_list;
int sgCount = request->sg_count;
int requestSize;
SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_cnt=%d, %s buffer",
offset, allocation_length, size, sg_list, sg_cnt, to_buffer ? "to" : "from");
offset, allocationLength, size, sgList, sgCount, toBuffer ? "to" : "from");
// skip unused S/G entries
while (sg_cnt > 0 && offset >= sg_list->size) {
offset -= sg_list->size;
++sg_list;
--sg_cnt;
while (sgCount > 0 && offset >= sgList->size) {
offset -= sgList->size;
++sgList;
--sgCount;
}
if (sg_cnt == 0)
if (sgCount == 0)
return 0;
// remaining bytes we are allowed to copy from/to request
req_size = min(allocation_length, request->data_len) - offset;
requestSize = min(allocationLength, request->data_length) - offset;
// copy one S/G entry at a time
for (; size > 0 && req_size > 0 && sg_cnt > 0; ++sg_list, --sg_cnt) {
for (; size > 0 && requestSize > 0 && sgCount > 0; ++sgList, --sgCount) {
addr_t virtualAddress;
size_t bytes;
bytes = min(size, req_size);
bytes = min(bytes, sg_list->size);
bytes = min(size, requestSize);
bytes = min(bytes, sgList->size);
if (vm_get_physical_page((addr_t)sg_list->address, &virtualAddress,
if (vm_get_physical_page((addr_t)sgList->address, &virtualAddress,
PHYSICAL_PAGE_CAN_WAIT) != B_OK)
return false;
SHOW_FLOW(4, "buffer=%p, virt_addr=%p, bytes=%d, to_buffer=%d",
buffer, (void *)(virtualAddress + offset), (int)bytes, to_buffer);
buffer, (void *)(virtualAddress + offset), (int)bytes, toBuffer);
if (to_buffer)
if (toBuffer)
memcpy(buffer, (void *)(virtualAddress + offset), bytes);
else
memcpy((void *)(virtualAddress + offset), buffer, bytes);
+24 -29
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2004, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
@@ -48,26 +48,24 @@
#define ERR_TOO_BIG (B_ERRORS_END + 1)
/** Prepare PIO transfer */
/*! Prepare PIO transfer */
void
prep_PIO_transfer(ide_device_info *device, ide_qrequest *qrequest)
{
SHOW_FLOW0(4, "");
device->left_sg_elem = qrequest->request->sg_cnt;
device->left_sg_elem = qrequest->request->sg_count;
device->cur_sg_elem = qrequest->request->sg_list;
device->cur_sg_ofs = 0;
device->has_odd_byte = false;
qrequest->request->data_resid = qrequest->request->data_len;
qrequest->request->data_resid = qrequest->request->data_length;
}
/** transfer virtually continuous data */
/*! Transfer virtually continuous data */
static inline status_t
transfer_PIO_virtcont(ide_device_info *device, uint8 *virtualAddress, int length,
bool write, int *transferred)
transfer_PIO_virtcont(ide_device_info *device, uint8 *virtualAddress,
int length, bool write, int *transferred)
{
ide_bus_info *bus = device->bus;
ide_controller_interface *controller = bus->controller;
@@ -89,7 +87,8 @@ transfer_PIO_virtcont(ide_device_info *device, uint8 *virtualAddress, int length
*transferred += 2;
}
controller->write_pio(channel_cookie, (uint16 *)virtualAddress, length / 2, false);
controller->write_pio(channel_cookie, (uint16 *)virtualAddress,
length / 2, false);
// take care if chunk size was odd, which means that 1 byte remains
virtualAddress += length & ~1;
@@ -108,7 +107,8 @@ transfer_PIO_virtcont(ide_device_info *device, uint8 *virtualAddress, int length
SHOW_FLOW(4, "Reading PIO to %p, %d bytes", virtualAddress, length);
controller->read_pio(channel_cookie, (uint16 *)virtualAddress, length / 2, false);
controller->read_pio(channel_cookie, (uint16 *)virtualAddress,
length / 2, false);
// take care of odd chunk size;
// in this case we read 1 byte to few!
@@ -135,8 +135,7 @@ transfer_PIO_virtcont(ide_device_info *device, uint8 *virtualAddress, int length
}
/** transmit physically continuous data */
/*! Transmit physically continuous data */
static inline status_t
transfer_PIO_physcont(ide_device_info *device, addr_t physicalAddress,
int length, bool write, int *transferred)
@@ -184,8 +183,7 @@ transfer_PIO_physcont(ide_device_info *device, addr_t physicalAddress,
}
/** transfer PIO block from/to buffer */
/*! Transfer PIO block from/to buffer */
static inline int
transfer_PIO_block(ide_device_info *device, int length, bool write, int *transferred)
{
@@ -227,7 +225,7 @@ transfer_PIO_block(ide_device_info *device, int length, bool write, int *transfe
}
/** write zero data (required for ATAPI if we ran out of data) */
/*! Write zero data (required for ATAPI if we ran out of data) */
static void
write_discard_PIO(ide_device_info *device, int length)
@@ -254,8 +252,7 @@ write_discard_PIO(ide_device_info *device, int length)
}
/** read PIO data and discard it (required for ATAPI if buffer was too small) */
/*! Read PIO data and discard it (required for ATAPI if buffer was too small) */
static void
read_discard_PIO(ide_device_info *device, int length)
{
@@ -276,13 +273,12 @@ read_discard_PIO(ide_device_info *device, int length)
}
/** write PIO data
* return: there are 3 possible results
* NO_ERROR - everything's nice and groovy
* ERR_TOO_BIG - data buffer was too short, remaining data got discarded
* B_ERROR - something serious went wrong, sense data was set
*/
/*! write PIO data
return: there are 3 possible results
NO_ERROR - everything's nice and groovy
ERR_TOO_BIG - data buffer was too short, remaining data got discarded
B_ERROR - something serious went wrong, sense data was set
*/
status_t
write_PIO_block(ide_qrequest *qrequest, int length)
{
@@ -327,10 +323,9 @@ write_PIO_block(ide_qrequest *qrequest, int length)
}
/** read PIO data
* return: see write_PIO_block
*/
/*! read PIO data
return: see write_PIO_block
*/
status_t
read_PIO_block(ide_qrequest *qrequest, int length)
{
+98 -113
View File
@@ -1,5 +1,7 @@
/*
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
@@ -25,41 +27,41 @@ ata_mode_sense_10(ide_device_info *device, ide_qrequest *qrequest)
scsi_ccb *request = qrequest->request;
scsi_cmd_mode_sense_10 *cmd = (scsi_cmd_mode_sense_10 *)request->cdb;
scsi_mode_param_header_10 param_header;
scsi_modepage_contr contr;
scsi_modepage_control control;
scsi_mode_param_block_desc block_desc;
size_t total_length = sizeof(scsi_mode_param_header_10)
size_t totalLength = sizeof(scsi_mode_param_header_10)
+ sizeof(scsi_mode_param_block_desc)
+ sizeof(scsi_modepage_contr);
+ sizeof(scsi_modepage_control);
scsi_mode_param_dev_spec_da devspec = {
res0_0 : 0,
DPOFUA : 0,
res0_6 : 0,
WP : 0
_res0_0 : 0,
dpo_fua : 0,
_res0_6 : 0,
write_protected : 0
};
uint32 allocation_length;
uint32 allocationLength;
SHOW_FLOW0(1, "Hi!");
allocation_length = ((int16)cmd->high_allocation_length << 8)
| cmd->low_allocation_length;
allocationLength = B_BENDIAN_TO_HOST_INT16(cmd->allocation_length);
// we answer control page requests and "all pages" requests
// (as the latter are the same as the first)
if ((cmd->page_code != SCSI_MODEPAGE_CONTROL && cmd->page_code != SCSI_MODEPAGE_ALL)
|| (cmd->PC != SCSI_MODE_SENSE_PC_CURRENT && cmd->PC != SCSI_MODE_SENSE_PC_SAVED)) {
|| (cmd->page_control != SCSI_MODE_SENSE_PC_CURRENT
&& cmd->page_control != SCSI_MODE_SENSE_PC_SAVED)) {
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
return;
}
//param_header = (scsi_mode_param_header_10 *)request->data;
param_header.low_mode_data_len = total_length - 1;
param_header.high_mode_data_len = 0;
param_header.mode_data_length = B_HOST_TO_BENDIAN_INT16(totalLength - 1);
param_header.medium_type = 0; // XXX standard is a bit vague here
param_header.dev_spec_parameter = *(uint8 *)&devspec;
param_header.low_block_desc_len = sizeof(scsi_mode_param_block_desc);
param_header.high_block_desc_len = 0;
param_header.block_desc_length
= B_HOST_TO_BENDIAN_INT16(sizeof(scsi_mode_param_block_desc));
copy_sg_data(request, 0, allocation_length, &param_header, sizeof(param_header), false);
copy_sg_data(request, 0, allocationLength, &param_header,
sizeof(param_header), false);
/*block_desc = (scsi_mode_param_block_desc *)(request->data
+ sizeof(*param_header));*/
@@ -70,7 +72,7 @@ ata_mode_sense_10(ide_device_info *device, ide_qrequest *qrequest)
block_desc.med_blocklen = 512 >> 8;
block_desc.low_blocklen = 512 & 0xff;
copy_sg_data(request, sizeof(param_header), allocation_length,
copy_sg_data(request, sizeof(param_header), allocationLength,
&block_desc, sizeof(block_desc), false);
/*contr = (scsi_modepage_contr *)(request->data
@@ -78,33 +80,31 @@ ata_mode_sense_10(ide_device_info *device, ide_qrequest *qrequest)
+ ((uint16)param_header->high_block_desc_len << 8)
+ param_header->low_block_desc_len);*/
memset(&contr, 0, sizeof(contr));
contr.RLEC = false;
contr.DQue = !device->CQ_enabled;
contr.QErr = false;
memset(&control, 0, sizeof(control));
control.RLEC = false;
control.DQue = !device->CQ_enabled;
control.QErr = false;
// when a command fails we requeue all
// lost commands automagically
contr.QAM = SCSI_QAM_UNRESTRICTED;
control.QAM = SCSI_QAM_UNRESTRICTED;
copy_sg_data(request, sizeof(param_header)
+ ((uint16)param_header.high_block_desc_len << 8)
+ param_header.low_block_desc_len,
allocation_length, &contr, sizeof(contr), false);
copy_sg_data(request, sizeof(param_header)
+ B_BENDIAN_TO_HOST_INT16(param_header.block_desc_length),
allocationLength, &control, sizeof(control), false);
// the number of bytes that were transferred to buffer is
// restricted by allocation length and by request data buffer size
total_length = min(total_length, allocation_length);
total_length = min(total_length, request->data_len);
totalLength = min(totalLength, allocationLength);
totalLength = min(totalLength, request->data_length);
request->data_resid = request->data_len - total_length;
request->data_resid = request->data_length - totalLength;
}
/** emulate modifying control page */
/*! Emulate modifying control page */
static bool
ata_mode_select_control_page(ide_device_info *device, ide_qrequest *qrequest,
scsi_modepage_contr *page)
scsi_modepage_control *page)
{
if (page->header.page_length != sizeof(*page) - sizeof(page->header)) {
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_PARAM_LIST_LENGTH_ERR);
@@ -117,8 +117,7 @@ ata_mode_select_control_page(ide_device_info *device, ide_qrequest *qrequest,
}
/** emulate MODE SELECT 10 command */
/*! Emulate MODE SELECT 10 command */
static void
ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -126,50 +125,50 @@ ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
scsi_cmd_mode_select_10 *cmd = (scsi_cmd_mode_select_10 *)request->cdb;
scsi_mode_param_header_10 param_header;
scsi_modepage_header page_header;
uint32 total_length;
uint32 modepage_offset;
uint32 totalLength;
uint32 modepageOffset;
char modepage_buffer[64]; // !!! enlarge this to support longer mode pages
if (cmd->SP || cmd->PF != 1) {
if (cmd->save_pages || cmd->pf != 1) {
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
return;
}
total_length = min(request->data_len,
((uint16)cmd->high_param_list_length << 8) | (uint32)cmd->low_param_list_length);
totalLength = min(request->data_length,
B_BENDIAN_TO_HOST_INT16(cmd->param_list_length));
// first, retrieve page header to get size of different chunks
//param_header = (scsi_mode_param_header_10 *)request->data;
if (!copy_sg_data(request, 0, total_length, &param_header, sizeof(param_header), true))
if (!copy_sg_data(request, 0, totalLength, &param_header, sizeof(param_header), true))
goto err;
total_length = min(total_length, (((uint16)param_header.high_mode_data_len << 8)
| param_header.low_mode_data_len) + 1UL);
totalLength = min(totalLength,
B_BENDIAN_TO_HOST_INT16(param_header.mode_data_length) + 1UL);
// this is the start of the first mode page;
// we ignore the block descriptor silently
modepage_offset = sizeof(param_header) + (((uint16)param_header.high_block_desc_len << 8)
| param_header.low_block_desc_len);
modepageOffset = sizeof(param_header)
+ B_BENDIAN_TO_HOST_INT16(param_header.block_desc_length);
// go through list of pages
while (modepage_offset < total_length) {
uint32 page_len;
while (modepageOffset < totalLength) {
uint32 pageLength;
// get header to know how long page is
if (!copy_sg_data(request, modepage_offset, total_length,
if (!copy_sg_data(request, modepageOffset, totalLength,
&page_header, sizeof(page_header), true))
goto err;
// get size of one page and copy it to buffer
page_len = page_header.page_length + sizeof(scsi_modepage_header);
pageLength = page_header.page_length + sizeof(scsi_modepage_header);
// the buffer has a maximum size - this is really standard compliant but
// sufficient for our needs
if (page_len > sizeof(modepage_buffer))
if (pageLength > sizeof(modepage_buffer))
goto err;
if (!copy_sg_data(request, modepage_offset, total_length,
&modepage_buffer, min(page_len, sizeof(modepage_buffer)), true))
if (!copy_sg_data(request, modepageOffset, totalLength,
&modepage_buffer, min(pageLength, sizeof(modepage_buffer)), true))
goto err;
// modify page;
@@ -177,22 +176,23 @@ ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
switch (page_header.page_code) {
case SCSI_MODEPAGE_CONTROL:
if (!ata_mode_select_control_page(device, qrequest,
(scsi_modepage_contr *)modepage_buffer))
(scsi_modepage_control *)modepage_buffer))
return;
break;
default:
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_PARAM_LIST_FIELD);
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST,
SCSIS_ASC_INV_PARAM_LIST_FIELD);
return;
}
modepage_offset += page_len;
modepageOffset += pageLength;
}
if (modepage_offset != total_length)
if (modepageOffset != totalLength)
goto err;
request->data_resid = request->data_len - total_length;
request->data_resid = request->data_length - totalLength;
return;
// if we arrive here, data length was incorrect
@@ -201,8 +201,7 @@ err:
}
/** emulate TEST UNIT READY */
/*! Emulate TEST UNIT READY */
static bool
ata_test_unit_ready(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -234,8 +233,7 @@ ata_test_unit_ready(ide_device_info *device, ide_qrequest *qrequest)
}
/** flush internal device cache */
/*! Flush internal device cache */
static bool
ata_flush_cache(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -259,10 +257,9 @@ ata_flush_cache(ide_device_info *device, ide_qrequest *qrequest)
}
/** load or eject medium
* load = true - load medium
*/
/*! Load or eject medium
load = true - load medium
*/
static bool
ata_load_eject(ide_device_info *device, ide_qrequest *qrequest, bool load)
{
@@ -284,8 +281,7 @@ ata_load_eject(ide_device_info *device, ide_qrequest *qrequest, bool load)
}
/** emulate PREVENT ALLOW command */
/*! Emulate PREVENT ALLOW command */
static bool
ata_prevent_allow(ide_device_info *device, bool prevent)
{
@@ -294,8 +290,7 @@ ata_prevent_allow(ide_device_info *device, bool prevent)
}
/** emulate INQUIRY command */
/*! Emulate INQUIRY command */
static void
ata_inquiry(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -305,7 +300,7 @@ ata_inquiry(ide_device_info *device, ide_qrequest *qrequest)
uint32 allocation_length = cmd->allocation_length;
uint32 transfer_size;
if (cmd->EVPD || cmd->page_code) {
if (cmd->evpd || cmd->page_code) {
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
return;
}
@@ -316,27 +311,28 @@ ata_inquiry(ide_device_info *device, ide_qrequest *qrequest)
data.device_qualifier = scsi_periph_qual_connected;
data.device_type_modifier = 0;
data.RMB = false;
data.removable_medium = false;
data.ANSI_version = 2;
data.ECMA_version = 0;
data.ISO_version = 0;
data.ansi_version = 2;
data.ecma_version = 0;
data.iso_version = 0;
data.response_data_format = 2;
data.TrmIOP = false; // to be changed if we support TERM I/O
data.term_iop = false;
// to be changed if we support TERM I/O
data.additional_length = sizeof(scsi_res_inquiry) - 4;
data.SftRe = false;
data.CmdQue = device->queue_depth > 1;
data.Linked = false;
data.soft_reset = false;
data.cmd_queue = device->queue_depth > 1;
data.linked = false;
// these values are free-style
data.Sync = false;
data.WBus16 = true;
data.WBus32 = false;
data.sync = false;
data.write_bus16 = true;
data.write_bus32 = false;
data.RelAdr = false;
data.relative_address = false;
// the following fields are *much* to small, sigh...
memcpy(data.vendor_ident, device->infoblock.model_number,
@@ -348,48 +344,38 @@ ata_inquiry(ide_device_info *device, ide_qrequest *qrequest)
copy_sg_data(request, 0, allocation_length, &data, sizeof(data), false);
transfer_size = min(sizeof(data), allocation_length);
transfer_size = min(transfer_size, request->data_len);
transfer_size = min(transfer_size, request->data_length);
request->data_resid = request->data_len - transfer_size;
request->data_resid = request->data_length - transfer_size;
}
/** emulate READ CAPACITY command */
/*! Emulate READ CAPACITY command */
static void
read_capacity(ide_device_info *device, ide_qrequest *qrequest)
{
scsi_ccb *request = qrequest->request;
scsi_res_read_capacity data;
scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb;
uint32 last_block;
uint32 lastBlock;
if (cmd->PMI || cmd->top_LBA || cmd->high_LBA || cmd->mid_LBA || cmd->low_LBA) {
if (cmd->pmi || cmd->lba) {
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
return;
}
// ToDo: 512 bytes fixed block size?
data.top_block_size = (512 >> 24) & 0xff;
data.high_block_size = (512 >> 16) & 0xff;
data.mid_block_size = (512 >> 8) & 0xff;
data.low_block_size = 512 & 0xff;
// TODO: 512 bytes fixed block size?
data.block_size = B_HOST_TO_BENDIAN_INT32(512);
last_block = device->total_sectors - 1;
lastBlock = device->total_sectors - 1;
data.lba = B_HOST_TO_BENDIAN_INT32(lastBlock);
data.top_LBA = (last_block >> 24) & 0xff;
data.high_LBA = (last_block >> 16) & 0xff;
data.mid_LBA = (last_block >> 8) & 0xff;
data.low_LBA = last_block & 0xff;
copy_sg_data(request, 0, request->data_len, &data, sizeof(data), false);
request->data_resid = max(request->data_len - sizeof(data), 0);
copy_sg_data(request, 0, request->data_length, &data, sizeof(data), false);
request->data_resid = max(request->data_length - sizeof(data), 0);
}
/** execute SCSI command */
/*! Execute SCSI command */
void
ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
{
@@ -463,7 +449,7 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
// we must always flush cache if start = 0
ata_flush_cache(device, qrequest);
if (cmd->LoEj)
if (cmd->load_eject)
ata_load_eject(device, qrequest, cmd->start);
break;
@@ -494,14 +480,14 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
// sadly, there are two possible read/write operation codes;
// at least, the third one, read/write(12), is not valid for DAS
case SCSI_OP_READ_6:
case SCSI_OP_WRITE_6: {
case SCSI_OP_WRITE_6:
{
scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)request->cdb;
uint32 pos;
size_t length;
pos = ((uint32)cmd->high_LBA << 16) | ((uint32)cmd->mid_LBA << 8)
| (uint32)cmd->low_LBA;
pos = ((uint32)cmd->high_lba << 16) | ((uint32)cmd->mid_lba << 8)
| (uint32)cmd->low_lba;
length = cmd->length != 0 ? cmd->length : 256;
SHOW_FLOW(3, "READ6/WRITE6 pos=%lx, length=%lx", pos, length);
@@ -511,15 +497,14 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
}
case SCSI_OP_READ_10:
case SCSI_OP_WRITE_10: {
case SCSI_OP_WRITE_10:
{
scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb;
uint32 pos;
size_t length;
pos = ((uint32)cmd->top_LBA << 24) | ((uint32)cmd->high_LBA << 16)
| ((uint32)cmd->mid_LBA << 8) | (uint32)cmd->low_LBA;
length = ((uint32)cmd->high_length << 8) | cmd->low_length;
pos = B_BENDIAN_TO_HOST_INT32(cmd->lba);
length = B_BENDIAN_TO_HOST_INT16(cmd->length);
if (length != 0) {
ata_send_rw(device, qrequest, pos, length, cmd->opcode == SCSI_OP_WRITE_10);
@@ -1,11 +1,11 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Part of Open SCSI bus manager
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*!
Device scanner.
Scans SCSI busses for devices. Scanning is initiated by
@@ -19,10 +19,12 @@
#include <stdlib.h>
// send TUR
// result: true, if device answered
// false, if there is no device
static bool scsi_scan_send_tur( scsi_ccb *worker_req )
/*! send TUR
result: true, if device answered
false, if there is no device
*/
static bool
scsi_scan_send_tur(scsi_ccb *worker_req)
{
scsi_cmd_tur *cmd = (scsi_cmd_tur *)worker_req->cdb;
@@ -33,8 +35,8 @@ static bool scsi_scan_send_tur( scsi_ccb *worker_req )
worker_req->sg_list = NULL;
worker_req->data = NULL;
worker_req->data_len = 0;
worker_req->cdb_len = sizeof( *cmd );
worker_req->data_length = 0;
worker_req->cdb_length = sizeof(*cmd);
worker_req->timeout = 0;
worker_req->sort = -1;
worker_req->flags = 0;
@@ -44,42 +46,41 @@ static bool scsi_scan_send_tur( scsi_ccb *worker_req )
SHOW_FLOW( 3, "status=%x", worker_req->subsys_status );
// as this command was only for syncing, we ignore almost all errors
switch( worker_req->subsys_status ) {
case SCSI_SEL_TIMEOUT:
// there seems to be no device around
return false;
default:
return true;
switch (worker_req->subsys_status) {
case SCSI_SEL_TIMEOUT:
// there seems to be no device around
return false;
default:
return true;
}
}
/** get inquiry data
* returns true on success
*/
/*! get inquiry data
returns true on success
*/
static bool
scsi_scan_get_inquiry(scsi_ccb *worker_req, scsi_res_inquiry *new_inquiry_data)
{
scsi_cmd_inquiry *cmd = (scsi_cmd_inquiry *)worker_req->cdb;
scsi_device_info *device = worker_req->device;
SHOW_FLOW0( 3, "" );
SHOW_FLOW0(3, "");
// in case not whole structure gets transferred, we set remaining data to zero
memset(new_inquiry_data, 0, sizeof(*new_inquiry_data));
cmd->opcode = SCSI_OP_INQUIRY;
cmd->LUN = device->target_lun;
cmd->EVPD = 0;
cmd->lun = device->target_lun;
cmd->evpd = 0;
cmd->page_code = 0;
cmd->allocation_length = sizeof( *new_inquiry_data );
cmd->allocation_length = sizeof(*new_inquiry_data);
worker_req->sg_list = NULL;
worker_req->data = (uchar *)new_inquiry_data;
worker_req->data_len = sizeof(*new_inquiry_data);
worker_req->cdb_len = 6;
worker_req->data_length = sizeof(*new_inquiry_data);
worker_req->cdb_length = 6;
worker_req->timeout = SCSI_STD_TIMEOUT;
worker_req->sort = -1;
worker_req->flags = SCSI_DIR_IN;
@@ -102,7 +103,7 @@ scsi_scan_get_inquiry(scsi_ccb *worker_req, scsi_res_inquiry *new_inquiry_data)
SHOW_INFO(3, "device type: %d, qualifier: %d, removable: %d, ANSI version: %d, response data format: %d\n"
"vendor: %s, product: %s, rev: %s",
new_inquiry_data->device_type, new_inquiry_data->device_qualifier,
new_inquiry_data->RMB, new_inquiry_data->ANSI_version,
new_inquiry_data->removable_medium, new_inquiry_data->ansi_version,
new_inquiry_data->response_data_format,
vendor, product, rev);
@@ -114,19 +115,17 @@ scsi_scan_get_inquiry(scsi_ccb *worker_req, scsi_res_inquiry *new_inquiry_data)
// bad luck
if (min(cmd->allocation_length, new_inquiry_data->additional_length + 4)
>= (int)offsetof(scsi_res_inquiry, version_descriptor[9])) {
int i, prev_standard;
prev_standard = -1;
int i, previousStandard = -1;
for (i = 0; i < 8; ++i) {
int standard = (new_inquiry_data->version_descriptor[0].high << 8) |
new_inquiry_data->version_descriptor[0].low;
int standard = B_BENDIAN_TO_HOST_INT16(
new_inquiry_data->version_descriptor[i]);
// omit standards reported twice
if( standard != prev_standard && standard != 0 )
SHOW_INFO( 3, "standard: %04x", standard );
if (standard != previousStandard && standard != 0)
SHOW_INFO(3, "standard: %04x", standard);
prev_standard = standard;
previousStandard = standard;
}
}
@@ -135,7 +134,7 @@ scsi_scan_get_inquiry(scsi_ccb *worker_req, scsi_res_inquiry *new_inquiry_data)
/* {
unsigned int i;
for( i = 0; i < worker_req->data_len - worker_req->data_resid; ++i ) {
for( i = 0; i < worker_req->data_length - worker_req->data_resid; ++i ) {
dprintf( "%2x ", *((char *)new_inquiry_data + i) );
}
@@ -160,25 +159,24 @@ scsi_scan_lun(scsi_bus_info *bus, uchar target_id, uchar target_lun)
scsi_device_info *device;
bool found;
//snooze( 1000000 );
//snooze(1000000);
SHOW_FLOW( 3, "%d:%d:%d", bus->path_id, target_id, target_lun );
SHOW_FLOW(3, "%d:%d:%d", bus->path_id, target_id, target_lun);
res = scsi_force_get_device(bus, target_id, target_lun, &device);
if (res != B_OK)
goto err;
//SHOW_FLOW( 3, "temp_device: %d", (int)temp_device );
//SHOW_FLOW(3, "temp_device: %d", (int)temp_device);
worker_req = scsi_alloc_ccb(device);
if (worker_req == NULL) {
// there is no out-of-mem code
res = B_NO_MEMORY;
goto err2;
}
SHOW_FLOW0( 3, "2" );
SHOW_FLOW0(3, "2");
worker_req->flags = SCSI_DIR_IN;
@@ -245,44 +243,42 @@ scsi_scan_bus(scsi_bus_info *bus)
SHOW_FLOW0( 3, "" );
// get ID of initiator (i.e. controller)
res = scsi_inquiry_path( bus, &inquiry );
if( res != SCSI_REQ_CMP )
res = scsi_inquiry_path(bus, &inquiry);
if (res != SCSI_REQ_CMP)
return B_ERROR;
initiator_id = inquiry.initiator_id;
SHOW_FLOW( 3, "initiator_id=%d", initiator_id );
SHOW_FLOW(3, "initiator_id=%d", initiator_id);
// tell SIM to rescan bus (needed at least by IDE translator)
// as this function is optional for SIM, we ignore its result
bus->interface->scan_bus( bus->sim_cookie );
for( target_id = 0; target_id <= 1/*MAX_TARGET_ID*/; ++target_id ) {
bus->interface->scan_bus(bus->sim_cookie);
for (target_id = 0; target_id <= 1/*MAX_TARGET_ID*/; ++target_id) {
int lun;
SHOW_FLOW( 3, "target: %d", target_id );
if( target_id == initiator_id )
SHOW_FLOW(3, "target: %d", target_id);
if (target_id == initiator_id)
continue;
// TODO: there are a lot of devices out there that go mad if you probe
// anything but LUN 0, so we should probably add a black-list
// or something
for( lun = 0; lun <= MAX_LUN_ID; ++lun ) {
for (lun = 0; lun <= MAX_LUN_ID; ++lun) {
status_t res;
SHOW_FLOW( 3, "lun: %d", lun );
res = scsi_scan_lun( bus, target_id, lun );
SHOW_FLOW(3, "lun: %d", lun);
res = scsi_scan_lun(bus, target_id, lun);
// if there is no device at lun 0, there's probably no device at all
if( lun == 0 && res != SCSI_REQ_CMP )
if (lun == 0 && res != SCSI_REQ_CMP)
break;
}
}
SHOW_FLOW0( 3, "done" );
SHOW_FLOW0(3, "done");
return B_OK;
}
@@ -253,9 +253,9 @@ scsi_create_autosense_request(scsi_device_info *device)
goto err;
request->data = buffer;
request->data_len = SCSI_MAX_SENSE_SIZE;
request->data_length = SCSI_MAX_SENSE_SIZE;
request->sg_list = (physical_entry *)(buffer + SCSI_MAX_SENSE_SIZE);
request->sg_cnt = 1;
request->sg_count = 1;
get_memory_map(buffer, SCSI_MAX_SENSE_SIZE,
(physical_entry *)request->sg_list, 1);
@@ -268,12 +268,12 @@ scsi_create_autosense_request(scsi_device_info *device)
SCSI_ORDERED_QTAG | SCSI_DMA_SAFE;
cmd = (scsi_cmd_request_sense *)request->cdb;
request->cdb_len = sizeof(*cmd);
request->cdb_length = sizeof(*cmd);
memset(cmd, 0, sizeof(*cmd));
cmd->opcode = SCSI_OP_REQUEST_SENSE;
cmd->LUN = device->target_lun;
cmd->alloc_length = SCSI_MAX_SENSE_SIZE;
cmd->lun = device->target_lun;
cmd->allocation_length = SCSI_MAX_SENSE_SIZE;
return B_OK;
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
@@ -32,14 +32,13 @@
#include <string.h>
/** check whether S/G list of request is supported DMA controller */
/*! Check whether S/G list of request is supported DMA controller */
static bool
is_sg_list_dma_safe(scsi_ccb *request)
{
scsi_bus_info *bus = request->bus;
const physical_entry *sg_list = request->sg_list;
uint32 sg_count = request->sg_cnt;
uint32 sg_count = request->sg_count;
uint32 dma_boundary = bus->dma_params.dma_boundary;
uint32 alignment = bus->dma_params.alignment;
uint32 max_sg_block_size = bus->dma_params.max_sg_block_size;
@@ -102,13 +101,13 @@ scsi_copy_dma_buffer(scsi_ccb *request, uint32 size, bool to_buffer)
{
dma_buffer *buffer = request->dma_buffer;
const physical_entry *sg_list = buffer->sg_list_orig;
uint32 num_vecs = buffer->sg_cnt_orig;
uint32 num_vecs = buffer->sg_count_orig;
char *buffer_data = buffer->address;
SHOW_FLOW(1, "to_buffer=%d, %d bytes", to_buffer, (int)size);
// survive even if controller returned invalid data size
size = min(size, request->data_len);
size = min(size, request->data_length);
// we have to use S/G list to original data; the DMA buffer
// was allocated in kernel and is thus visible even if the thread
@@ -288,7 +287,7 @@ scsi_alloc_dma_buffer(dma_buffer *buffer, dma_params *dma_params, uint32 size)
res = get_iovec_memory_map(
&vec, 1, 0, buffer->size,
buffer->sg_list, sg_list_entries, &buffer->sg_cnt,
buffer->sg_list, sg_list_entries, &buffer->sg_count,
&mapped_len );
if( res != B_OK || mapped_len != buffer->size ) {
@@ -307,7 +306,7 @@ scsi_free_dma_buffer_sg_orig(dma_buffer *buffer)
if (buffer->sg_orig > 0) {
delete_area(buffer->sg_orig);
buffer->sg_orig = 0;
buffer->sg_cnt_max_orig = 0;
buffer->sg_count_max_orig = 0;
}
}
@@ -332,17 +331,16 @@ scsi_alloc_dma_buffer_sg_orig(dma_buffer *buffer, int size)
return false;
}
buffer->sg_cnt_max_orig = size / sizeof(physical_entry);
buffer->sg_count_max_orig = size / sizeof(physical_entry);
SHOW_INFO(3, "Got up to %d S/G entries to original data",
(int)buffer->sg_cnt_max_orig);
(int)buffer->sg_count_max_orig);
return true;
}
/** helper: dump S/G table */
/*! dump S/G table */
static void
dump_sg_table(const physical_entry *sg_list,
uint32 sg_list_count)
@@ -364,17 +362,17 @@ static bool
scsi_dma_buffer_compose_sg_orig(dma_buffer *buffer, scsi_ccb *request)
{
// enlarge buffer is required
if (buffer->sg_cnt_max_orig < request->sg_cnt) {
if (!scsi_alloc_dma_buffer_sg_orig(buffer, request->sg_cnt))
if (buffer->sg_count_max_orig < request->sg_count) {
if (!scsi_alloc_dma_buffer_sg_orig(buffer, request->sg_count))
return false;
}
SHOW_FLOW0(1, "copy S/G list");
memcpy(buffer->sg_list_orig, request->sg_list,
request->sg_cnt * sizeof(physical_entry));
request->sg_count * sizeof(physical_entry));
buffer->sg_cnt_orig = request->sg_cnt;
buffer->sg_count_orig = request->sg_count;
return true;
}
@@ -397,7 +395,7 @@ scsi_get_dma_buffer(scsi_ccb *request)
SHOW_FLOW0(1, "Buffer is not DMA safe" );
dump_sg_table(request->sg_list, request->sg_cnt);
dump_sg_table(request->sg_list, request->sg_count);
// only one buffer at a time
acquire_sem(device->dma_buffer_owner);
@@ -416,9 +414,9 @@ scsi_get_dma_buffer(scsi_ccb *request)
request->dma_buffer = buffer;
// enlarge buffer if too small
if (buffer->size < request->data_len) {
if (buffer->size < request->data_length) {
if (!scsi_alloc_dma_buffer(buffer, &device->bus->dma_params,
request->data_len))
request->data_length))
goto err;
}
@@ -429,20 +427,20 @@ scsi_get_dma_buffer(scsi_ccb *request)
// copy data to buffer
if ((request->flags & SCSI_DIR_MASK) == SCSI_DIR_OUT) {
if (!scsi_copy_dma_buffer( request, request->data_len, true))
if (!scsi_copy_dma_buffer( request, request->data_length, true))
goto err;
}
// replace data address, so noone notices that a buffer is used
buffer->orig_data = request->data;
buffer->orig_sg_list = request->sg_list;
buffer->orig_sg_cnt = request->sg_cnt;
buffer->orig_sg_count = request->sg_count;
request->data = buffer->address;
request->sg_list = buffer->sg_list;
request->sg_cnt = buffer->sg_cnt;
request->sg_count = buffer->sg_count;
SHOW_INFO(1, "bytes: %d", (int)request->data_len);
SHOW_INFO(1, "bytes: %d", (int)request->data_length);
SHOW_INFO0(3, "we can start now");
request->buffered = true;
@@ -463,10 +461,9 @@ err:
}
/** copy data back and release DMA buffer;
* you must have called cleanup_tmp_sg before
*/
/*! Copy data back and release DMA buffer;
you must have called cleanup_tmp_sg before
*/
void
scsi_release_dma_buffer(scsi_ccb *request)
{
@@ -480,12 +477,12 @@ scsi_release_dma_buffer(scsi_ccb *request)
// copy data from buffer if required and if operation succeeded
if ((request->subsys_status & SCSI_SUBSYS_STATUS_MASK) == SCSI_REQ_CMP
&& (request->flags & SCSI_DIR_MASK) == SCSI_DIR_IN)
scsi_copy_dma_buffer(request, request->data_len - request->data_resid, false );
scsi_copy_dma_buffer(request, request->data_length - request->data_resid, false);
// restore request
request->data = buffer->orig_data;
request->sg_list = buffer->orig_sg_list;
request->sg_cnt = buffer->orig_sg_cnt;
request->sg_count = buffer->orig_sg_count;
// free buffer
ACQUIRE_BEN(&device->dma_buffer_lock);
@@ -537,5 +534,5 @@ scsi_dma_buffer_init(dma_buffer *buffer)
buffer->area = 0;
buffer->size = 0;
buffer->sg_orig = 0;
buffer->sg_cnt_max_orig = 0;
buffer->sg_count_max_orig = 0;
}
+102 -119
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
@@ -31,8 +31,7 @@ static void release_emulation_buffer(scsi_ccb *request);
static void restore_request_data(scsi_ccb *request);
/** free emulation buffer */
/*! Free emulation buffer */
void
scsi_free_emulation_buffer(scsi_device_info *device)
{
@@ -49,10 +48,9 @@ scsi_free_emulation_buffer(scsi_device_info *device)
}
/** setup buffer used to emulate unsupported SCSI commands
* buffer_size must be power of two
*/
/*! Setup buffer used to emulate unsupported SCSI commands
buffer_size must be power of two
*/
status_t
scsi_init_emulation_buffer(scsi_device_info *device, size_t buffer_size)
{
@@ -98,17 +96,17 @@ scsi_init_emulation_buffer(scsi_device_info *device, size_t buffer_size)
device->buffer_sg_list = (void *)(aligned_addr + buffer_size);
device->buffer_sg_list[0].address = (void *)aligned_phys;
device->buffer_sg_list[0].size = buffer_size;
device->buffer_sg_cnt = 1;
device->buffer_sg_count = 1;
return B_OK;
}
/** some ATAPI devices don't like 6 byte read/write commands, so
* we translate them to their 10 byte partners;
* USB devices usually don't like 10 bytes either
*/
/*!
Some ATAPI devices don't like 6 byte read/write commands, so
we translate them to their 10 byte counterparts;
USB devices usually don't like 10 bytes either
*/
static bool
scsi_read_write_6(scsi_ccb *request)
{
@@ -117,50 +115,46 @@ scsi_read_write_6(scsi_ccb *request)
SHOW_FLOW0(3, "patching READ/WRITE(6) to READ/WRITE(10)");
request->cdb_len = sizeof(*cdb);
request->cdb_length = sizeof(*cdb);
memset(cdb, 0, sizeof(*cdb));
cdb->opcode = cmd->opcode + (SCSI_OP_READ_10 - SCSI_OP_READ_6);
cdb->LUN = cmd->LUN;
cdb->low_LBA = cmd->low_LBA;
cdb->mid_LBA = cmd->mid_LBA;
cdb->high_LBA = cmd->high_LBA;
cdb->low_length = cmd->length;
cdb->high_length = cmd->length == 0;
cdb->lun = cmd->lun;
cdb->lba = B_HOST_TO_BENDIAN_INT32((uint32)cmd->low_lba
| ((uint32)cmd->mid_lba << 8) | ((uint32)cmd->high_lba << 16));
cdb->length = B_HOST_TO_BENDIAN_INT16((uint16)cmd->length);
cdb->control = cmd->control;
return true;
}
/** all ATAPI devices don't like 6 byte MODE SENSE, so we translate
* that to 10 byte MODE SENSE
*/
/*! All ATAPI devices don't like 6 byte MODE SENSE, so we translate
that to 10 byte MODE SENSE
*/
static bool
scsi_start_mode_sense_6(scsi_ccb *request)
{
scsi_cmd_mode_sense_6 *cmd = (scsi_cmd_mode_sense_6 *)request->orig_cdb;
scsi_cmd_mode_sense_10 *cdb = (scsi_cmd_mode_sense_10 *)request->cdb;
size_t allocation_length;
size_t allocationLength;
SHOW_FLOW0(3, "patching MODE SENSE(6) to MODE SENSE(10)");
request->cdb_len = sizeof(*cdb);
request->cdb_length = sizeof(*cdb);
memset(cdb, 0, sizeof(*cdb));
cdb->opcode = SCSI_OP_MODE_SENSE_10;
cdb->DBD = cmd->DBD;
cdb->LUN = cmd->LUN;
cdb->disable_block_desc = cmd->disable_block_desc;
cdb->lun = cmd->lun;
cdb->page_code = cmd->page_code;
cdb->PC = cmd->PC;
cdb->page_control = cmd->page_control;
allocation_length = cmd->allocation_length
allocationLength = cmd->allocation_length
- sizeof(scsi_cmd_mode_sense_6) + sizeof(scsi_cmd_mode_sense_10);
cdb->high_allocation_length = allocation_length >> 8;
cdb->low_allocation_length = allocation_length & 0xff;
cdb->allocation_length = B_HOST_TO_BENDIAN_INT16(allocationLength);
SHOW_FLOW(3, "allocation_length=%ld", allocation_length);
SHOW_FLOW(3, "allocation_length=%ld", allocationLength);
cdb->control = cmd->control;
@@ -170,15 +164,14 @@ scsi_start_mode_sense_6(scsi_ccb *request)
replace_request_data(request);
// restrict data buffer len to length specified in cdb
request->data_len = allocation_length;
request->data_length = allocationLength;
return true;
}
/** all ATAPI devices don't like 6 byte MODE SELECT, so we translate
* that to 10 byte MODE SELECT
*/
/*! All ATAPI devices don't like 6 byte MODE SELECT, so we translate
that to 10 byte MODE SELECT
*/
static bool
scsi_start_mode_select_6(scsi_ccb *request)
{
@@ -204,16 +197,14 @@ scsi_start_mode_select_6(scsi_ccb *request)
goto err;
// construct new cdb
request->cdb_len = sizeof(*cdb);
request->cdb_length = sizeof(*cdb);
memset(cdb, 0, sizeof(*cdb));
cdb->opcode = SCSI_OP_MODE_SELECT_10;
cdb->SP = cmd->SP;
cdb->PF = cmd->PF;
cdb->LUN = cmd->LUN;
cdb->high_param_list_length = param_list_length_10 >> 8;
cdb->low_param_list_length = param_list_length_10 & 0xff;
cdb->save_pages = cmd->save_pages;
cdb->pf = cmd->pf;
cdb->lun = cmd->lun;
cdb->param_list_length = B_HOST_TO_BENDIAN_INT16(param_list_length_10);
SHOW_FLOW(3, "param_list_length=%ld", param_list_length_6);
@@ -228,17 +219,18 @@ scsi_start_mode_select_6(scsi_ccb *request)
// mode_data_len is reserved for MODE SELECT
header_10->medium_type = header_6.medium_type;
header_10->dev_spec_parameter = header_6.dev_spec_parameter;
header_10->low_block_desc_len = header_6.block_desc_len;
header_10->block_desc_length = B_HOST_TO_BENDIAN_INT16(
(uint16)header_6.block_desc_length);
// append actual mode select data
if (!copy_sg_data( request, sizeof(header_6), param_list_length_6, header_10 + 1,
if (!copy_sg_data(request, sizeof(header_6), param_list_length_6, header_10 + 1,
param_list_length_10 - sizeof(*header_10), true))
goto err;
replace_request_data(request);
// restrict buffer size to the one specified in cdb
request->data_len = param_list_length_10;
request->data_length = param_list_length_10;
return true;
err:
@@ -249,10 +241,9 @@ err:
}
/** emulation procedure at start of command
* returns false if command is to be finished without further execution
*/
/*! Emulation procedure at start of command
returns false if command is to be finished without further execution
*/
bool
scsi_start_emulation(scsi_ccb *request)
{
@@ -261,7 +252,7 @@ scsi_start_emulation(scsi_ccb *request)
SHOW_FLOW(3, "command=%x", request->cdb[0]);
memcpy(request->orig_cdb, request->cdb, SCSI_MAX_CDB_SIZE);
request->orig_cdb_len = request->cdb_len;
request->orig_cdb_length = request->cdb_length;
switch (request->orig_cdb[0]) {
case SCSI_OP_READ_6:
@@ -279,8 +270,7 @@ scsi_start_emulation(scsi_ccb *request)
}
/** back-translate MODE SENSE 10 to MODE SENSE 6 */
/*! Back-translate MODE SENSE 10 to MODE SENSE 6 */
static void
scsi_finish_mode_sense_10_6(scsi_ccb *request)
{
@@ -289,7 +279,8 @@ scsi_finish_mode_sense_10_6(scsi_ccb *request)
scsi_mode_param_header_10 *header_10 = (scsi_mode_param_header_10 *)device->buffer;
int transfer_size_6, transfer_size_10;
if (request->subsys_status != SCSI_REQ_CMP || request->device_status != SCSI_STATUS_GOOD) {
if (request->subsys_status != SCSI_REQ_CMP
|| request->device_status != SCSI_STATUS_GOOD) {
// on error, do nothing
release_emulation_buffer(request);
return;
@@ -297,7 +288,7 @@ scsi_finish_mode_sense_10_6(scsi_ccb *request)
// check how much data we got from device and thus will copy into
// request data
transfer_size_10 = request->data_len - request->data_resid;
transfer_size_10 = request->data_length - request->data_resid;
transfer_size_6 = transfer_size_10
- sizeof(scsi_mode_param_header_10 *) + sizeof(scsi_mode_param_header_6 *);
@@ -310,13 +301,13 @@ scsi_finish_mode_sense_10_6(scsi_ccb *request)
// convert total length
// (+1 is there because mode_data_len in 10 byte header ignores first
// two bytes, whereas in the 6 byte header it ignores only one byte)
header_6.mode_data_len = header_10->low_mode_data_len
header_6.mode_data_length = B_BENDIAN_TO_HOST_INT16(header_10->mode_data_length)
- sizeof(scsi_mode_param_header_10) + sizeof(scsi_mode_param_header_6)
+ 1;
header_6.medium_type = header_10->medium_type;
header_6.dev_spec_parameter = header_10->dev_spec_parameter;
header_6.block_desc_len = header_10->low_block_desc_len;
header_6.block_desc_length = B_BENDIAN_TO_HOST_INT16(header_10->block_desc_length);
// copy adapted header
copy_sg_data(request, 0, transfer_size_6, &header_6, sizeof(header_6), false);
@@ -325,14 +316,13 @@ scsi_finish_mode_sense_10_6(scsi_ccb *request)
copy_sg_data(request, sizeof(header_6), transfer_size_6,
header_10 + 1, transfer_size_10 - sizeof(*header_10), false);
request->data_resid = request->data_len - transfer_size_6;
request->data_resid = request->data_length - transfer_size_6;
release_emulation_buffer(request);
}
/** back-translate MODE SELECT 10 to MODE SELECT 6 */
/*! Back-translate MODE SELECT 10 to MODE SELECT 6 */
static void
scsi_finish_mode_select_10_6(scsi_ccb *request)
{
@@ -348,35 +338,34 @@ scsi_finish_mode_select_10_6(scsi_ccb *request)
}
/** fix inquiry data; some ATAPI devices return wrong version */
/*! Fix inquiry data; some ATAPI devices return wrong version */
static void
scsi_finish_inquiry(scsi_ccb *request)
{
int transfer_size;
int transferSize;
scsi_res_inquiry res;
SHOW_FLOW0(3, "fixing INQUIRY");
if (request->subsys_status != SCSI_REQ_CMP || request->device_status != SCSI_STATUS_GOOD)
if (request->subsys_status != SCSI_REQ_CMP
|| request->device_status != SCSI_STATUS_GOOD)
return;
transfer_size = request->data_len - request->data_resid;
transferSize = request->data_length - request->data_resid;
copy_sg_data(request, 0, transfer_size, &res, sizeof(res), true);
copy_sg_data(request, 0, transferSize, &res, sizeof(res), true);
SHOW_FLOW(3, "ANSI version: %d, response data format: %d",
res.ANSI_version, res.response_data_format);
res.ansi_version, res.response_data_format);
res.ANSI_version = 2;
res.ansi_version = 2;
res.response_data_format = 2;
copy_sg_data(request, 0, transfer_size, &res, sizeof(res), false);
copy_sg_data(request, 0, transferSize, &res, sizeof(res), false);
}
/** adjust result of emulated request */
/*! Adjust result of emulated request */
void
scsi_finish_emulation(scsi_ccb *request)
{
@@ -398,12 +387,11 @@ scsi_finish_emulation(scsi_ccb *request)
// restore cdb
memcpy(request->cdb, request->orig_cdb, SCSI_MAX_CDB_SIZE);
request->cdb_len = request->orig_cdb_len;
request->cdb_length = request->orig_cdb_length;
}
/** set sense of request */
/*! Set sense of request */
static void
set_sense(scsi_ccb *request, int sense_key, int sense_asc)
{
@@ -433,43 +421,42 @@ set_sense(scsi_ccb *request, int sense_key, int sense_asc)
}
/** copy data between request data and buffer
* request - request to copy data from/to
* offset - offset of data in request
* allocation_length- limit of request's data buffer according to CDB
* buffer - data to copy data from/to
* size - number of bytes to copy
* to_buffer - true: copy from request to buffer
* false: copy from buffer to request
* return: true, if data of request was large enough
*/
/*! Copy data between request data and buffer
request - request to copy data from/to
offset - offset of data in request
allocation_length- limit of request's data buffer according to CDB
buffer - data to copy data from/to
size - number of bytes to copy
to_buffer - true: copy from request to buffer
false: copy from buffer to request
return: true, if data of request was large enough
*/
static bool
copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length,
void *buffer, int size, bool to_buffer)
{
const physical_entry *sg_list = request->sg_list;
int sg_cnt = request->sg_cnt;
int sg_count = request->sg_count;
int req_size;
SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_cnt=%d, %s buffer",
offset, allocation_length, size, sg_list, sg_cnt, to_buffer ? "to" : "from");
SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_count=%d, %s buffer",
offset, allocation_length, size, sg_list, sg_count, to_buffer ? "to" : "from");
// skip unused S/G entries
while (sg_cnt > 0 && offset >= sg_list->size) {
while (sg_count > 0 && offset >= sg_list->size) {
offset -= sg_list->size;
++sg_list;
--sg_cnt;
--sg_count;
}
if (sg_cnt == 0)
if (sg_count == 0)
return 0;
// remaining bytes we are allowed to copy from/to request
req_size = min(allocation_length, request->data_len) - offset;
req_size = min(allocation_length, request->data_length) - offset;
// copy one S/G entry at a time
for (; size > 0 && req_size > 0 && sg_cnt > 0; ++sg_list, --sg_cnt) {
for (; size > 0 && req_size > 0 && sg_count > 0; ++sg_list, --sg_count) {
size_t bytes;
addr_t virtualAddress;
@@ -516,67 +503,63 @@ copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length,
}
/** allocate emulation buffer */
/*! Allocate emulation buffer */
static void
get_emulation_buffer(scsi_ccb *request)
{
scsi_device_info *device = request->device;
SHOW_FLOW0( 3, "" );
SHOW_FLOW0(3, "");
acquire_sem(device->buffer_sem);
request->orig_sg_list = request->sg_list;
request->orig_sg_cnt = request->sg_cnt;
request->orig_data_len = request->data_len;
request->orig_sg_count = request->sg_count;
request->orig_data_length = request->data_length;
request->sg_list = device->buffer_sg_list;
request->sg_cnt = device->buffer_sg_cnt;
request->data_len = device->buffer_size;
request->sg_count = device->buffer_sg_count;
request->data_length = device->buffer_size;
}
/** replace request data with emulation buffer, saving original pointer;
* you must have called get_emulation_buffer() first
*/
/*! Replace request data with emulation buffer, saving original pointer;
you must have called get_emulation_buffer() first
*/
static void
replace_request_data(scsi_ccb *request)
{
scsi_device_info *device = request->device;
SHOW_FLOW0( 3, "" );
SHOW_FLOW0(3, "");
request->orig_sg_list = request->sg_list;
request->orig_sg_cnt = request->sg_cnt;
request->orig_data_len = request->data_len;
request->orig_sg_count = request->sg_count;
request->orig_data_length = request->data_length;
request->sg_list = device->buffer_sg_list;
request->sg_cnt = device->buffer_sg_cnt;
request->data_len = device->buffer_size;
request->sg_count = device->buffer_sg_count;
request->data_length = device->buffer_size;
}
/** release emulation buffer */
/*! Release emulation buffer */
static void
release_emulation_buffer(scsi_ccb *request)
{
SHOW_FLOW0( 3, "" );
SHOW_FLOW0(3, "");
release_sem(request->device->buffer_sem);
}
/** restore original request data pointers */
/*! Restore original request data pointers */
static void
restore_request_data(scsi_ccb *request)
{
SHOW_FLOW0( 3, "" );
SHOW_FLOW0(3, "");
request->sg_list = request->orig_sg_list;
request->sg_cnt = request->orig_sg_cnt;
request->data_len = request->orig_data_len;
request->sg_count = request->orig_sg_count;
request->data_length = request->orig_data_length;
}
@@ -1,12 +1,11 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Part of Open SCSI bus manager
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*!
Creates temporary Scatter/Gather table if the peripheral
driver has provided a simple pointer only.
*/
@@ -17,7 +16,8 @@
#include <string.h>
#include <iovec.h>
locked_pool_cookie temp_sg_pool;
static locked_pool_cookie temp_sg_pool;
static bool
@@ -30,14 +30,14 @@ fill_temp_sg(scsi_ccb *ccb)
uint32 max_sg_blocks = min(bus->dma_params.max_sg_blocks, MAX_TEMP_SG_FRAGMENTS);
iovec vec = {
ccb->data,
ccb->data_len
ccb->data_length
};
size_t num_entries;
size_t mapped_len;
uint32 cur_idx;
physical_entry *temp_sg = (physical_entry *)ccb->sg_list;
res = get_iovec_memory_map(&vec, 1, 0, ccb->data_len, temp_sg, max_sg_blocks,
res = get_iovec_memory_map(&vec, 1, 0, ccb->data_length, temp_sg, max_sg_blocks,
&num_entries, &mapped_len);
if (res != B_OK) {
@@ -45,10 +45,10 @@ fill_temp_sg(scsi_ccb *ccb)
return false;
}
if (mapped_len != ccb->data_len)
if (mapped_len != ccb->data_length)
goto too_complex;
if (dma_boundary != ~0UL || ccb->data_len > max_sg_block_size) {
if (dma_boundary != ~0UL || ccb->data_length > max_sg_block_size) {
// S/G list may not be controller-compatible:
// we have to split offending entries
SHOW_FLOW(3, "Checking violation of dma boundary 0x%x and entry size 0x%x",
@@ -82,7 +82,7 @@ fill_temp_sg(scsi_ccb *ccb)
}
}
ccb->sg_cnt = num_entries;
ccb->sg_count = num_entries;
return true;
@@ -102,7 +102,7 @@ create_temp_sg(scsi_ccb *ccb)
physical_entry *temp_sg;
status_t res;
SHOW_FLOW(3, "ccb=%p, data=%p, data_len=%lu", ccb, ccb->data, ccb->data_len);
SHOW_FLOW(3, "ccb=%p, data=%p, data_length=%lu", ccb, ccb->data, ccb->data_length);
ccb->sg_list = temp_sg = locked_pool->alloc(temp_sg_pool);
if (temp_sg == NULL) {
@@ -110,7 +110,7 @@ create_temp_sg(scsi_ccb *ccb)
return false;
}
res = lock_memory(ccb->data, ccb->data_len, B_DMA_IO
res = lock_memory(ccb->data, ccb->data_length, B_DMA_IO
| ((ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN ? B_READ_DEVICE : 0));
if (res != B_OK) {
@@ -122,7 +122,7 @@ create_temp_sg(scsi_ccb *ccb)
// this is the success path
return true;
unlock_memory(ccb->data, ccb->data_len, B_DMA_IO
unlock_memory(ccb->data, ccb->data_length, B_DMA_IO
| ((ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN ? B_READ_DEVICE : 0));
err:
@@ -147,11 +147,11 @@ cleanup_tmp_sg(scsi_ccb *ccb)
{
status_t res;
SHOW_FLOW( 3, "ccb=%p, data=%p, data_len=%d",
ccb, ccb->data, (int)ccb->data_len );
SHOW_FLOW(3, "ccb=%p, data=%p, data_length=%d",
ccb, ccb->data, (int)ccb->data_length);
res = unlock_memory( ccb->data, ccb->data_len, B_DMA_IO |
((ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN ? B_READ_DEVICE : 0));
res = unlock_memory(ccb->data, ccb->data_length, B_DMA_IO
| ((ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN ? B_READ_DEVICE : 0));
if (res != B_OK) {
SHOW_FLOW0(3, "Cannot unlock previously locked memory!");
@@ -2,15 +2,10 @@
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef __SCSI_INTERNAL_H__
#define __SCSI_INTERNAL_H__
/*
Part of Open SCSI bus manager
Internal structures/definitions
*/
#ifndef _SCSI_INTERNAL_H
#define _SCSI_INTERNAL_H
//! Internal structures/definitions
#include <bus/SCSI.h>
@@ -146,18 +141,18 @@ typedef struct dma_buffer {
uint32 size; // size of DMA buffer
area_id sg_list_area; // area of S/G list
physical_entry *sg_list; // address of S/G list
uint32 sg_cnt; // number of entries in S/G list
uint32 sg_count; // number of entries in S/G list
bool inuse; // true, if in use
bigtime_t last_use; // timestamp of last usage
area_id sg_orig; // area of S/G list to original data
physical_entry *sg_list_orig; // S/G list to original data
uint32 sg_cnt_max_orig; // maximum size (in entries)
uint32 sg_cnt_orig; // current size (in entries)
uint32 sg_count_max_orig; // maximum size (in entries)
uint32 sg_count_orig; // current size (in entries)
uchar *orig_data; // pointer to original data
const physical_entry *orig_sg_list; // original S/G list
uint32 orig_sg_cnt; // size of original S/G list
const physical_entry *orig_sg_list; // original S/G list
uint32 orig_sg_count; // size of original S/G list
} dma_buffer;
@@ -169,7 +164,7 @@ typedef struct scsi_device_info {
bool manual_autosense : 1; // no autosense support
bool is_atapi : 1; // ATAPI device - needs some commands emulated
int lock_count; // sum of blocked[0..1] and sim_overflow
int lock_count; // sum of blocked[0..1] and sim_overflow
int blocked[2]; // depth of nested locks by bus manager (0) and SIM (1)
int sim_overflow; // 1, if SIM returned a request because of device queue overflow
int left_slots; // left command queuing slots for device
@@ -209,7 +204,7 @@ typedef struct scsi_device_info {
// buffer used for emulating SCSI commands
char *buffer;
physical_entry *buffer_sg_list;
size_t buffer_sg_cnt;
size_t buffer_sg_count;
size_t buffer_size;
area_id buffer_area;
sem_id buffer_sem;
@@ -253,89 +248,78 @@ extern struct pnp_devfs_driver_info scsi_bus_raw_module;
// bus_mgr.c
uchar scsi_inquiry_path( scsi_bus bus, scsi_path_inquiry *inquiry_data );
// busses.c
uchar scsi_inquiry_path(scsi_bus bus, scsi_path_inquiry *inquiry_data);
// ccb.c
scsi_ccb *scsi_alloc_ccb(scsi_device_info *device);
void scsi_free_ccb(scsi_ccb *ccb);
// ccb_mgr.c
scsi_ccb *scsi_alloc_ccb( scsi_device_info *device );
void scsi_free_ccb( scsi_ccb *ccb );
status_t scsi_init_ccb_alloc( scsi_bus_info *bus );
void scsi_uninit_ccb_alloc( scsi_bus_info *bus );
status_t scsi_init_ccb_alloc(scsi_bus_info *bus);
void scsi_uninit_ccb_alloc(scsi_bus_info *bus);
// device_mgr.c
status_t scsi_force_get_device( scsi_bus_info *bus,
uchar target_id, uchar target_lun, scsi_device_info **res_device );
void scsi_put_forced_device( scsi_device_info *device );
status_t scsi_register_device( scsi_bus_info *bus, uchar target_id,
uchar target_lun, scsi_res_inquiry *inquiry_data );
// devices.c
status_t scsi_force_get_device(scsi_bus_info *bus,
uchar target_id, uchar target_lun, scsi_device_info **res_device);
void scsi_put_forced_device(scsi_device_info *device);
status_t scsi_register_device(scsi_bus_info *bus, uchar target_id,
uchar target_lun, scsi_res_inquiry *inquiry_data);
// device_scan.c
status_t scsi_scan_bus( scsi_bus_info *bus );
status_t scsi_scan_lun( scsi_bus_info *bus, uchar target_id, uchar target_lun );
status_t scsi_scan_bus(scsi_bus_info *bus);
status_t scsi_scan_lun(scsi_bus_info *bus, uchar target_id, uchar target_lun);
// dpc.c
status_t scsi_alloc_dpc(scsi_dpc_info **dpc);
status_t scsi_free_dpc(scsi_dpc_info *dpc);
bool scsi_check_exec_dpc(scsi_bus_info *bus);
status_t scsi_alloc_dpc( scsi_dpc_info **dpc );
status_t scsi_free_dpc( scsi_dpc_info *dpc );
bool scsi_check_exec_dpc( scsi_bus_info *bus );
status_t scsi_schedule_dpc( scsi_bus_info *bus, scsi_dpc_info *dpc, /*int flags,*/
void (*func)( void *arg ), void *arg );
status_t scsi_schedule_dpc(scsi_bus_info *bus, scsi_dpc_info *dpc, /*int flags,*/
void (*func)( void *arg ), void *arg);
// scsi_io.c
void scsi_async_io(scsi_ccb *request);
void scsi_sync_io(scsi_ccb *request);
uchar scsi_term_io(scsi_ccb *ccb_to_terminate);
uchar scsi_abort(scsi_ccb *ccb_to_abort);
void scsi_async_io( scsi_ccb *request );
void scsi_sync_io( scsi_ccb *request );
uchar scsi_term_io( scsi_ccb *ccb_to_terminate );
uchar scsi_abort( scsi_ccb *ccb_to_abort );
bool scsi_check_exec_service(scsi_bus_info *bus);
bool scsi_check_exec_service( scsi_bus_info *bus );
void scsi_done_io(scsi_ccb *ccb);
void scsi_done_io( scsi_ccb *ccb );
void scsi_requeue_request( scsi_ccb *request, bool bus_overflow );
void scsi_resubmit_request( scsi_ccb *request );
void scsi_request_finished( scsi_ccb *request, uint num_requests );
void scsi_requeue_request(scsi_ccb *request, bool bus_overflow);
void scsi_resubmit_request(scsi_ccb *request);
void scsi_request_finished(scsi_ccb *request, uint num_requests);
// sg_mgr.c
// scatter_gather.c
bool create_temp_sg(scsi_ccb *ccb);
void cleanup_tmp_sg(scsi_ccb *ccb);
bool create_temp_sg( scsi_ccb *ccb );
void cleanup_tmp_sg( scsi_ccb *ccb );
int init_temp_sg( void );
void uninit_temp_sg( void );
int init_temp_sg(void);
void uninit_temp_sg(void);
// dma_buffer.c
void scsi_dma_buffer_daemon( void *dev, int counter );
void scsi_release_dma_buffer( scsi_ccb *request );
bool scsi_get_dma_buffer( scsi_ccb *request );
void scsi_dma_buffer_free( dma_buffer *buffer );
void scsi_dma_buffer_init( dma_buffer *buffer );
void scsi_dma_buffer_daemon(void *dev, int counter);
void scsi_release_dma_buffer(scsi_ccb *request);
bool scsi_get_dma_buffer(scsi_ccb *request);
void scsi_dma_buffer_free(dma_buffer *buffer);
void scsi_dma_buffer_init(dma_buffer *buffer);
// queuing.c
// emulation.c
bool scsi_start_emulation(scsi_ccb *request);
void scsi_finish_emulation(scsi_ccb *request);
void scsi_free_emulation_buffer(scsi_device_info *device);
status_t scsi_init_emulation_buffer(scsi_device_info *device, size_t buffer_size);
bool scsi_start_emulation( scsi_ccb *request );
void scsi_finish_emulation( scsi_ccb *request );
void scsi_free_emulation_buffer( scsi_device_info *device );
status_t scsi_init_emulation_buffer( scsi_device_info *device, size_t buffer_size );
#endif
#endif /* _SCSI_INTERNAL_H */
+16 -18
View File
@@ -1,13 +1,11 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2004, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI bus manager
Handling of SCSI I/O requests
*/
//! Part of Open SCSI bus manager
#include "scsi_internal.h"
@@ -184,7 +182,7 @@ finish_autosense(scsi_device_info *device)
// we got sense data -> copy it to sense buffer
sense_len = min(SCSI_MAX_SENSE_SIZE,
request->data_len - request->data_resid);
request->data_length - request->data_resid);
SHOW_FLOW(3, "Got sense: %d bytes", sense_len);
@@ -407,9 +405,9 @@ scsi_async_io(scsi_ccb *request)
if (request->state != SCSI_STATE_FINISHED)
panic("Passed ccb to scsi_action that isn't ready (state = %d)\n", request->state);
if (request->cdb_len < func_group_len[request->cdb[0] >> 5]) {
if (request->cdb_length < func_group_len[request->cdb[0] >> 5]) {
SHOW_ERROR(3, "invalid command len (%d instead of %d)",
request->cdb_len, func_group_len[request->cdb[0] >> 5]);
request->cdb_length, func_group_len[request->cdb[0] >> 5]);
request->subsys_status = SCSI_REQ_INVALID;
goto err;
@@ -417,7 +415,7 @@ scsi_async_io(scsi_ccb *request)
FAST_LOGN(request->device->log, ev_scsi_async_io,
func_group_len[request->cdb[0] >> 5] + 2,
(uint32)request, request->data_len,
(uint32)request, request->data_length,
request->cdb[0], request->cdb[1], request->cdb[2], request->cdb[3],
request->cdb[4], request->cdb[5], request->cdb[6], request->cdb[7],
request->cdb[8], request->cdb[9], request->cdb[10], request->cdb[11],
@@ -432,9 +430,9 @@ scsi_async_io(scsi_ccb *request)
}
if ((request->flags & SCSI_DIR_MASK) != SCSI_DIR_NONE
&& request->sg_list == NULL && request->data_len > 0) {
&& request->sg_list == NULL && request->data_length > 0) {
SHOW_ERROR( 3, "Asynchronous SCSI I/O requires S/G list (data is %d bytes)",
(int)request->data_len );
(int)request->data_length );
request->subsys_status = SCSI_DATA_RUN_ERR;
goto err;
}
@@ -443,7 +441,7 @@ scsi_async_io(scsi_ccb *request)
// make data DMA safe
// (S/G list must be created first to be able to verify DMA restrictions)
if ((request->flags & SCSI_DMA_SAFE) == 0 && request->data_len > 0) {
if ((request->flags & SCSI_DMA_SAFE) == 0 && request->data_length > 0) {
request->buffered = true;
if (!scsi_get_dma_buffer(request)) {
SHOW_ERROR0( 3, "cannot create DMA buffer for request - reduce data volume" );
@@ -459,7 +457,7 @@ scsi_async_io(scsi_ccb *request)
request->emulated = true;
if (!scsi_start_emulation(request)) {
SHOW_ERROR( 3, "cannot emulate SCSI command 0x%02x", request->cdb[0] );
SHOW_ERROR(3, "cannot emulate SCSI command 0x%02x", request->cdb[0]);
goto err2;
}
}
@@ -475,7 +473,7 @@ scsi_async_io(scsi_ccb *request)
// abuse TUR to find proper spot in command packet for LUN
scsi_cmd_tur *cmd = (scsi_cmd_tur *)request->cdb;
cmd->LUN = request->device->target_lun;
cmd->lun = request->device->target_lun;
}
request->ordered = (request->flags & SCSI_ORDERED_QTAG) != 0;
@@ -513,7 +511,7 @@ scsi_sync_io(scsi_ccb *request)
// create scatter-gather list if required
if ((request->flags & SCSI_DIR_MASK) != SCSI_DIR_NONE
&& request->sg_list == NULL && request->data_len > 0) {
&& request->sg_list == NULL && request->data_length > 0) {
tmp_sg = true;
if (!create_temp_sg(request)) {
SHOW_ERROR0( 3, "data is too much fragmented - you should use s/g list" );
@@ -1,13 +1,12 @@
/*
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI Disk Driver
//! Device management.
Device management.
*/
#include "scsi_cd_int.h"
@@ -143,7 +142,7 @@ cd_device_added(device_node_handle node)
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: B_BLOCK_IO_MODULE_NAME }},
// tell block_io whether the device is removable
{ "removable", B_UINT8_TYPE, { ui8: device_inquiry->RMB }},
{ "removable", B_UINT8_TYPE, { ui8: device_inquiry->removable_medium }},
// tell which name we want to have in devfs
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
// impose own max block restriction
@@ -1,18 +1,20 @@
/*
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI CD-ROM driver
//! Main file.
Main file.
*/
#include "scsi_cd_int.h"
#include <string.h>
#include <scsi.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
extern block_device_interface cd_interface;
@@ -116,7 +118,7 @@ get_toc(cd_device_info *device, scsi_toc *toc)
scsi_ccb *ccb;
status_t res;
scsi_cmd_read_toc *cmd;
size_t data_len;
size_t dataLength;
scsi_toc_general *short_response = (scsi_toc_general *)toc->toc_data;
SHOW_FLOW0(0, "");
@@ -132,20 +134,19 @@ get_toc(cd_device_info *device, scsi_toc *toc)
memset(cmd, 0, sizeof(*cmd));
cmd->opcode = SCSI_OP_READ_TOC;
cmd->TIME = 1;
cmd->time = 1;
cmd->format = SCSI_TOC_FORMAT_TOC;
cmd->track = 1;
cmd->high_allocation_length = 0;
cmd->low_allocation_length = sizeof(scsi_toc_general);
cmd->allocation_length = B_HOST_TO_BENDIAN_INT16(sizeof(scsi_toc_general));
ccb->cdb_len = sizeof(*cmd);
ccb->cdb_length = sizeof(*cmd);
ccb->sort = -1;
ccb->timeout = SCSI_CD_STD_TIMEOUT;
ccb->data = toc->toc_data;
ccb->sg_list = NULL;
ccb->data_len = sizeof(toc->toc_data);
ccb->data_length = sizeof(toc->toc_data);
res = scsi_periph->safe_exec(device->scsi_periph_device, ccb);
if (res != B_OK)
@@ -158,14 +159,13 @@ get_toc(cd_device_info *device, scsi_toc *toc)
// but scsi_toc_toc has already one track, so we get
// last - first extra tracks; finally, we want the lead-out as
// well, so we add an extra track)
data_len = (short_response->last - short_response->first + 1)
dataLength = (short_response->last - short_response->first + 1)
* sizeof(scsi_toc_track) + sizeof(scsi_toc_toc);
data_len = min(data_len, sizeof(toc->toc_data));
dataLength = min(dataLength, sizeof(toc->toc_data));
SHOW_FLOW(0, "data_len: %d", (int)data_len);
SHOW_FLOW(0, "data_length: %d", (int)dataLength);
cmd->high_allocation_length = data_len >> 8;
cmd->low_allocation_length = data_len & 0xff;
cmd->allocation_length = B_HOST_TO_BENDIAN_INT16(dataLength);
res = scsi_periph->safe_exec(device->scsi_periph_device, ccb);
@@ -204,12 +204,11 @@ get_position(cd_device_info *device, scsi_position *position)
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = SCSI_OP_READ_SUB_CHANNEL;
cmd.TIME = 1;
cmd.SUBQ = 1;
cmd.time = 1;
cmd.subq = 1;
cmd.parameter_list = scsi_sub_channel_parameter_list_cd_pos;
cmd.track = 0;
cmd.high_allocation_length = sizeof(*position) >> 8;
cmd.low_allocation_length = sizeof(*position) & 0xff;
cmd.allocation_length = B_HOST_TO_BENDIAN_INT16(sizeof(scsi_position));
return scsi_periph->simple_exec(device->scsi_periph_device,
&cmd, sizeof(cmd), position, sizeof(*position), SCSI_DIR_IN);
@@ -232,7 +231,7 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = SCSI_OP_MODE_SENSE_6;
cmd.page_code = SCSI_MODEPAGE_AUDIO;
cmd.PC = SCSI_MODE_SENSE_PC_CURRENT;
cmd.page_control = SCSI_MODE_SENSE_PC_CURRENT;
cmd.allocation_length = sizeof(header);
memset(&header, -2, sizeof(header));
@@ -242,12 +241,12 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
if (res != B_OK)
return res;
SHOW_FLOW(0, "block_desc_len=%d", header.block_desc_len);
SHOW_FLOW(0, "block_desc_len=%d", header.block_desc_length);
// ToDo: why this??
return B_ERROR;
// retrieve param header, block descriptor and actual codepage
len = sizeof(header) + header.block_desc_len
len = sizeof(header) + header.block_desc_length
+ sizeof(scsi_modepage_audio);
buffer = malloc(len);
@@ -266,11 +265,12 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
}
SHOW_FLOW(3, "mode_data_len=%d, block_desc_len=%d",
((scsi_mode_param_header_6 *)buffer)->mode_data_len,
((scsi_mode_param_header_6 *)buffer)->block_desc_len);
((scsi_mode_param_header_6 *)buffer)->mode_data_length,
((scsi_mode_param_header_6 *)buffer)->block_desc_length);
// find control page and retrieve values
page = (scsi_modepage_audio *)((char *)buffer + sizeof(header) + header.block_desc_len);
page = (scsi_modepage_audio *)((char *)buffer + sizeof(header)
+ header.block_desc_length);
SHOW_FLOW(0, "page=%p, codepage=%d", page, page->header.page_code);
@@ -312,8 +312,8 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = SCSI_OP_MODE_SELECT_6;
cmd.PF = 1;
cmd.param_list_length = sizeof(header) + header.block_desc_len
cmd.pf = 1;
cmd.param_list_length = sizeof(header) + header.block_desc_length
+ sizeof(*page);
res = scsi_periph->simple_exec(device->scsi_periph_device,
@@ -351,8 +351,7 @@ play_msf(cd_device_info *device, scsi_play_position *buf)
}
/** play audio cd; time is in track/index */
/*! Play audio cd; time is in track/index */
static status_t
play_track_index(cd_device_info *device, scsi_play_track *buf)
{
@@ -468,7 +467,7 @@ scan(cd_device_info *device, scsi_scan *buf)
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = SCSI_OP_SCAN;
cmd.Direct = buf->direction < 0;
cmd.direct = buf->direction < 0;
cmd.start.time = cd_pos->absolute_address.time;
cmd.type = scsi_scan_msf;
@@ -501,33 +500,28 @@ read_cd(cd_device_info *device, scsi_read_cd *read_cd)
return B_NO_MEMORY;
cmd = (scsi_cmd_read_cd *)ccb->cdb;
memset( cmd, 0, sizeof( *cmd ));
memset(cmd, 0, sizeof(*cmd));
cmd->opcode = SCSI_OP_READ_CD;
cmd->sector_type = 1;
// skip first two seconds, they are lead-in
lba = (read_cd->start_m * 60 + read_cd->start_s) * 75 + read_cd->start_f
- 2 * 75;
cmd->lba.top = (lba >> 24) & 0xff;
cmd->lba.high = (lba >> 16) & 0xff;
cmd->lba.mid = (lba >> 8) & 0xff;
cmd->lba.low = lba & 0xff;
length = (read_cd->length_m * 60 + read_cd->length_s) * 75 + read_cd->length_f;
cmd->lba = B_HOST_TO_BENDIAN_INT32(lba);
cmd->high_length = (length >> 16) & 0xff;
cmd->mid_length = (length >> 8) & 0xff;
cmd->low_length = length & 0xff;
cmd->error_field = scsi_read_cd_error_none;
cmd->EDC_ECC = 0;
cmd->edc_ecc = 0;
cmd->user_data = 1;
cmd->header_code = scsi_read_cd_header_none;
cmd->SYNC = 0;
cmd->sync = 0;
cmd->sub_channel_selection = scsi_read_cd_sub_channel_none;
ccb->cdb_len = sizeof(*cmd);
ccb->cdb_length = sizeof(*cmd);
ccb->flags = SCSI_DIR_IN | SCSI_DIS_DISCONNECT;
ccb->sort = lba;
@@ -536,7 +530,7 @@ read_cd(cd_device_info *device, scsi_read_cd *read_cd)
ccb->data = read_cd->buffer;
ccb->sg_list = NULL;
ccb->data_len = read_cd->buffer_length;
ccb->data_length = read_cd->buffer_length;
res = scsi_periph->safe_exec(device->scsi_periph_device, ccb);
@@ -1,18 +1,17 @@
/*
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2004, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI Disk Driver
Device management.
*/
//! Device management.
#include "scsi_dsk_int.h"
#include <pnp_devfs.h>
#include <stdlib.h>
#include <string.h>
@@ -138,7 +137,7 @@ das_device_added(device_node_handle node)
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: SCSI_DSK_MODULE_NAME }},
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: B_BLOCK_IO_MODULE_NAME }},
// tell block_io whether the device is removable
{ "removable", B_UINT8_TYPE, { ui8: device_inquiry->RMB }},
{ "removable", B_UINT8_TYPE, { ui8: device_inquiry->removable_medium }},
// tell which name we want to have in devfs
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
// impose own max block restriction
+16 -24
View File
@@ -1,13 +1,11 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI Peripheral Driver
Handling of block device (currently, only a capacity check is provided)
*/
//! Handling of block device (currently, only a capacity check is provided)
#include "scsi_periph_int.h"
@@ -17,10 +15,10 @@
status_t
periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request)
{
scsi_res_read_capacity capacity_res;
scsi_res_read_capacity capacityResult;
scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb;
uint64 capacity;
uint32 block_size;
uint32 blockSize;
status_t res;
SHOW_FLOW(3, "%p, %p", device, request);
@@ -32,9 +30,9 @@ periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request)
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->data = (char *)&capacityResult;
request->data_length = sizeof(capacityResult);
request->cdb_length = sizeof(scsi_cmd_read_capacity);
request->timeout = device->std_timeout;
request->sort = -1;
request->sg_list = NULL;
@@ -56,28 +54,22 @@ periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request)
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;
capacity = B_BENDIAN_TO_HOST_INT32(capacityResult.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;
blockSize = B_BENDIAN_TO_HOST_INT32(capacityResult.block_size);
} else {
capacity = 0;
block_size = 0;
blockSize = 0;
}
SHOW_FLOW(3, "capacity = %Ld, block_size = %ld", capacity, block_size);
SHOW_FLOW(3, "capacity = %Ld, block_size = %ld", capacity, blockSize);
device->callbacks->set_capacity(device->periph_device,
capacity, block_size);
capacity, blockSize);
/* device->byte2blk_shift = log2( device->block_size );
if( device->byte2blk_shift < 0 ) {
+26 -33
View File
@@ -1,14 +1,12 @@
/*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI Disk Driver
Everything doing the real input/output stuff.
*/
//! Everything doing the real input/output stuff.
#include "scsi_periph_int.h"
#include <scsi.h>
@@ -25,28 +23,29 @@ static int periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *v
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)
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);
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)
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);
bytes_transferred, preferred_ccb_size, true);
}
/** universal read/write function */
/*! 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)
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;
@@ -90,8 +89,8 @@ periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *vecs,
request->data = NULL;
request->sg_list = vecs->vec;
request->data_len = num_bytes;
request->sg_cnt = vecs->num;
request->data_length = num_bytes;
request->sg_count = vecs->num;
request->sort = pos;
request->timeout = device->std_timeout;
// see whether daemon instructed us to post an ordered command;
@@ -108,12 +107,12 @@ periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *vecs,
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->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);
request->cdb_length = sizeof(*cmd);
} else {
scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb;
@@ -121,19 +120,13 @@ periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *vecs,
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->relative_address = 0;
cmd->force_unit_access = 0;
cmd->disable_page_out = 0;
cmd->lba = B_HOST_TO_BENDIAN_INT32(pos);
cmd->length = B_HOST_TO_BENDIAN_INT16(num_blocks);
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);
request->cdb_length = sizeof(*cmd);
}
// last chance to detect errors that occured during concurrent accesses
@@ -242,12 +235,12 @@ raw_command(scsi_periph_device_info *device, raw_device_command *cmd)
request->data = cmd->data;
request->sg_list = NULL;
request->data_len = cmd->data_length;
request->data_length = 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;
request->cdb_length = cmd->command_length;
device->scsi->sync_io(request);
@@ -1,13 +1,11 @@
/*
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI Peripheral Driver
Handling of removable media.
*/
//! Handling of removable media.
#include "scsi_periph_int.h"
@@ -25,7 +23,7 @@ periph_media_changed(scsi_periph_device_info *device, scsi_ccb *request)
bigtime_t backup_timeout;
uchar *backup_data;
const physical_entry *backup_sg_list;
uint16 backup_sg_cnt;
uint16 backup_sg_count;
uint32 backup_data_len;
// if there is no hook, the driver doesn't handle removal devices
@@ -44,26 +42,26 @@ periph_media_changed(scsi_periph_device_info *device, scsi_ccb *request)
// path)
backup_flags = request->flags;
memcpy(backup_cdb, request->cdb, SCSI_MAX_CDB_SIZE);
backup_cdb_len = request->cdb_len;
backup_cdb_len = request->cdb_length;
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;
backup_sg_count = request->sg_count;
backup_data_len = request->data_length;
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->cdb_length = 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;
request->sg_count = backup_sg_count;
request->data_length = backup_data_len;
}
@@ -94,7 +92,7 @@ send_tur(scsi_periph_device_info *device, scsi_ccb *request)
request->data = NULL;
request->sg_list = NULL;
request->data_len = 0;
request->data_length = 0;
request->timeout = device->std_timeout;
request->sort = -1;
request->sg_list = NULL;
@@ -102,7 +100,7 @@ send_tur(scsi_periph_device_info *device, scsi_ccb *request)
memset(cmd, 0, sizeof(*cmd));
cmd->opcode = SCSI_OP_TUR;
request->cdb_len = sizeof(*cmd);
request->cdb_length = sizeof(*cmd);
device->scsi->sync_io(request);
@@ -194,14 +192,13 @@ 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
*/
/*! Send START/STOP command to device
start - true for start, false for stop
withLoadEject - 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)
periph_send_start_stop(scsi_periph_device_info *device, scsi_ccb *request,
bool start, bool withLoadEject)
{
scsi_cmd_ssu *cmd = (scsi_cmd_ssu *)request->cdb;
@@ -210,7 +207,7 @@ periph_send_start_stop(scsi_periph_device_info *device, scsi_ccb *request,
request->data = NULL;
request->sg_list = NULL;
request->data_len = 0;
request->data_length = 0;
request->timeout = device->std_timeout;
request->sort = -1;
request->sg_list = NULL;
@@ -219,11 +216,11 @@ periph_send_start_stop(scsi_periph_device_info *device, scsi_ccb *request,
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->immediately = 0;
cmd->start = start;
cmd->LoEj = with_LoEj;
cmd->load_eject = withLoadEject;
request->cdb_len = sizeof(*cmd);
request->cdb_length = sizeof(*cmd);
device->scsi->sync_io(request);
@@ -1,13 +1,12 @@
/*
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI Peripheral Driver
//! Main file.
Main file.
*/
#include "scsi_periph_int.h"
@@ -20,8 +19,8 @@ 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)
periph_simple_exec(scsi_periph_device_info *device, void *cdb, uchar cdbLength,
void *data, size_t dataLength, int ccb_flags)
{
scsi_ccb *ccb;
status_t res;
@@ -34,15 +33,15 @@ periph_simple_exec(scsi_periph_device_info *device, void *cdb, uchar cdb_len,
ccb->flags = ccb_flags;
memcpy(ccb->cdb, cdb, cdb_len);
ccb->cdb_len = cdb_len;
memcpy(ccb->cdb, cdb, cdbLength);
ccb->cdb_length = cdbLength;
ccb->sort = -1;
ccb->timeout = device->std_timeout;
ccb->data = data;
ccb->sg_list = NULL;
ccb->data_len = data_len;
ccb->data_length = dataLength;
res = periph_safe_exec(device, ccb);
@@ -63,7 +62,6 @@ periph_safe_exec(scsi_periph_device_info *device, scsi_ccb *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
@@ -76,18 +74,18 @@ periph_safe_exec(scsi_periph_device_info *device, scsi_ccb *request)
bigtime_t backup_timeout;
uchar *backup_data;
const physical_entry *backup_sg_list;
uint16 backup_sg_cnt;
uint16 backup_sg_count;
uint32 backup_data_len;
backup_flags = request->flags;
memcpy(backup_cdb, request->cdb, SCSI_MAX_CDB_SIZE);
backup_cdb_len = request->cdb_len;
backup_cdb_len = request->cdb_length;
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;
backup_sg_count = request->sg_count;
backup_data_len = request->data_length;
SHOW_INFO0( 2, "Sending start to init LUN" );
@@ -95,13 +93,13 @@ periph_safe_exec(scsi_periph_device_info *device, scsi_ccb *request)
request->flags = backup_flags;
memcpy(request->cdb, backup_cdb, SCSI_MAX_CDB_SIZE);
request->cdb_len = backup_cdb_len;
request->cdb_length = 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;
request->sg_count = backup_sg_count;
request->data_length = backup_data_len;
if (res.action == err_act_ok)
res.action = err_act_retry;
@@ -3,13 +3,13 @@
* Distributed under the terms of the MIT License.
*
* Authors:
* Bruno Albuquerque, bga@bug-br.org.br
* Bruno Albuquerque, bga@bug-br.org.br
*
* Copyright 2004-2006 yellowTAB GMbH. This file is
* based on work I did for ZETA while employed by
* yellowTAB and is used under permission.
*
*/
*/
#include "scsi_periph_int.h"
@@ -17,6 +17,7 @@
#include <string.h>
err_res
periph_synchronize_cache(scsi_periph_device_info *device, scsi_ccb *request)
{
@@ -26,20 +27,19 @@ periph_synchronize_cache(scsi_periph_device_info *device, scsi_ccb *request)
request->data = NULL;
request->sg_list = NULL;
request->data_len = 0;
request->data_length = 0;
request->timeout = device->std_timeout;
request->sort = -1;
memset(cmd, 0, sizeof(*cmd));
cmd->opcode = SCSI_OP_SYNCHRONIZE_CACHE;
cmd->immed = 0;
cmd->immediately = 0;
// TODO(bga): Maybe we will actually want to set those one day...
cmd->nblocks_high = 0;
cmd->nblocks_low = 0;
// TODO: Maybe we will actually want to set this one day...
cmd->block_count = 0;
request->cdb_len = sizeof(*cmd);
request->cdb_length = sizeof(*cmd);
device->scsi->sync_io(request);