* 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:
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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, ¶m_header, sizeof(param_header), false);
|
||||
copy_sg_data(request, 0, allocationLength, ¶m_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, ¶m_header, sizeof(param_header), true))
|
||||
if (!copy_sg_data(request, 0, totalLength, ¶m_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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user