* 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.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _SCSI_BUSMANAGER_H_
|
#ifndef _SCSI_BUSMANAGER_H
|
||||||
#define _SCSI_BUSMANAGER_H_
|
#define _SCSI_BUSMANAGER_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SCSI bus manager interface
|
SCSI bus manager interface
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
Something about requests involving data transfer: you can either specify
|
Something about requests involving data transfer: you can either specify
|
||||||
the virtual address in <data> of CCB (in which case it must be continuous),
|
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
|
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
|
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
|
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
|
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)
|
// structure of one scsi i/o CCB (command control block)
|
||||||
typedef struct scsi_ccb
|
typedef struct scsi_ccb {
|
||||||
{
|
|
||||||
struct scsi_ccb *next, *prev; // internal
|
struct scsi_ccb *next, *prev; // internal
|
||||||
|
|
||||||
uchar subsys_status; // Returned subsystem status
|
uchar subsys_status; // Returned subsystem status
|
||||||
@@ -126,14 +125,14 @@ typedef struct scsi_ccb
|
|||||||
sem_id completion_sem;
|
sem_id completion_sem;
|
||||||
|
|
||||||
uint8 cdb[SCSI_MAX_CDB_SIZE]; // command data block
|
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)
|
int64 sort; // value of command to sort on (<0 means n/a)
|
||||||
bigtime_t timeout; // timeout - 0 = use default
|
bigtime_t timeout; // timeout - 0 = use default
|
||||||
|
|
||||||
uchar *data; // pointer to data
|
uchar *data; // pointer to data
|
||||||
const physical_entry *sg_list; // SG list
|
const physical_entry *sg_list; // scatter/gather list
|
||||||
uint16 sg_cnt; // number of SG entries
|
uint16 sg_count; // number of S/G entries
|
||||||
uint32 data_len; // length of data
|
uint32 data_length; // length of data
|
||||||
int32 data_resid; // data transfer residual length: 2's comp
|
int32 data_resid; // data transfer residual length: 2's comp
|
||||||
|
|
||||||
uchar sense[SCSI_MAX_SENSE_SIZE]; // autosense data
|
uchar sense[SCSI_MAX_SENSE_SIZE]; // autosense data
|
||||||
@@ -151,10 +150,10 @@ typedef struct scsi_ccb
|
|||||||
|
|
||||||
// original data before command emulation was applied
|
// original data before command emulation was applied
|
||||||
uint8 orig_cdb[SCSI_MAX_CDB_SIZE];
|
uint8 orig_cdb[SCSI_MAX_CDB_SIZE];
|
||||||
uchar orig_cdb_len;
|
uchar orig_cdb_length;
|
||||||
const physical_entry *orig_sg_list;
|
const physical_entry *orig_sg_list;
|
||||||
uint16 orig_sg_cnt;
|
uint16 orig_sg_count;
|
||||||
uint32 orig_data_len;
|
uint32 orig_data_length;
|
||||||
|
|
||||||
// private SIM data
|
// private SIM data
|
||||||
uchar sim_state; // set to zero when request is submitted first time
|
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
|
// Path inquiry, extended by BeOS XPT_EXTENDED_PATH_INQ parameters
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uchar version_num; /* Version number for the SIM/HBA */
|
uchar version_num; /* Version number for the SIM/HBA */
|
||||||
uchar hba_inquiry; /* Mimic of INQ byte 7 for the HBA */
|
uchar hba_inquiry; /* Mimic of INQ byte 7 for the HBA */
|
||||||
uchar hba_misc; /* Misc HBA feature flags */
|
uchar hba_misc; /* Misc HBA feature flags */
|
||||||
@@ -457,4 +455,4 @@ typedef struct scsi_sim_interface {
|
|||||||
} 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.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* 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
|
Use this module to minimize work required to write a SCSI
|
||||||
peripheral driver.
|
peripheral driver.
|
||||||
|
|
||||||
@@ -15,8 +17,6 @@
|
|||||||
- detection of medium capacity
|
- detection of medium capacity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SCSI_PERIPH_H__
|
|
||||||
#define __SCSI_PERIPH_H__
|
|
||||||
|
|
||||||
#include <bus/SCSI.h>
|
#include <bus/SCSI.h>
|
||||||
#include <block_io.h>
|
#include <block_io.h>
|
||||||
@@ -161,4 +161,4 @@ typedef struct scsi_periph_interface {
|
|||||||
|
|
||||||
#define SCSI_PERIPH_MODULE_NAME "generic/scsi_periph/v1"
|
#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.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -26,10 +26,10 @@
|
|||||||
#define IDE_ATAPI_BUFFER_SIZE 512
|
#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
|
static bool
|
||||||
check_packet_error(ide_device_info *device, ide_qrequest *qrequest)
|
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
|
void
|
||||||
packet_dpc(ide_qrequest *qrequest)
|
packet_dpc(ide_qrequest *qrequest)
|
||||||
{
|
{
|
||||||
@@ -248,7 +247,7 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
|
|
||||||
SHOW_FLOW(3, "finished: %d of %d left",
|
SHOW_FLOW(3, "finished: %d of %d left",
|
||||||
(int)qrequest->request->data_resid,
|
(int)qrequest->request->data_resid,
|
||||||
(int)qrequest->request->data_len);
|
(int)qrequest->request->data_length);
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(qrequest);
|
||||||
return;
|
return;
|
||||||
@@ -263,8 +262,7 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Create taskfile for ATAPI packet */
|
/*! Create taskfile for ATAPI packet */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
create_packet_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
create_packet_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
||||||
bool write)
|
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.dma = qrequest->uses_dma;
|
||||||
device->tf.packet.ovl = 0;
|
device->tf.packet.ovl = 0;
|
||||||
device->tf.packet.byte_count_0_7 = request->data_len & 0xff;
|
device->tf.packet.byte_count_0_7 = request->data_length & 0xff;
|
||||||
device->tf.packet.byte_count_8_15 = request->data_len >> 8;
|
device->tf.packet.byte_count_8_15 = request->data_length >> 8;
|
||||||
device->tf.packet.command = IDE_CMD_PACKET;
|
device->tf.packet.command = IDE_CMD_PACKET;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Send ATAPI packet */
|
/*! Send ATAPI packet */
|
||||||
|
|
||||||
void
|
void
|
||||||
send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write)
|
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] );
|
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[0], device->packet[1], device->packet[2],
|
||||||
device->packet[3], device->packet[4], device->packet[5],
|
device->packet[3], device->packet[4], device->packet[5],
|
||||||
device->packet[6], device->packet[7], device->packet[8],
|
device->packet[6], device->packet[7], device->packet[8],
|
||||||
device->packet[9], device->packet[10], device->packet[11],
|
device->packet[9], device->packet[10], device->packet[11],
|
||||||
qrequest->request->cdb_len );
|
qrequest->request->cdb_length);
|
||||||
|
|
||||||
//snooze( 1000000 );
|
//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
|
// report how much data is transmitted, and this information is
|
||||||
// crucial for the SCSI protocol)
|
// crucial for the SCSI protocol)
|
||||||
// special offer: let READ_CD commands use DMA too
|
// special offer: let READ_CD commands use DMA too
|
||||||
qrequest->uses_dma = device->DMA_enabled &&
|
qrequest->uses_dma = device->DMA_enabled
|
||||||
(scsi_cmd == SCSI_OP_READ_6 || scsi_cmd == SCSI_OP_WRITE_6 ||
|
&& (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_10 || scsi_cmd == SCSI_OP_WRITE_10
|
||||||
scsi_cmd == SCSI_OP_READ_12 || scsi_cmd == SCSI_OP_WRITE_12 ||
|
|| scsi_cmd == SCSI_OP_READ_12 || scsi_cmd == SCSI_OP_WRITE_12
|
||||||
scsi_cmd == SCSI_OP_READ_CD );
|
|| scsi_cmd == SCSI_OP_READ_CD);
|
||||||
|
|
||||||
// try preparing DMA, if that fails, fall back to PIO
|
// try preparing DMA, if that fails, fall back to PIO
|
||||||
if (qrequest->uses_dma) {
|
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
|
void
|
||||||
atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
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;
|
// ATAPI command packets are 12 bytes long;
|
||||||
// if the command is shorter, remaining bytes must be padded with zeros
|
// if the command is shorter, remaining bytes must be padded with zeros
|
||||||
memset(device->packet, 0, sizeof(device->packet));
|
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) {
|
if (request->cdb[0] == SCSI_OP_REQUEST_SENSE && device->combined_sense) {
|
||||||
// we have a pending emulated sense - return it on REQUEST 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
|
bool
|
||||||
prep_atapi(ide_device_info *device)
|
prep_atapi(ide_device_info *device)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*/
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
//! DMA helper functions
|
||||||
Part of Open IDE bus manager
|
|
||||||
|
|
||||||
DMA helper functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ide_internal.h"
|
#include "ide_internal.h"
|
||||||
|
|
||||||
@@ -65,10 +64,9 @@ configure_dma(ide_device_info *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** abort DMA transmission
|
/*! Abort DMA transmission
|
||||||
* must be called _before_ start_dma_wait
|
must be called _before_ start_dma_wait
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
abort_dma(ide_device_info *device, ide_qrequest *qrequest)
|
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
|
/*! Prepare DMA transmission
|
||||||
* on return, DMA engine waits for device to transmit data
|
on return, DMA engine waits for device to transmit data
|
||||||
* warning: doesn't set sense data on error
|
warning: doesn't set sense data on error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
prepare_dma(ide_device_info *device, ide_qrequest *qrequest)
|
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;
|
status_t res;
|
||||||
|
|
||||||
res = bus->controller->prepare_dma(bus->channel_cookie, request->sg_list,
|
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)
|
if (res != B_OK)
|
||||||
return false;
|
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
|
void
|
||||||
start_dma_wait(ide_device_info *device, ide_qrequest *qrequest)
|
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
|
void
|
||||||
start_dma_wait_no_lock(ide_device_info *device, ide_qrequest *qrequest)
|
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
|
bool
|
||||||
finish_dma(ide_device_info *device)
|
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.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//! General SCSI emulation routines
|
||||||
General SCSI emulation routines
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "ide_internal.h"
|
#include "ide_internal.h"
|
||||||
@@ -18,15 +16,14 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
/** Emulate REQUEST SENSE */
|
/*! Emulate REQUEST SENSE */
|
||||||
|
|
||||||
void
|
void
|
||||||
ide_request_sense(ide_device_info *device, ide_qrequest *qrequest)
|
ide_request_sense(ide_device_info *device, ide_qrequest *qrequest)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *request = qrequest->request;
|
||||||
scsi_cmd_request_sense *cmd = (scsi_cmd_request_sense *)request->cdb;
|
scsi_cmd_request_sense *cmd = (scsi_cmd_request_sense *)request->cdb;
|
||||||
scsi_sense sense;
|
scsi_sense sense;
|
||||||
uint32 transfer_size;
|
uint32 transferSize;
|
||||||
|
|
||||||
// cannot use finish_checksense here, as data is not copied into autosense buffer
|
// 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
|
// 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
|
else
|
||||||
memset(&sense, 0, sizeof(sense));
|
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
|
// reset sense information on read
|
||||||
device->combined_sense = 0;
|
device->combined_sense = 0;
|
||||||
|
|
||||||
transfer_size = min(sizeof(sense), cmd->alloc_length);
|
transferSize = min(sizeof(sense), cmd->allocation_length);
|
||||||
transfer_size = min(transfer_size, request->data_len);
|
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
|
// normally, all flags are set to "success", but for Request Sense
|
||||||
// this would have overwritten the sense we want to read
|
// 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
|
/*! Copy data between request data and buffer
|
||||||
* request - request to copy data from/to
|
request - request to copy data from/to
|
||||||
* offset - offset of data in request
|
offset - offset of data in request
|
||||||
* allocation_length- limit of request's data buffer according to CDB
|
allocation_length- limit of request's data buffer according to CDB
|
||||||
* buffer - data to copy data from/to
|
buffer - data to copy data from/to
|
||||||
* size - number of bytes to copy
|
size - number of bytes to copy
|
||||||
* to_buffer - true: copy from request to buffer
|
to_buffer - true: copy from request to buffer
|
||||||
* false: copy from buffer to request
|
false: copy from buffer to request
|
||||||
* return: true, if data of request was large enough
|
return: true, if data of request was large enough
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length,
|
copy_sg_data(scsi_ccb *request, uint offset, uint allocationLength,
|
||||||
void *buffer, int size, bool to_buffer)
|
void *buffer, int size, bool toBuffer)
|
||||||
{
|
{
|
||||||
const physical_entry *sg_list = request->sg_list;
|
const physical_entry *sgList = request->sg_list;
|
||||||
int sg_cnt = request->sg_cnt;
|
int sgCount = request->sg_count;
|
||||||
int req_size;
|
int requestSize;
|
||||||
|
|
||||||
SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_cnt=%d, %s buffer",
|
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
|
// skip unused S/G entries
|
||||||
while (sg_cnt > 0 && offset >= sg_list->size) {
|
while (sgCount > 0 && offset >= sgList->size) {
|
||||||
offset -= sg_list->size;
|
offset -= sgList->size;
|
||||||
++sg_list;
|
++sgList;
|
||||||
--sg_cnt;
|
--sgCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sg_cnt == 0)
|
if (sgCount == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// remaining bytes we are allowed to copy from/to request
|
// 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
|
// 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;
|
addr_t virtualAddress;
|
||||||
size_t bytes;
|
size_t bytes;
|
||||||
|
|
||||||
bytes = min(size, req_size);
|
bytes = min(size, requestSize);
|
||||||
bytes = min(bytes, sg_list->size);
|
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)
|
PHYSICAL_PAGE_CAN_WAIT) != B_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SHOW_FLOW(4, "buffer=%p, virt_addr=%p, bytes=%d, to_buffer=%d",
|
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);
|
memcpy(buffer, (void *)(virtualAddress + offset), bytes);
|
||||||
else
|
else
|
||||||
memcpy((void *)(virtualAddress + offset), buffer, bytes);
|
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.
|
* Copyright 2002-2004, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -48,26 +48,24 @@
|
|||||||
#define ERR_TOO_BIG (B_ERRORS_END + 1)
|
#define ERR_TOO_BIG (B_ERRORS_END + 1)
|
||||||
|
|
||||||
|
|
||||||
/** Prepare PIO transfer */
|
/*! Prepare PIO transfer */
|
||||||
|
|
||||||
void
|
void
|
||||||
prep_PIO_transfer(ide_device_info *device, ide_qrequest *qrequest)
|
prep_PIO_transfer(ide_device_info *device, ide_qrequest *qrequest)
|
||||||
{
|
{
|
||||||
SHOW_FLOW0(4, "");
|
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_elem = qrequest->request->sg_list;
|
||||||
device->cur_sg_ofs = 0;
|
device->cur_sg_ofs = 0;
|
||||||
device->has_odd_byte = false;
|
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
|
static inline status_t
|
||||||
transfer_PIO_virtcont(ide_device_info *device, uint8 *virtualAddress, int length,
|
transfer_PIO_virtcont(ide_device_info *device, uint8 *virtualAddress,
|
||||||
bool write, int *transferred)
|
int length, bool write, int *transferred)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
ide_controller_interface *controller = bus->controller;
|
ide_controller_interface *controller = bus->controller;
|
||||||
@@ -89,7 +87,8 @@ transfer_PIO_virtcont(ide_device_info *device, uint8 *virtualAddress, int length
|
|||||||
*transferred += 2;
|
*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
|
// take care if chunk size was odd, which means that 1 byte remains
|
||||||
virtualAddress += length & ~1;
|
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);
|
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;
|
// take care of odd chunk size;
|
||||||
// in this case we read 1 byte to few!
|
// 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
|
static inline status_t
|
||||||
transfer_PIO_physcont(ide_device_info *device, addr_t physicalAddress,
|
transfer_PIO_physcont(ide_device_info *device, addr_t physicalAddress,
|
||||||
int length, bool write, int *transferred)
|
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
|
static inline int
|
||||||
transfer_PIO_block(ide_device_info *device, int length, bool write, int *transferred)
|
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
|
static void
|
||||||
write_discard_PIO(ide_device_info *device, int length)
|
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
|
static void
|
||||||
read_discard_PIO(ide_device_info *device, int length)
|
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
|
/*! write PIO data
|
||||||
* return: there are 3 possible results
|
return: there are 3 possible results
|
||||||
* NO_ERROR - everything's nice and groovy
|
NO_ERROR - everything's nice and groovy
|
||||||
* ERR_TOO_BIG - data buffer was too short, remaining data got discarded
|
ERR_TOO_BIG - data buffer was too short, remaining data got discarded
|
||||||
* B_ERROR - something serious went wrong, sense data was set
|
B_ERROR - something serious went wrong, sense data was set
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
write_PIO_block(ide_qrequest *qrequest, int length)
|
write_PIO_block(ide_qrequest *qrequest, int length)
|
||||||
{
|
{
|
||||||
@@ -327,10 +323,9 @@ write_PIO_block(ide_qrequest *qrequest, int length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** read PIO data
|
/*! read PIO data
|
||||||
* return: see write_PIO_block
|
return: see write_PIO_block
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
read_PIO_block(ide_qrequest *qrequest, int length)
|
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.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* 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_ccb *request = qrequest->request;
|
||||||
scsi_cmd_mode_sense_10 *cmd = (scsi_cmd_mode_sense_10 *)request->cdb;
|
scsi_cmd_mode_sense_10 *cmd = (scsi_cmd_mode_sense_10 *)request->cdb;
|
||||||
scsi_mode_param_header_10 param_header;
|
scsi_mode_param_header_10 param_header;
|
||||||
scsi_modepage_contr contr;
|
scsi_modepage_control control;
|
||||||
scsi_mode_param_block_desc block_desc;
|
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_mode_param_block_desc)
|
||||||
+ sizeof(scsi_modepage_contr);
|
+ sizeof(scsi_modepage_control);
|
||||||
scsi_mode_param_dev_spec_da devspec = {
|
scsi_mode_param_dev_spec_da devspec = {
|
||||||
res0_0 : 0,
|
_res0_0 : 0,
|
||||||
DPOFUA : 0,
|
dpo_fua : 0,
|
||||||
res0_6 : 0,
|
_res0_6 : 0,
|
||||||
WP : 0
|
write_protected : 0
|
||||||
};
|
};
|
||||||
uint32 allocation_length;
|
uint32 allocationLength;
|
||||||
|
|
||||||
SHOW_FLOW0(1, "Hi!");
|
SHOW_FLOW0(1, "Hi!");
|
||||||
|
|
||||||
allocation_length = ((int16)cmd->high_allocation_length << 8)
|
allocationLength = B_BENDIAN_TO_HOST_INT16(cmd->allocation_length);
|
||||||
| cmd->low_allocation_length;
|
|
||||||
|
|
||||||
// we answer control page requests and "all pages" requests
|
// we answer control page requests and "all pages" requests
|
||||||
// (as the latter are the same as the first)
|
// (as the latter are the same as the first)
|
||||||
if ((cmd->page_code != SCSI_MODEPAGE_CONTROL && cmd->page_code != SCSI_MODEPAGE_ALL)
|
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);
|
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//param_header = (scsi_mode_param_header_10 *)request->data;
|
//param_header = (scsi_mode_param_header_10 *)request->data;
|
||||||
param_header.low_mode_data_len = total_length - 1;
|
param_header.mode_data_length = B_HOST_TO_BENDIAN_INT16(totalLength - 1);
|
||||||
param_header.high_mode_data_len = 0;
|
|
||||||
param_header.medium_type = 0; // XXX standard is a bit vague here
|
param_header.medium_type = 0; // XXX standard is a bit vague here
|
||||||
param_header.dev_spec_parameter = *(uint8 *)&devspec;
|
param_header.dev_spec_parameter = *(uint8 *)&devspec;
|
||||||
param_header.low_block_desc_len = sizeof(scsi_mode_param_block_desc);
|
param_header.block_desc_length
|
||||||
param_header.high_block_desc_len = 0;
|
= 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
|
/*block_desc = (scsi_mode_param_block_desc *)(request->data
|
||||||
+ sizeof(*param_header));*/
|
+ 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.med_blocklen = 512 >> 8;
|
||||||
block_desc.low_blocklen = 512 & 0xff;
|
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);
|
&block_desc, sizeof(block_desc), false);
|
||||||
|
|
||||||
/*contr = (scsi_modepage_contr *)(request->data
|
/*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)
|
+ ((uint16)param_header->high_block_desc_len << 8)
|
||||||
+ param_header->low_block_desc_len);*/
|
+ param_header->low_block_desc_len);*/
|
||||||
|
|
||||||
memset(&contr, 0, sizeof(contr));
|
memset(&control, 0, sizeof(control));
|
||||||
contr.RLEC = false;
|
control.RLEC = false;
|
||||||
contr.DQue = !device->CQ_enabled;
|
control.DQue = !device->CQ_enabled;
|
||||||
contr.QErr = false;
|
control.QErr = false;
|
||||||
// when a command fails we requeue all
|
// when a command fails we requeue all
|
||||||
// lost commands automagically
|
// lost commands automagically
|
||||||
contr.QAM = SCSI_QAM_UNRESTRICTED;
|
control.QAM = SCSI_QAM_UNRESTRICTED;
|
||||||
|
|
||||||
copy_sg_data(request, sizeof(param_header)
|
copy_sg_data(request, sizeof(param_header)
|
||||||
+ ((uint16)param_header.high_block_desc_len << 8)
|
+ B_BENDIAN_TO_HOST_INT16(param_header.block_desc_length),
|
||||||
+ param_header.low_block_desc_len,
|
allocationLength, &control, sizeof(control), false);
|
||||||
allocation_length, &contr, sizeof(contr), false);
|
|
||||||
|
|
||||||
// the number of bytes that were transferred to buffer is
|
// the number of bytes that were transferred to buffer is
|
||||||
// restricted by allocation length and by request data buffer size
|
// restricted by allocation length and by request data buffer size
|
||||||
total_length = min(total_length, allocation_length);
|
totalLength = min(totalLength, allocationLength);
|
||||||
total_length = min(total_length, request->data_len);
|
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
|
static bool
|
||||||
ata_mode_select_control_page(ide_device_info *device, ide_qrequest *qrequest,
|
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)) {
|
if (page->header.page_length != sizeof(*page) - sizeof(page->header)) {
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_PARAM_LIST_LENGTH_ERR);
|
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
|
static void
|
||||||
ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
|
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_cmd_mode_select_10 *cmd = (scsi_cmd_mode_select_10 *)request->cdb;
|
||||||
scsi_mode_param_header_10 param_header;
|
scsi_mode_param_header_10 param_header;
|
||||||
scsi_modepage_header page_header;
|
scsi_modepage_header page_header;
|
||||||
uint32 total_length;
|
uint32 totalLength;
|
||||||
uint32 modepage_offset;
|
uint32 modepageOffset;
|
||||||
char modepage_buffer[64]; // !!! enlarge this to support longer mode pages
|
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);
|
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
total_length = min(request->data_len,
|
totalLength = min(request->data_length,
|
||||||
((uint16)cmd->high_param_list_length << 8) | (uint32)cmd->low_param_list_length);
|
B_BENDIAN_TO_HOST_INT16(cmd->param_list_length));
|
||||||
|
|
||||||
// first, retrieve page header to get size of different chunks
|
// first, retrieve page header to get size of different chunks
|
||||||
//param_header = (scsi_mode_param_header_10 *)request->data;
|
//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;
|
goto err;
|
||||||
|
|
||||||
total_length = min(total_length, (((uint16)param_header.high_mode_data_len << 8)
|
totalLength = min(totalLength,
|
||||||
| param_header.low_mode_data_len) + 1UL);
|
B_BENDIAN_TO_HOST_INT16(param_header.mode_data_length) + 1UL);
|
||||||
|
|
||||||
// this is the start of the first mode page;
|
// this is the start of the first mode page;
|
||||||
// we ignore the block descriptor silently
|
// we ignore the block descriptor silently
|
||||||
modepage_offset = sizeof(param_header) + (((uint16)param_header.high_block_desc_len << 8)
|
modepageOffset = sizeof(param_header)
|
||||||
| param_header.low_block_desc_len);
|
+ B_BENDIAN_TO_HOST_INT16(param_header.block_desc_length);
|
||||||
|
|
||||||
// go through list of pages
|
// go through list of pages
|
||||||
while (modepage_offset < total_length) {
|
while (modepageOffset < totalLength) {
|
||||||
uint32 page_len;
|
uint32 pageLength;
|
||||||
|
|
||||||
// get header to know how long page is
|
// 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))
|
&page_header, sizeof(page_header), true))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
// get size of one page and copy it to buffer
|
// 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
|
// the buffer has a maximum size - this is really standard compliant but
|
||||||
// sufficient for our needs
|
// sufficient for our needs
|
||||||
if (page_len > sizeof(modepage_buffer))
|
if (pageLength > sizeof(modepage_buffer))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!copy_sg_data(request, modepage_offset, total_length,
|
if (!copy_sg_data(request, modepageOffset, totalLength,
|
||||||
&modepage_buffer, min(page_len, sizeof(modepage_buffer)), true))
|
&modepage_buffer, min(pageLength, sizeof(modepage_buffer)), true))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
// modify page;
|
// modify page;
|
||||||
@@ -177,22 +176,23 @@ ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
switch (page_header.page_code) {
|
switch (page_header.page_code) {
|
||||||
case SCSI_MODEPAGE_CONTROL:
|
case SCSI_MODEPAGE_CONTROL:
|
||||||
if (!ata_mode_select_control_page(device, qrequest,
|
if (!ata_mode_select_control_page(device, qrequest,
|
||||||
(scsi_modepage_contr *)modepage_buffer))
|
(scsi_modepage_control *)modepage_buffer))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
modepage_offset += page_len;
|
modepageOffset += pageLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modepage_offset != total_length)
|
if (modepageOffset != totalLength)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
request->data_resid = request->data_len - total_length;
|
request->data_resid = request->data_length - totalLength;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if we arrive here, data length was incorrect
|
// if we arrive here, data length was incorrect
|
||||||
@@ -201,8 +201,7 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** emulate TEST UNIT READY */
|
/*! Emulate TEST UNIT READY */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ata_test_unit_ready(ide_device_info *device, ide_qrequest *qrequest)
|
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
|
static bool
|
||||||
ata_flush_cache(ide_device_info *device, ide_qrequest *qrequest)
|
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 or eject medium
|
||||||
* load = true - load medium
|
load = true - load medium
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
ata_load_eject(ide_device_info *device, ide_qrequest *qrequest, bool load)
|
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
|
static bool
|
||||||
ata_prevent_allow(ide_device_info *device, bool prevent)
|
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
|
static void
|
||||||
ata_inquiry(ide_device_info *device, ide_qrequest *qrequest)
|
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 allocation_length = cmd->allocation_length;
|
||||||
uint32 transfer_size;
|
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);
|
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -316,27 +311,28 @@ ata_inquiry(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
data.device_qualifier = scsi_periph_qual_connected;
|
data.device_qualifier = scsi_periph_qual_connected;
|
||||||
|
|
||||||
data.device_type_modifier = 0;
|
data.device_type_modifier = 0;
|
||||||
data.RMB = false;
|
data.removable_medium = false;
|
||||||
|
|
||||||
data.ANSI_version = 2;
|
data.ansi_version = 2;
|
||||||
data.ECMA_version = 0;
|
data.ecma_version = 0;
|
||||||
data.ISO_version = 0;
|
data.iso_version = 0;
|
||||||
|
|
||||||
data.response_data_format = 2;
|
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.additional_length = sizeof(scsi_res_inquiry) - 4;
|
||||||
|
|
||||||
data.SftRe = false;
|
data.soft_reset = false;
|
||||||
data.CmdQue = device->queue_depth > 1;
|
data.cmd_queue = device->queue_depth > 1;
|
||||||
data.Linked = false;
|
data.linked = false;
|
||||||
|
|
||||||
// these values are free-style
|
// these values are free-style
|
||||||
data.Sync = false;
|
data.sync = false;
|
||||||
data.WBus16 = true;
|
data.write_bus16 = true;
|
||||||
data.WBus32 = false;
|
data.write_bus32 = false;
|
||||||
|
|
||||||
data.RelAdr = false;
|
data.relative_address = false;
|
||||||
|
|
||||||
// the following fields are *much* to small, sigh...
|
// the following fields are *much* to small, sigh...
|
||||||
memcpy(data.vendor_ident, device->infoblock.model_number,
|
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);
|
copy_sg_data(request, 0, allocation_length, &data, sizeof(data), false);
|
||||||
|
|
||||||
transfer_size = min(sizeof(data), allocation_length);
|
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
|
static void
|
||||||
read_capacity(ide_device_info *device, ide_qrequest *qrequest)
|
read_capacity(ide_device_info *device, ide_qrequest *qrequest)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *request = qrequest->request;
|
||||||
scsi_res_read_capacity data;
|
scsi_res_read_capacity data;
|
||||||
scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb;
|
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);
|
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_CDB_FIELD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo: 512 bytes fixed block size?
|
// TODO: 512 bytes fixed block size?
|
||||||
data.top_block_size = (512 >> 24) & 0xff;
|
data.block_size = B_HOST_TO_BENDIAN_INT32(512);
|
||||||
data.high_block_size = (512 >> 16) & 0xff;
|
|
||||||
data.mid_block_size = (512 >> 8) & 0xff;
|
|
||||||
data.low_block_size = 512 & 0xff;
|
|
||||||
|
|
||||||
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;
|
copy_sg_data(request, 0, request->data_length, &data, sizeof(data), false);
|
||||||
data.high_LBA = (last_block >> 16) & 0xff;
|
request->data_resid = max(request->data_length - sizeof(data), 0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** execute SCSI command */
|
/*! Execute SCSI command */
|
||||||
|
|
||||||
void
|
void
|
||||||
ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
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
|
// we must always flush cache if start = 0
|
||||||
ata_flush_cache(device, qrequest);
|
ata_flush_cache(device, qrequest);
|
||||||
|
|
||||||
if (cmd->LoEj)
|
if (cmd->load_eject)
|
||||||
ata_load_eject(device, qrequest, cmd->start);
|
ata_load_eject(device, qrequest, cmd->start);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -494,14 +480,14 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
// sadly, there are two possible read/write operation codes;
|
// sadly, there are two possible read/write operation codes;
|
||||||
// at least, the third one, read/write(12), is not valid for DAS
|
// at least, the third one, read/write(12), is not valid for DAS
|
||||||
case SCSI_OP_READ_6:
|
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;
|
scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)request->cdb;
|
||||||
uint32 pos;
|
uint32 pos;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
pos = ((uint32)cmd->high_LBA << 16) | ((uint32)cmd->mid_LBA << 8)
|
pos = ((uint32)cmd->high_lba << 16) | ((uint32)cmd->mid_lba << 8)
|
||||||
| (uint32)cmd->low_LBA;
|
| (uint32)cmd->low_lba;
|
||||||
|
|
||||||
length = cmd->length != 0 ? cmd->length : 256;
|
length = cmd->length != 0 ? cmd->length : 256;
|
||||||
|
|
||||||
SHOW_FLOW(3, "READ6/WRITE6 pos=%lx, length=%lx", pos, length);
|
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_READ_10:
|
||||||
case SCSI_OP_WRITE_10: {
|
case SCSI_OP_WRITE_10:
|
||||||
|
{
|
||||||
scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb;
|
scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb;
|
||||||
uint32 pos;
|
uint32 pos;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
pos = ((uint32)cmd->top_LBA << 24) | ((uint32)cmd->high_LBA << 16)
|
pos = B_BENDIAN_TO_HOST_INT32(cmd->lba);
|
||||||
| ((uint32)cmd->mid_LBA << 8) | (uint32)cmd->low_LBA;
|
length = B_BENDIAN_TO_HOST_INT16(cmd->length);
|
||||||
|
|
||||||
length = ((uint32)cmd->high_length << 8) | cmd->low_length;
|
|
||||||
|
|
||||||
if (length != 0) {
|
if (length != 0) {
|
||||||
ata_send_rw(device, qrequest, pos, length, cmd->opcode == SCSI_OP_WRITE_10);
|
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.
|
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*/
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
/*
|
*/
|
||||||
Part of Open SCSI bus manager
|
|
||||||
|
|
||||||
|
/*!
|
||||||
Device scanner.
|
Device scanner.
|
||||||
|
|
||||||
Scans SCSI busses for devices. Scanning is initiated by
|
Scans SCSI busses for devices. Scanning is initiated by
|
||||||
@@ -19,10 +19,12 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
// send TUR
|
/*! send TUR
|
||||||
// result: true, if device answered
|
result: true, if device answered
|
||||||
// false, if there is no device
|
false, if there is no device
|
||||||
static bool scsi_scan_send_tur( scsi_ccb *worker_req )
|
*/
|
||||||
|
static bool
|
||||||
|
scsi_scan_send_tur(scsi_ccb *worker_req)
|
||||||
{
|
{
|
||||||
scsi_cmd_tur *cmd = (scsi_cmd_tur *)worker_req->cdb;
|
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->sg_list = NULL;
|
||||||
worker_req->data = NULL;
|
worker_req->data = NULL;
|
||||||
worker_req->data_len = 0;
|
worker_req->data_length = 0;
|
||||||
worker_req->cdb_len = sizeof( *cmd );
|
worker_req->cdb_length = sizeof(*cmd);
|
||||||
worker_req->timeout = 0;
|
worker_req->timeout = 0;
|
||||||
worker_req->sort = -1;
|
worker_req->sort = -1;
|
||||||
worker_req->flags = 0;
|
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 );
|
SHOW_FLOW( 3, "status=%x", worker_req->subsys_status );
|
||||||
|
|
||||||
// as this command was only for syncing, we ignore almost all errors
|
// as this command was only for syncing, we ignore almost all errors
|
||||||
switch( worker_req->subsys_status ) {
|
switch (worker_req->subsys_status) {
|
||||||
case SCSI_SEL_TIMEOUT:
|
case SCSI_SEL_TIMEOUT:
|
||||||
// there seems to be no device around
|
// there seems to be no device around
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** get inquiry data
|
/*! get inquiry data
|
||||||
* returns true on success
|
returns true on success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
scsi_scan_get_inquiry(scsi_ccb *worker_req, scsi_res_inquiry *new_inquiry_data)
|
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_cmd_inquiry *cmd = (scsi_cmd_inquiry *)worker_req->cdb;
|
||||||
scsi_device_info *device = worker_req->device;
|
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
|
// in case not whole structure gets transferred, we set remaining data to zero
|
||||||
memset(new_inquiry_data, 0, sizeof(*new_inquiry_data));
|
memset(new_inquiry_data, 0, sizeof(*new_inquiry_data));
|
||||||
|
|
||||||
cmd->opcode = SCSI_OP_INQUIRY;
|
cmd->opcode = SCSI_OP_INQUIRY;
|
||||||
cmd->LUN = device->target_lun;
|
cmd->lun = device->target_lun;
|
||||||
cmd->EVPD = 0;
|
cmd->evpd = 0;
|
||||||
cmd->page_code = 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->sg_list = NULL;
|
||||||
worker_req->data = (uchar *)new_inquiry_data;
|
worker_req->data = (uchar *)new_inquiry_data;
|
||||||
worker_req->data_len = sizeof(*new_inquiry_data);
|
worker_req->data_length = sizeof(*new_inquiry_data);
|
||||||
worker_req->cdb_len = 6;
|
worker_req->cdb_length = 6;
|
||||||
worker_req->timeout = SCSI_STD_TIMEOUT;
|
worker_req->timeout = SCSI_STD_TIMEOUT;
|
||||||
worker_req->sort = -1;
|
worker_req->sort = -1;
|
||||||
worker_req->flags = SCSI_DIR_IN;
|
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"
|
SHOW_INFO(3, "device type: %d, qualifier: %d, removable: %d, ANSI version: %d, response data format: %d\n"
|
||||||
"vendor: %s, product: %s, rev: %s",
|
"vendor: %s, product: %s, rev: %s",
|
||||||
new_inquiry_data->device_type, new_inquiry_data->device_qualifier,
|
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,
|
new_inquiry_data->response_data_format,
|
||||||
vendor, product, rev);
|
vendor, product, rev);
|
||||||
|
|
||||||
@@ -114,19 +115,17 @@ scsi_scan_get_inquiry(scsi_ccb *worker_req, scsi_res_inquiry *new_inquiry_data)
|
|||||||
// bad luck
|
// bad luck
|
||||||
if (min(cmd->allocation_length, new_inquiry_data->additional_length + 4)
|
if (min(cmd->allocation_length, new_inquiry_data->additional_length + 4)
|
||||||
>= (int)offsetof(scsi_res_inquiry, version_descriptor[9])) {
|
>= (int)offsetof(scsi_res_inquiry, version_descriptor[9])) {
|
||||||
int i, prev_standard;
|
int i, previousStandard = -1;
|
||||||
|
|
||||||
prev_standard = -1;
|
|
||||||
|
|
||||||
for (i = 0; i < 8; ++i) {
|
for (i = 0; i < 8; ++i) {
|
||||||
int standard = (new_inquiry_data->version_descriptor[0].high << 8) |
|
int standard = B_BENDIAN_TO_HOST_INT16(
|
||||||
new_inquiry_data->version_descriptor[0].low;
|
new_inquiry_data->version_descriptor[i]);
|
||||||
|
|
||||||
// omit standards reported twice
|
// omit standards reported twice
|
||||||
if( standard != prev_standard && standard != 0 )
|
if (standard != previousStandard && standard != 0)
|
||||||
SHOW_INFO( 3, "standard: %04x", standard );
|
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;
|
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) );
|
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;
|
scsi_device_info *device;
|
||||||
bool found;
|
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);
|
res = scsi_force_get_device(bus, target_id, target_lun, &device);
|
||||||
if (res != B_OK)
|
if (res != B_OK)
|
||||||
goto err;
|
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);
|
worker_req = scsi_alloc_ccb(device);
|
||||||
|
|
||||||
if (worker_req == NULL) {
|
if (worker_req == NULL) {
|
||||||
// there is no out-of-mem code
|
// there is no out-of-mem code
|
||||||
res = B_NO_MEMORY;
|
res = B_NO_MEMORY;
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHOW_FLOW0( 3, "2" );
|
SHOW_FLOW0(3, "2");
|
||||||
|
|
||||||
worker_req->flags = SCSI_DIR_IN;
|
worker_req->flags = SCSI_DIR_IN;
|
||||||
|
|
||||||
@@ -245,44 +243,42 @@ scsi_scan_bus(scsi_bus_info *bus)
|
|||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0( 3, "" );
|
||||||
|
|
||||||
// get ID of initiator (i.e. controller)
|
// get ID of initiator (i.e. controller)
|
||||||
res = scsi_inquiry_path( bus, &inquiry );
|
res = scsi_inquiry_path(bus, &inquiry);
|
||||||
|
if (res != SCSI_REQ_CMP)
|
||||||
if( res != SCSI_REQ_CMP )
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
initiator_id = inquiry.initiator_id;
|
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)
|
// tell SIM to rescan bus (needed at least by IDE translator)
|
||||||
// as this function is optional for SIM, we ignore its result
|
// as this function is optional for SIM, we ignore its result
|
||||||
bus->interface->scan_bus( bus->sim_cookie );
|
bus->interface->scan_bus(bus->sim_cookie);
|
||||||
|
|
||||||
for( target_id = 0; target_id <= 1/*MAX_TARGET_ID*/; ++target_id ) {
|
for (target_id = 0; target_id <= 1/*MAX_TARGET_ID*/; ++target_id) {
|
||||||
int lun;
|
int lun;
|
||||||
|
|
||||||
SHOW_FLOW( 3, "target: %d", target_id );
|
SHOW_FLOW(3, "target: %d", target_id);
|
||||||
|
|
||||||
if( target_id == initiator_id )
|
if (target_id == initiator_id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// TODO: there are a lot of devices out there that go mad if you probe
|
// 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
|
// anything but LUN 0, so we should probably add a black-list
|
||||||
// or something
|
// or something
|
||||||
for( lun = 0; lun <= MAX_LUN_ID; ++lun ) {
|
for (lun = 0; lun <= MAX_LUN_ID; ++lun) {
|
||||||
status_t res;
|
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 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SHOW_FLOW0( 3, "done" );
|
SHOW_FLOW0(3, "done");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,9 +253,9 @@ scsi_create_autosense_request(scsi_device_info *device)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
request->data = buffer;
|
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_list = (physical_entry *)(buffer + SCSI_MAX_SENSE_SIZE);
|
||||||
request->sg_cnt = 1;
|
request->sg_count = 1;
|
||||||
|
|
||||||
get_memory_map(buffer, SCSI_MAX_SENSE_SIZE,
|
get_memory_map(buffer, SCSI_MAX_SENSE_SIZE,
|
||||||
(physical_entry *)request->sg_list, 1);
|
(physical_entry *)request->sg_list, 1);
|
||||||
@@ -268,12 +268,12 @@ scsi_create_autosense_request(scsi_device_info *device)
|
|||||||
SCSI_ORDERED_QTAG | SCSI_DMA_SAFE;
|
SCSI_ORDERED_QTAG | SCSI_DMA_SAFE;
|
||||||
|
|
||||||
cmd = (scsi_cmd_request_sense *)request->cdb;
|
cmd = (scsi_cmd_request_sense *)request->cdb;
|
||||||
request->cdb_len = sizeof(*cmd);
|
request->cdb_length = sizeof(*cmd);
|
||||||
|
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->opcode = SCSI_OP_REQUEST_SENSE;
|
cmd->opcode = SCSI_OP_REQUEST_SENSE;
|
||||||
cmd->LUN = device->target_lun;
|
cmd->lun = device->target_lun;
|
||||||
cmd->alloc_length = SCSI_MAX_SENSE_SIZE;
|
cmd->allocation_length = SCSI_MAX_SENSE_SIZE;
|
||||||
|
|
||||||
return B_OK;
|
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.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -32,14 +32,13 @@
|
|||||||
#include <string.h>
|
#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
|
static bool
|
||||||
is_sg_list_dma_safe(scsi_ccb *request)
|
is_sg_list_dma_safe(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
scsi_bus_info *bus = request->bus;
|
scsi_bus_info *bus = request->bus;
|
||||||
const physical_entry *sg_list = request->sg_list;
|
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 dma_boundary = bus->dma_params.dma_boundary;
|
||||||
uint32 alignment = bus->dma_params.alignment;
|
uint32 alignment = bus->dma_params.alignment;
|
||||||
uint32 max_sg_block_size = bus->dma_params.max_sg_block_size;
|
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;
|
dma_buffer *buffer = request->dma_buffer;
|
||||||
const physical_entry *sg_list = buffer->sg_list_orig;
|
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;
|
char *buffer_data = buffer->address;
|
||||||
|
|
||||||
SHOW_FLOW(1, "to_buffer=%d, %d bytes", to_buffer, (int)size);
|
SHOW_FLOW(1, "to_buffer=%d, %d bytes", to_buffer, (int)size);
|
||||||
|
|
||||||
// survive even if controller returned invalid data 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
|
// 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
|
// 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(
|
res = get_iovec_memory_map(
|
||||||
&vec, 1, 0, buffer->size,
|
&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 );
|
&mapped_len );
|
||||||
|
|
||||||
if( res != B_OK || mapped_len != buffer->size ) {
|
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) {
|
if (buffer->sg_orig > 0) {
|
||||||
delete_area(buffer->sg_orig);
|
delete_area(buffer->sg_orig);
|
||||||
buffer->sg_orig = 0;
|
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;
|
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",
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** helper: dump S/G table */
|
/*! dump S/G table */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dump_sg_table(const physical_entry *sg_list,
|
dump_sg_table(const physical_entry *sg_list,
|
||||||
uint32 sg_list_count)
|
uint32 sg_list_count)
|
||||||
@@ -364,17 +362,17 @@ static bool
|
|||||||
scsi_dma_buffer_compose_sg_orig(dma_buffer *buffer, scsi_ccb *request)
|
scsi_dma_buffer_compose_sg_orig(dma_buffer *buffer, scsi_ccb *request)
|
||||||
{
|
{
|
||||||
// enlarge buffer is required
|
// enlarge buffer is required
|
||||||
if (buffer->sg_cnt_max_orig < request->sg_cnt) {
|
if (buffer->sg_count_max_orig < request->sg_count) {
|
||||||
if (!scsi_alloc_dma_buffer_sg_orig(buffer, request->sg_cnt))
|
if (!scsi_alloc_dma_buffer_sg_orig(buffer, request->sg_count))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHOW_FLOW0(1, "copy S/G list");
|
SHOW_FLOW0(1, "copy S/G list");
|
||||||
|
|
||||||
memcpy(buffer->sg_list_orig, request->sg_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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +395,7 @@ scsi_get_dma_buffer(scsi_ccb *request)
|
|||||||
|
|
||||||
SHOW_FLOW0(1, "Buffer is not DMA safe" );
|
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
|
// only one buffer at a time
|
||||||
acquire_sem(device->dma_buffer_owner);
|
acquire_sem(device->dma_buffer_owner);
|
||||||
@@ -416,9 +414,9 @@ scsi_get_dma_buffer(scsi_ccb *request)
|
|||||||
request->dma_buffer = buffer;
|
request->dma_buffer = buffer;
|
||||||
|
|
||||||
// enlarge buffer if too small
|
// 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,
|
if (!scsi_alloc_dma_buffer(buffer, &device->bus->dma_params,
|
||||||
request->data_len))
|
request->data_length))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,20 +427,20 @@ scsi_get_dma_buffer(scsi_ccb *request)
|
|||||||
|
|
||||||
// copy data to buffer
|
// copy data to buffer
|
||||||
if ((request->flags & SCSI_DIR_MASK) == SCSI_DIR_OUT) {
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace data address, so noone notices that a buffer is used
|
// replace data address, so noone notices that a buffer is used
|
||||||
buffer->orig_data = request->data;
|
buffer->orig_data = request->data;
|
||||||
buffer->orig_sg_list = request->sg_list;
|
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->data = buffer->address;
|
||||||
request->sg_list = buffer->sg_list;
|
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");
|
SHOW_INFO0(3, "we can start now");
|
||||||
|
|
||||||
request->buffered = true;
|
request->buffered = true;
|
||||||
@@ -463,10 +461,9 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** copy data back and release DMA buffer;
|
/*! Copy data back and release DMA buffer;
|
||||||
* you must have called cleanup_tmp_sg before
|
you must have called cleanup_tmp_sg before
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
scsi_release_dma_buffer(scsi_ccb *request)
|
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
|
// copy data from buffer if required and if operation succeeded
|
||||||
if ((request->subsys_status & SCSI_SUBSYS_STATUS_MASK) == SCSI_REQ_CMP
|
if ((request->subsys_status & SCSI_SUBSYS_STATUS_MASK) == SCSI_REQ_CMP
|
||||||
&& (request->flags & SCSI_DIR_MASK) == SCSI_DIR_IN)
|
&& (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
|
// restore request
|
||||||
request->data = buffer->orig_data;
|
request->data = buffer->orig_data;
|
||||||
request->sg_list = buffer->orig_sg_list;
|
request->sg_list = buffer->orig_sg_list;
|
||||||
request->sg_cnt = buffer->orig_sg_cnt;
|
request->sg_count = buffer->orig_sg_count;
|
||||||
|
|
||||||
// free buffer
|
// free buffer
|
||||||
ACQUIRE_BEN(&device->dma_buffer_lock);
|
ACQUIRE_BEN(&device->dma_buffer_lock);
|
||||||
@@ -537,5 +534,5 @@ scsi_dma_buffer_init(dma_buffer *buffer)
|
|||||||
buffer->area = 0;
|
buffer->area = 0;
|
||||||
buffer->size = 0;
|
buffer->size = 0;
|
||||||
buffer->sg_orig = 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.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* 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);
|
static void restore_request_data(scsi_ccb *request);
|
||||||
|
|
||||||
|
|
||||||
/** free emulation buffer */
|
/*! Free emulation buffer */
|
||||||
|
|
||||||
void
|
void
|
||||||
scsi_free_emulation_buffer(scsi_device_info *device)
|
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
|
/*! Setup buffer used to emulate unsupported SCSI commands
|
||||||
* buffer_size must be power of two
|
buffer_size must be power of two
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
scsi_init_emulation_buffer(scsi_device_info *device, size_t buffer_size)
|
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 = (void *)(aligned_addr + buffer_size);
|
||||||
device->buffer_sg_list[0].address = (void *)aligned_phys;
|
device->buffer_sg_list[0].address = (void *)aligned_phys;
|
||||||
device->buffer_sg_list[0].size = buffer_size;
|
device->buffer_sg_list[0].size = buffer_size;
|
||||||
device->buffer_sg_cnt = 1;
|
device->buffer_sg_count = 1;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** some ATAPI devices don't like 6 byte read/write commands, so
|
/*!
|
||||||
* we translate them to their 10 byte partners;
|
Some ATAPI devices don't like 6 byte read/write commands, so
|
||||||
* USB devices usually don't like 10 bytes either
|
we translate them to their 10 byte counterparts;
|
||||||
*/
|
USB devices usually don't like 10 bytes either
|
||||||
|
*/
|
||||||
static bool
|
static bool
|
||||||
scsi_read_write_6(scsi_ccb *request)
|
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)");
|
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));
|
memset(cdb, 0, sizeof(*cdb));
|
||||||
|
|
||||||
cdb->opcode = cmd->opcode + (SCSI_OP_READ_10 - SCSI_OP_READ_6);
|
cdb->opcode = cmd->opcode + (SCSI_OP_READ_10 - SCSI_OP_READ_6);
|
||||||
cdb->LUN = cmd->LUN;
|
cdb->lun = cmd->lun;
|
||||||
cdb->low_LBA = cmd->low_LBA;
|
cdb->lba = B_HOST_TO_BENDIAN_INT32((uint32)cmd->low_lba
|
||||||
cdb->mid_LBA = cmd->mid_LBA;
|
| ((uint32)cmd->mid_lba << 8) | ((uint32)cmd->high_lba << 16));
|
||||||
cdb->high_LBA = cmd->high_LBA;
|
cdb->length = B_HOST_TO_BENDIAN_INT16((uint16)cmd->length);
|
||||||
cdb->low_length = cmd->length;
|
|
||||||
cdb->high_length = cmd->length == 0;
|
|
||||||
cdb->control = cmd->control;
|
cdb->control = cmd->control;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** all ATAPI devices don't like 6 byte MODE SENSE, so we translate
|
/*! All ATAPI devices don't like 6 byte MODE SENSE, so we translate
|
||||||
* that to 10 byte MODE SENSE
|
that to 10 byte MODE SENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
scsi_start_mode_sense_6(scsi_ccb *request)
|
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_6 *cmd = (scsi_cmd_mode_sense_6 *)request->orig_cdb;
|
||||||
scsi_cmd_mode_sense_10 *cdb = (scsi_cmd_mode_sense_10 *)request->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)");
|
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));
|
memset(cdb, 0, sizeof(*cdb));
|
||||||
|
|
||||||
cdb->opcode = SCSI_OP_MODE_SENSE_10;
|
cdb->opcode = SCSI_OP_MODE_SENSE_10;
|
||||||
cdb->DBD = cmd->DBD;
|
cdb->disable_block_desc = cmd->disable_block_desc;
|
||||||
cdb->LUN = cmd->LUN;
|
cdb->lun = cmd->lun;
|
||||||
cdb->page_code = cmd->page_code;
|
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);
|
- sizeof(scsi_cmd_mode_sense_6) + sizeof(scsi_cmd_mode_sense_10);
|
||||||
cdb->high_allocation_length = allocation_length >> 8;
|
cdb->allocation_length = B_HOST_TO_BENDIAN_INT16(allocationLength);
|
||||||
cdb->low_allocation_length = allocation_length & 0xff;
|
|
||||||
|
|
||||||
SHOW_FLOW(3, "allocation_length=%ld", allocation_length);
|
SHOW_FLOW(3, "allocation_length=%ld", allocationLength);
|
||||||
|
|
||||||
cdb->control = cmd->control;
|
cdb->control = cmd->control;
|
||||||
|
|
||||||
@@ -170,15 +164,14 @@ scsi_start_mode_sense_6(scsi_ccb *request)
|
|||||||
replace_request_data(request);
|
replace_request_data(request);
|
||||||
|
|
||||||
// restrict data buffer len to length specified in cdb
|
// restrict data buffer len to length specified in cdb
|
||||||
request->data_len = allocation_length;
|
request->data_length = allocationLength;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** all ATAPI devices don't like 6 byte MODE SELECT, so we translate
|
/*! All ATAPI devices don't like 6 byte MODE SELECT, so we translate
|
||||||
* that to 10 byte MODE SELECT
|
that to 10 byte MODE SELECT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
scsi_start_mode_select_6(scsi_ccb *request)
|
scsi_start_mode_select_6(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
@@ -204,16 +197,14 @@ scsi_start_mode_select_6(scsi_ccb *request)
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
// construct new cdb
|
// construct new cdb
|
||||||
request->cdb_len = sizeof(*cdb);
|
request->cdb_length = sizeof(*cdb);
|
||||||
memset(cdb, 0, sizeof(*cdb));
|
memset(cdb, 0, sizeof(*cdb));
|
||||||
|
|
||||||
cdb->opcode = SCSI_OP_MODE_SELECT_10;
|
cdb->opcode = SCSI_OP_MODE_SELECT_10;
|
||||||
cdb->SP = cmd->SP;
|
cdb->save_pages = cmd->save_pages;
|
||||||
cdb->PF = cmd->PF;
|
cdb->pf = cmd->pf;
|
||||||
cdb->LUN = cmd->LUN;
|
cdb->lun = cmd->lun;
|
||||||
|
cdb->param_list_length = B_HOST_TO_BENDIAN_INT16(param_list_length_10);
|
||||||
cdb->high_param_list_length = param_list_length_10 >> 8;
|
|
||||||
cdb->low_param_list_length = param_list_length_10 & 0xff;
|
|
||||||
|
|
||||||
SHOW_FLOW(3, "param_list_length=%ld", param_list_length_6);
|
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
|
// mode_data_len is reserved for MODE SELECT
|
||||||
header_10->medium_type = header_6.medium_type;
|
header_10->medium_type = header_6.medium_type;
|
||||||
header_10->dev_spec_parameter = header_6.dev_spec_parameter;
|
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
|
// 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))
|
param_list_length_10 - sizeof(*header_10), true))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
replace_request_data(request);
|
replace_request_data(request);
|
||||||
|
|
||||||
// restrict buffer size to the one specified in cdb
|
// 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;
|
return true;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@@ -249,10 +241,9 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** emulation procedure at start of command
|
/*! Emulation procedure at start of command
|
||||||
* returns false if command is to be finished without further execution
|
returns false if command is to be finished without further execution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
scsi_start_emulation(scsi_ccb *request)
|
scsi_start_emulation(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
@@ -261,7 +252,7 @@ scsi_start_emulation(scsi_ccb *request)
|
|||||||
SHOW_FLOW(3, "command=%x", request->cdb[0]);
|
SHOW_FLOW(3, "command=%x", request->cdb[0]);
|
||||||
|
|
||||||
memcpy(request->orig_cdb, request->cdb, SCSI_MAX_CDB_SIZE);
|
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]) {
|
switch (request->orig_cdb[0]) {
|
||||||
case SCSI_OP_READ_6:
|
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
|
static void
|
||||||
scsi_finish_mode_sense_10_6(scsi_ccb *request)
|
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;
|
scsi_mode_param_header_10 *header_10 = (scsi_mode_param_header_10 *)device->buffer;
|
||||||
int transfer_size_6, transfer_size_10;
|
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
|
// on error, do nothing
|
||||||
release_emulation_buffer(request);
|
release_emulation_buffer(request);
|
||||||
return;
|
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
|
// check how much data we got from device and thus will copy into
|
||||||
// request data
|
// 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
|
transfer_size_6 = transfer_size_10
|
||||||
- sizeof(scsi_mode_param_header_10 *) + sizeof(scsi_mode_param_header_6 *);
|
- 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
|
// convert total length
|
||||||
// (+1 is there because mode_data_len in 10 byte header ignores first
|
// (+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)
|
// 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)
|
- sizeof(scsi_mode_param_header_10) + sizeof(scsi_mode_param_header_6)
|
||||||
+ 1;
|
+ 1;
|
||||||
|
|
||||||
header_6.medium_type = header_10->medium_type;
|
header_6.medium_type = header_10->medium_type;
|
||||||
header_6.dev_spec_parameter = header_10->dev_spec_parameter;
|
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 adapted header
|
||||||
copy_sg_data(request, 0, transfer_size_6, &header_6, sizeof(header_6), false);
|
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,
|
copy_sg_data(request, sizeof(header_6), transfer_size_6,
|
||||||
header_10 + 1, transfer_size_10 - sizeof(*header_10), false);
|
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);
|
release_emulation_buffer(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** back-translate MODE SELECT 10 to MODE SELECT 6 */
|
/*! Back-translate MODE SELECT 10 to MODE SELECT 6 */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
scsi_finish_mode_select_10_6(scsi_ccb *request)
|
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
|
static void
|
||||||
scsi_finish_inquiry(scsi_ccb *request)
|
scsi_finish_inquiry(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
int transfer_size;
|
int transferSize;
|
||||||
scsi_res_inquiry res;
|
scsi_res_inquiry res;
|
||||||
|
|
||||||
SHOW_FLOW0(3, "fixing INQUIRY");
|
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;
|
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",
|
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;
|
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
|
void
|
||||||
scsi_finish_emulation(scsi_ccb *request)
|
scsi_finish_emulation(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
@@ -398,12 +387,11 @@ scsi_finish_emulation(scsi_ccb *request)
|
|||||||
|
|
||||||
// restore cdb
|
// restore cdb
|
||||||
memcpy(request->cdb, request->orig_cdb, SCSI_MAX_CDB_SIZE);
|
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
|
static void
|
||||||
set_sense(scsi_ccb *request, int sense_key, int sense_asc)
|
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
|
/*! Copy data between request data and buffer
|
||||||
* request - request to copy data from/to
|
request - request to copy data from/to
|
||||||
* offset - offset of data in request
|
offset - offset of data in request
|
||||||
* allocation_length- limit of request's data buffer according to CDB
|
allocation_length- limit of request's data buffer according to CDB
|
||||||
* buffer - data to copy data from/to
|
buffer - data to copy data from/to
|
||||||
* size - number of bytes to copy
|
size - number of bytes to copy
|
||||||
* to_buffer - true: copy from request to buffer
|
to_buffer - true: copy from request to buffer
|
||||||
* false: copy from buffer to request
|
false: copy from buffer to request
|
||||||
* return: true, if data of request was large enough
|
return: true, if data of request was large enough
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length,
|
copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length,
|
||||||
void *buffer, int size, bool to_buffer)
|
void *buffer, int size, bool to_buffer)
|
||||||
{
|
{
|
||||||
const physical_entry *sg_list = request->sg_list;
|
const physical_entry *sg_list = request->sg_list;
|
||||||
int sg_cnt = request->sg_cnt;
|
int sg_count = request->sg_count;
|
||||||
int req_size;
|
int req_size;
|
||||||
|
|
||||||
SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_cnt=%d, %s buffer",
|
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_cnt, to_buffer ? "to" : "from");
|
offset, allocation_length, size, sg_list, sg_count, to_buffer ? "to" : "from");
|
||||||
|
|
||||||
// skip unused S/G entries
|
// 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;
|
offset -= sg_list->size;
|
||||||
++sg_list;
|
++sg_list;
|
||||||
--sg_cnt;
|
--sg_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sg_cnt == 0)
|
if (sg_count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// remaining bytes we are allowed to copy from/to request
|
// 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
|
// 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;
|
size_t bytes;
|
||||||
addr_t virtualAddress;
|
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
|
static void
|
||||||
get_emulation_buffer(scsi_ccb *request)
|
get_emulation_buffer(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
scsi_device_info *device = request->device;
|
scsi_device_info *device = request->device;
|
||||||
|
|
||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
acquire_sem(device->buffer_sem);
|
acquire_sem(device->buffer_sem);
|
||||||
|
|
||||||
request->orig_sg_list = request->sg_list;
|
request->orig_sg_list = request->sg_list;
|
||||||
request->orig_sg_cnt = request->sg_cnt;
|
request->orig_sg_count = request->sg_count;
|
||||||
request->orig_data_len = request->data_len;
|
request->orig_data_length = request->data_length;
|
||||||
|
|
||||||
request->sg_list = device->buffer_sg_list;
|
request->sg_list = device->buffer_sg_list;
|
||||||
request->sg_cnt = device->buffer_sg_cnt;
|
request->sg_count = device->buffer_sg_count;
|
||||||
request->data_len = device->buffer_size;
|
request->data_length = device->buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** replace request data with emulation buffer, saving original pointer;
|
/*! Replace request data with emulation buffer, saving original pointer;
|
||||||
* you must have called get_emulation_buffer() first
|
you must have called get_emulation_buffer() first
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
replace_request_data(scsi_ccb *request)
|
replace_request_data(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
scsi_device_info *device = request->device;
|
scsi_device_info *device = request->device;
|
||||||
|
|
||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
request->orig_sg_list = request->sg_list;
|
request->orig_sg_list = request->sg_list;
|
||||||
request->orig_sg_cnt = request->sg_cnt;
|
request->orig_sg_count = request->sg_count;
|
||||||
request->orig_data_len = request->data_len;
|
request->orig_data_length = request->data_length;
|
||||||
|
|
||||||
request->sg_list = device->buffer_sg_list;
|
request->sg_list = device->buffer_sg_list;
|
||||||
request->sg_cnt = device->buffer_sg_cnt;
|
request->sg_count = device->buffer_sg_count;
|
||||||
request->data_len = device->buffer_size;
|
request->data_length = device->buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** release emulation buffer */
|
/*! Release emulation buffer */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
release_emulation_buffer(scsi_ccb *request)
|
release_emulation_buffer(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
release_sem(request->device->buffer_sem);
|
release_sem(request->device->buffer_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** restore original request data pointers */
|
/*! Restore original request data pointers */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
restore_request_data(scsi_ccb *request)
|
restore_request_data(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
request->sg_list = request->orig_sg_list;
|
request->sg_list = request->orig_sg_list;
|
||||||
request->sg_cnt = request->orig_sg_cnt;
|
request->sg_count = request->orig_sg_count;
|
||||||
request->data_len = request->orig_data_len;
|
request->data_length = request->orig_data_length;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
|
||||||
*/
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
/*
|
|
||||||
Part of Open SCSI bus manager
|
|
||||||
|
|
||||||
|
/*!
|
||||||
Creates temporary Scatter/Gather table if the peripheral
|
Creates temporary Scatter/Gather table if the peripheral
|
||||||
driver has provided a simple pointer only.
|
driver has provided a simple pointer only.
|
||||||
*/
|
*/
|
||||||
@@ -17,7 +16,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <iovec.h>
|
#include <iovec.h>
|
||||||
|
|
||||||
locked_pool_cookie temp_sg_pool;
|
|
||||||
|
static locked_pool_cookie temp_sg_pool;
|
||||||
|
|
||||||
|
|
||||||
static bool
|
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);
|
uint32 max_sg_blocks = min(bus->dma_params.max_sg_blocks, MAX_TEMP_SG_FRAGMENTS);
|
||||||
iovec vec = {
|
iovec vec = {
|
||||||
ccb->data,
|
ccb->data,
|
||||||
ccb->data_len
|
ccb->data_length
|
||||||
};
|
};
|
||||||
size_t num_entries;
|
size_t num_entries;
|
||||||
size_t mapped_len;
|
size_t mapped_len;
|
||||||
uint32 cur_idx;
|
uint32 cur_idx;
|
||||||
physical_entry *temp_sg = (physical_entry *)ccb->sg_list;
|
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);
|
&num_entries, &mapped_len);
|
||||||
|
|
||||||
if (res != B_OK) {
|
if (res != B_OK) {
|
||||||
@@ -45,10 +45,10 @@ fill_temp_sg(scsi_ccb *ccb)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapped_len != ccb->data_len)
|
if (mapped_len != ccb->data_length)
|
||||||
goto too_complex;
|
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:
|
// S/G list may not be controller-compatible:
|
||||||
// we have to split offending entries
|
// we have to split offending entries
|
||||||
SHOW_FLOW(3, "Checking violation of dma boundary 0x%x and entry size 0x%x",
|
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;
|
return true;
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ create_temp_sg(scsi_ccb *ccb)
|
|||||||
physical_entry *temp_sg;
|
physical_entry *temp_sg;
|
||||||
status_t res;
|
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);
|
ccb->sg_list = temp_sg = locked_pool->alloc(temp_sg_pool);
|
||||||
if (temp_sg == NULL) {
|
if (temp_sg == NULL) {
|
||||||
@@ -110,7 +110,7 @@ create_temp_sg(scsi_ccb *ccb)
|
|||||||
return false;
|
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));
|
| ((ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN ? B_READ_DEVICE : 0));
|
||||||
|
|
||||||
if (res != B_OK) {
|
if (res != B_OK) {
|
||||||
@@ -122,7 +122,7 @@ create_temp_sg(scsi_ccb *ccb)
|
|||||||
// this is the success path
|
// this is the success path
|
||||||
return true;
|
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));
|
| ((ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN ? B_READ_DEVICE : 0));
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@@ -147,11 +147,11 @@ cleanup_tmp_sg(scsi_ccb *ccb)
|
|||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
SHOW_FLOW( 3, "ccb=%p, data=%p, data_len=%d",
|
SHOW_FLOW(3, "ccb=%p, data=%p, data_length=%d",
|
||||||
ccb, ccb->data, (int)ccb->data_len );
|
ccb, ccb->data, (int)ccb->data_length);
|
||||||
|
|
||||||
res = unlock_memory( ccb->data, ccb->data_len, B_DMA_IO |
|
res = unlock_memory(ccb->data, ccb->data_length, B_DMA_IO
|
||||||
((ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN ? B_READ_DEVICE : 0));
|
| ((ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN ? B_READ_DEVICE : 0));
|
||||||
|
|
||||||
if (res != B_OK) {
|
if (res != B_OK) {
|
||||||
SHOW_FLOW0(3, "Cannot unlock previously locked memory!");
|
SHOW_FLOW0(3, "Cannot unlock previously locked memory!");
|
||||||
|
|||||||
@@ -2,15 +2,10 @@
|
|||||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef __SCSI_INTERNAL_H__
|
#ifndef _SCSI_INTERNAL_H
|
||||||
#define __SCSI_INTERNAL_H__
|
#define _SCSI_INTERNAL_H
|
||||||
|
|
||||||
/*
|
|
||||||
Part of Open SCSI bus manager
|
|
||||||
|
|
||||||
Internal structures/definitions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
//! Internal structures/definitions
|
||||||
|
|
||||||
|
|
||||||
#include <bus/SCSI.h>
|
#include <bus/SCSI.h>
|
||||||
@@ -146,18 +141,18 @@ typedef struct dma_buffer {
|
|||||||
uint32 size; // size of DMA buffer
|
uint32 size; // size of DMA buffer
|
||||||
area_id sg_list_area; // area of S/G list
|
area_id sg_list_area; // area of S/G list
|
||||||
physical_entry *sg_list; // address 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
|
bool inuse; // true, if in use
|
||||||
bigtime_t last_use; // timestamp of last usage
|
bigtime_t last_use; // timestamp of last usage
|
||||||
|
|
||||||
area_id sg_orig; // area of S/G list to original data
|
area_id sg_orig; // area of S/G list to original data
|
||||||
physical_entry *sg_list_orig; // 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_count_max_orig; // maximum size (in entries)
|
||||||
uint32 sg_cnt_orig; // current size (in entries)
|
uint32 sg_count_orig; // current size (in entries)
|
||||||
|
|
||||||
uchar *orig_data; // pointer to original data
|
uchar *orig_data; // pointer to original data
|
||||||
const physical_entry *orig_sg_list; // original S/G list
|
const physical_entry *orig_sg_list; // original S/G list
|
||||||
uint32 orig_sg_cnt; // size of original S/G list
|
uint32 orig_sg_count; // size of original S/G list
|
||||||
} dma_buffer;
|
} dma_buffer;
|
||||||
|
|
||||||
|
|
||||||
@@ -169,7 +164,7 @@ typedef struct scsi_device_info {
|
|||||||
bool manual_autosense : 1; // no autosense support
|
bool manual_autosense : 1; // no autosense support
|
||||||
bool is_atapi : 1; // ATAPI device - needs some commands emulated
|
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 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 sim_overflow; // 1, if SIM returned a request because of device queue overflow
|
||||||
int left_slots; // left command queuing slots for device
|
int left_slots; // left command queuing slots for device
|
||||||
@@ -209,7 +204,7 @@ typedef struct scsi_device_info {
|
|||||||
// buffer used for emulating SCSI commands
|
// buffer used for emulating SCSI commands
|
||||||
char *buffer;
|
char *buffer;
|
||||||
physical_entry *buffer_sg_list;
|
physical_entry *buffer_sg_list;
|
||||||
size_t buffer_sg_cnt;
|
size_t buffer_sg_count;
|
||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
area_id buffer_area;
|
area_id buffer_area;
|
||||||
sem_id buffer_sem;
|
sem_id buffer_sem;
|
||||||
@@ -253,89 +248,78 @@ extern struct pnp_devfs_driver_info scsi_bus_raw_module;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// bus_mgr.c
|
// busses.c
|
||||||
|
uchar scsi_inquiry_path(scsi_bus bus, scsi_path_inquiry *inquiry_data);
|
||||||
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
|
status_t scsi_init_ccb_alloc(scsi_bus_info *bus);
|
||||||
|
void scsi_uninit_ccb_alloc(scsi_bus_info *bus);
|
||||||
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 );
|
|
||||||
|
|
||||||
|
|
||||||
// device_mgr.c
|
// devices.c
|
||||||
|
status_t scsi_force_get_device(scsi_bus_info *bus,
|
||||||
status_t scsi_force_get_device( scsi_bus_info *bus,
|
uchar target_id, uchar target_lun, scsi_device_info **res_device);
|
||||||
uchar target_id, uchar target_lun, scsi_device_info **res_device );
|
void scsi_put_forced_device(scsi_device_info *device);
|
||||||
void scsi_put_forced_device( scsi_device_info *device );
|
status_t scsi_register_device(scsi_bus_info *bus, uchar target_id,
|
||||||
status_t scsi_register_device( scsi_bus_info *bus, uchar target_id,
|
uchar target_lun, scsi_res_inquiry *inquiry_data);
|
||||||
uchar target_lun, scsi_res_inquiry *inquiry_data );
|
|
||||||
|
|
||||||
|
|
||||||
// device_scan.c
|
// device_scan.c
|
||||||
|
status_t scsi_scan_bus(scsi_bus_info *bus);
|
||||||
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_lun( scsi_bus_info *bus, uchar target_id, uchar target_lun );
|
|
||||||
|
|
||||||
|
|
||||||
// dpc.c
|
// 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_schedule_dpc(scsi_bus_info *bus, scsi_dpc_info *dpc, /*int flags,*/
|
||||||
status_t scsi_free_dpc( scsi_dpc_info *dpc );
|
void (*func)( void *arg ), void *arg);
|
||||||
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 );
|
|
||||||
|
|
||||||
|
|
||||||
// scsi_io.c
|
// 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 );
|
bool scsi_check_exec_service(scsi_bus_info *bus);
|
||||||
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 );
|
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_requeue_request( scsi_ccb *request, bool bus_overflow );
|
void scsi_request_finished(scsi_ccb *request, uint num_requests);
|
||||||
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 );
|
int init_temp_sg(void);
|
||||||
void cleanup_tmp_sg( scsi_ccb *ccb );
|
void uninit_temp_sg(void);
|
||||||
|
|
||||||
int init_temp_sg( void );
|
|
||||||
void uninit_temp_sg( void );
|
|
||||||
|
|
||||||
|
|
||||||
// dma_buffer.c
|
// dma_buffer.c
|
||||||
|
void scsi_dma_buffer_daemon(void *dev, int counter);
|
||||||
void scsi_dma_buffer_daemon( void *dev, int counter );
|
void scsi_release_dma_buffer(scsi_ccb *request);
|
||||||
void scsi_release_dma_buffer( scsi_ccb *request );
|
bool scsi_get_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_free( dma_buffer *buffer );
|
void scsi_dma_buffer_init(dma_buffer *buffer);
|
||||||
void scsi_dma_buffer_init( dma_buffer *buffer );
|
|
||||||
|
|
||||||
|
|
||||||
// queuing.c
|
// queuing.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// emulation.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 );
|
#endif /* _SCSI_INTERNAL_H */
|
||||||
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
|
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
* Copyright 2002-2004, Thomas Kurschel. All rights reserved.
|
||||||
*/
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
//! Part of Open SCSI bus manager
|
||||||
Part of Open SCSI bus manager
|
|
||||||
|
|
||||||
Handling of SCSI I/O requests
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "scsi_internal.h"
|
#include "scsi_internal.h"
|
||||||
@@ -184,7 +182,7 @@ finish_autosense(scsi_device_info *device)
|
|||||||
|
|
||||||
// we got sense data -> copy it to sense buffer
|
// we got sense data -> copy it to sense buffer
|
||||||
sense_len = min(SCSI_MAX_SENSE_SIZE,
|
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);
|
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)
|
if (request->state != SCSI_STATE_FINISHED)
|
||||||
panic("Passed ccb to scsi_action that isn't ready (state = %d)\n", request->state);
|
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)",
|
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;
|
request->subsys_status = SCSI_REQ_INVALID;
|
||||||
goto err;
|
goto err;
|
||||||
@@ -417,7 +415,7 @@ scsi_async_io(scsi_ccb *request)
|
|||||||
|
|
||||||
FAST_LOGN(request->device->log, ev_scsi_async_io,
|
FAST_LOGN(request->device->log, ev_scsi_async_io,
|
||||||
func_group_len[request->cdb[0] >> 5] + 2,
|
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[0], request->cdb[1], request->cdb[2], request->cdb[3],
|
||||||
request->cdb[4], request->cdb[5], request->cdb[6], request->cdb[7],
|
request->cdb[4], request->cdb[5], request->cdb[6], request->cdb[7],
|
||||||
request->cdb[8], request->cdb[9], request->cdb[10], request->cdb[11],
|
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
|
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)",
|
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;
|
request->subsys_status = SCSI_DATA_RUN_ERR;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -443,7 +441,7 @@ scsi_async_io(scsi_ccb *request)
|
|||||||
|
|
||||||
// make data DMA safe
|
// make data DMA safe
|
||||||
// (S/G list must be created first to be able to verify DMA restrictions)
|
// (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;
|
request->buffered = true;
|
||||||
if (!scsi_get_dma_buffer(request)) {
|
if (!scsi_get_dma_buffer(request)) {
|
||||||
SHOW_ERROR0( 3, "cannot create DMA buffer for request - reduce data volume" );
|
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;
|
request->emulated = true;
|
||||||
|
|
||||||
if (!scsi_start_emulation(request)) {
|
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;
|
goto err2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -475,7 +473,7 @@ scsi_async_io(scsi_ccb *request)
|
|||||||
// abuse TUR to find proper spot in command packet for LUN
|
// abuse TUR to find proper spot in command packet for LUN
|
||||||
scsi_cmd_tur *cmd = (scsi_cmd_tur *)request->cdb;
|
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;
|
request->ordered = (request->flags & SCSI_ORDERED_QTAG) != 0;
|
||||||
@@ -513,7 +511,7 @@ scsi_sync_io(scsi_ccb *request)
|
|||||||
|
|
||||||
// create scatter-gather list if required
|
// create scatter-gather list if required
|
||||||
if ((request->flags & SCSI_DIR_MASK) != SCSI_DIR_NONE
|
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;
|
tmp_sg = true;
|
||||||
if (!create_temp_sg(request)) {
|
if (!create_temp_sg(request)) {
|
||||||
SHOW_ERROR0( 3, "data is too much fragmented - you should use s/g list" );
|
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//! Device management.
|
||||||
Part of Open SCSI Disk Driver
|
|
||||||
|
|
||||||
Device management.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "scsi_cd_int.h"
|
#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 }},
|
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: B_BLOCK_IO_MODULE_NAME }},
|
||||||
|
|
||||||
// tell block_io whether the device is removable
|
// 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
|
// tell which name we want to have in devfs
|
||||||
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
|
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
|
||||||
// impose own max block restriction
|
// 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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//! Main file.
|
||||||
Part of Open SCSI CD-ROM driver
|
|
||||||
|
|
||||||
Main file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "scsi_cd_int.h"
|
#include "scsi_cd_int.h"
|
||||||
#include <string.h>
|
|
||||||
#include <scsi.h>
|
#include <scsi.h>
|
||||||
#include <malloc.h>
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
extern block_device_interface cd_interface;
|
extern block_device_interface cd_interface;
|
||||||
|
|
||||||
@@ -116,7 +118,7 @@ get_toc(cd_device_info *device, scsi_toc *toc)
|
|||||||
scsi_ccb *ccb;
|
scsi_ccb *ccb;
|
||||||
status_t res;
|
status_t res;
|
||||||
scsi_cmd_read_toc *cmd;
|
scsi_cmd_read_toc *cmd;
|
||||||
size_t data_len;
|
size_t dataLength;
|
||||||
scsi_toc_general *short_response = (scsi_toc_general *)toc->toc_data;
|
scsi_toc_general *short_response = (scsi_toc_general *)toc->toc_data;
|
||||||
|
|
||||||
SHOW_FLOW0(0, "");
|
SHOW_FLOW0(0, "");
|
||||||
@@ -132,20 +134,19 @@ get_toc(cd_device_info *device, scsi_toc *toc)
|
|||||||
|
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->opcode = SCSI_OP_READ_TOC;
|
cmd->opcode = SCSI_OP_READ_TOC;
|
||||||
cmd->TIME = 1;
|
cmd->time = 1;
|
||||||
cmd->format = SCSI_TOC_FORMAT_TOC;
|
cmd->format = SCSI_TOC_FORMAT_TOC;
|
||||||
cmd->track = 1;
|
cmd->track = 1;
|
||||||
cmd->high_allocation_length = 0;
|
cmd->allocation_length = B_HOST_TO_BENDIAN_INT16(sizeof(scsi_toc_general));
|
||||||
cmd->low_allocation_length = sizeof(scsi_toc_general);
|
|
||||||
|
|
||||||
ccb->cdb_len = sizeof(*cmd);
|
ccb->cdb_length = sizeof(*cmd);
|
||||||
|
|
||||||
ccb->sort = -1;
|
ccb->sort = -1;
|
||||||
ccb->timeout = SCSI_CD_STD_TIMEOUT;
|
ccb->timeout = SCSI_CD_STD_TIMEOUT;
|
||||||
|
|
||||||
ccb->data = toc->toc_data;
|
ccb->data = toc->toc_data;
|
||||||
ccb->sg_list = NULL;
|
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);
|
res = scsi_periph->safe_exec(device->scsi_periph_device, ccb);
|
||||||
if (res != B_OK)
|
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
|
// but scsi_toc_toc has already one track, so we get
|
||||||
// last - first extra tracks; finally, we want the lead-out as
|
// last - first extra tracks; finally, we want the lead-out as
|
||||||
// well, so we add an extra track)
|
// 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);
|
* 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->allocation_length = B_HOST_TO_BENDIAN_INT16(dataLength);
|
||||||
cmd->low_allocation_length = data_len & 0xff;
|
|
||||||
|
|
||||||
res = scsi_periph->safe_exec(device->scsi_periph_device, ccb);
|
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));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
cmd.opcode = SCSI_OP_READ_SUB_CHANNEL;
|
cmd.opcode = SCSI_OP_READ_SUB_CHANNEL;
|
||||||
cmd.TIME = 1;
|
cmd.time = 1;
|
||||||
cmd.SUBQ = 1;
|
cmd.subq = 1;
|
||||||
cmd.parameter_list = scsi_sub_channel_parameter_list_cd_pos;
|
cmd.parameter_list = scsi_sub_channel_parameter_list_cd_pos;
|
||||||
cmd.track = 0;
|
cmd.track = 0;
|
||||||
cmd.high_allocation_length = sizeof(*position) >> 8;
|
cmd.allocation_length = B_HOST_TO_BENDIAN_INT16(sizeof(scsi_position));
|
||||||
cmd.low_allocation_length = sizeof(*position) & 0xff;
|
|
||||||
|
|
||||||
return scsi_periph->simple_exec(device->scsi_periph_device,
|
return scsi_periph->simple_exec(device->scsi_periph_device,
|
||||||
&cmd, sizeof(cmd), position, sizeof(*position), SCSI_DIR_IN);
|
&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));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
cmd.opcode = SCSI_OP_MODE_SENSE_6;
|
cmd.opcode = SCSI_OP_MODE_SENSE_6;
|
||||||
cmd.page_code = SCSI_MODEPAGE_AUDIO;
|
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);
|
cmd.allocation_length = sizeof(header);
|
||||||
|
|
||||||
memset(&header, -2, 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)
|
if (res != B_OK)
|
||||||
return res;
|
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??
|
// ToDo: why this??
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
// retrieve param header, block descriptor and actual codepage
|
// 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);
|
+ sizeof(scsi_modepage_audio);
|
||||||
|
|
||||||
buffer = malloc(len);
|
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",
|
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)->mode_data_length,
|
||||||
((scsi_mode_param_header_6 *)buffer)->block_desc_len);
|
((scsi_mode_param_header_6 *)buffer)->block_desc_length);
|
||||||
|
|
||||||
// find control page and retrieve values
|
// 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);
|
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));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
cmd.opcode = SCSI_OP_MODE_SELECT_6;
|
cmd.opcode = SCSI_OP_MODE_SELECT_6;
|
||||||
cmd.PF = 1;
|
cmd.pf = 1;
|
||||||
cmd.param_list_length = sizeof(header) + header.block_desc_len
|
cmd.param_list_length = sizeof(header) + header.block_desc_length
|
||||||
+ sizeof(*page);
|
+ sizeof(*page);
|
||||||
|
|
||||||
res = scsi_periph->simple_exec(device->scsi_periph_device,
|
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
|
static status_t
|
||||||
play_track_index(cd_device_info *device, scsi_play_track *buf)
|
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));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
|
||||||
cmd.opcode = SCSI_OP_SCAN;
|
cmd.opcode = SCSI_OP_SCAN;
|
||||||
cmd.Direct = buf->direction < 0;
|
cmd.direct = buf->direction < 0;
|
||||||
cmd.start.time = cd_pos->absolute_address.time;
|
cmd.start.time = cd_pos->absolute_address.time;
|
||||||
cmd.type = scsi_scan_msf;
|
cmd.type = scsi_scan_msf;
|
||||||
|
|
||||||
@@ -501,33 +500,28 @@ read_cd(cd_device_info *device, scsi_read_cd *read_cd)
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
cmd = (scsi_cmd_read_cd *)ccb->cdb;
|
cmd = (scsi_cmd_read_cd *)ccb->cdb;
|
||||||
memset( cmd, 0, sizeof( *cmd ));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->opcode = SCSI_OP_READ_CD;
|
cmd->opcode = SCSI_OP_READ_CD;
|
||||||
cmd->sector_type = 1;
|
cmd->sector_type = 1;
|
||||||
|
|
||||||
// skip first two seconds, they are lead-in
|
// skip first two seconds, they are lead-in
|
||||||
lba = (read_cd->start_m * 60 + read_cd->start_s) * 75 + read_cd->start_f
|
lba = (read_cd->start_m * 60 + read_cd->start_s) * 75 + read_cd->start_f
|
||||||
- 2 * 75;
|
- 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;
|
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->high_length = (length >> 16) & 0xff;
|
||||||
cmd->mid_length = (length >> 8) & 0xff;
|
cmd->mid_length = (length >> 8) & 0xff;
|
||||||
cmd->low_length = length & 0xff;
|
cmd->low_length = length & 0xff;
|
||||||
|
|
||||||
cmd->error_field = scsi_read_cd_error_none;
|
cmd->error_field = scsi_read_cd_error_none;
|
||||||
cmd->EDC_ECC = 0;
|
cmd->edc_ecc = 0;
|
||||||
cmd->user_data = 1;
|
cmd->user_data = 1;
|
||||||
cmd->header_code = scsi_read_cd_header_none;
|
cmd->header_code = scsi_read_cd_header_none;
|
||||||
cmd->SYNC = 0;
|
cmd->sync = 0;
|
||||||
cmd->sub_channel_selection = scsi_read_cd_sub_channel_none;
|
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->flags = SCSI_DIR_IN | SCSI_DIS_DISCONNECT;
|
||||||
ccb->sort = lba;
|
ccb->sort = lba;
|
||||||
@@ -536,7 +530,7 @@ read_cd(cd_device_info *device, scsi_read_cd *read_cd)
|
|||||||
|
|
||||||
ccb->data = read_cd->buffer;
|
ccb->data = read_cd->buffer;
|
||||||
ccb->sg_list = NULL;
|
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);
|
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//! Device management.
|
||||||
Part of Open SCSI Disk Driver
|
|
||||||
|
|
||||||
Device management.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "scsi_dsk_int.h"
|
#include "scsi_dsk_int.h"
|
||||||
|
|
||||||
#include <pnp_devfs.h>
|
#include <pnp_devfs.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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_MODULE, B_STRING_TYPE, { string: SCSI_DSK_MODULE_NAME }},
|
||||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: B_BLOCK_IO_MODULE_NAME }},
|
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: B_BLOCK_IO_MODULE_NAME }},
|
||||||
// tell block_io whether the device is removable
|
// 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
|
// tell which name we want to have in devfs
|
||||||
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
|
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
|
||||||
// impose own max block restriction
|
// impose own max block restriction
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
|
||||||
*/
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
//! Handling of block device (currently, only a capacity check is provided)
|
||||||
Part of Open SCSI Peripheral Driver
|
|
||||||
|
|
||||||
Handling of block device (currently, only a capacity check is provided)
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "scsi_periph_int.h"
|
#include "scsi_periph_int.h"
|
||||||
@@ -17,10 +15,10 @@
|
|||||||
status_t
|
status_t
|
||||||
periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request)
|
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;
|
scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb;
|
||||||
uint64 capacity;
|
uint64 capacity;
|
||||||
uint32 block_size;
|
uint32 blockSize;
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
SHOW_FLOW(3, "%p, %p", device, request);
|
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->flags = SCSI_DIR_IN;
|
||||||
|
|
||||||
request->data = (char *)&capacity_res;
|
request->data = (char *)&capacityResult;
|
||||||
request->data_len = sizeof(capacity_res);
|
request->data_length = sizeof(capacityResult);
|
||||||
request->cdb_len = sizeof(scsi_cmd_read_capacity);
|
request->cdb_length = sizeof(scsi_cmd_read_capacity);
|
||||||
request->timeout = device->std_timeout;
|
request->timeout = device->std_timeout;
|
||||||
request->sort = -1;
|
request->sort = -1;
|
||||||
request->sg_list = NULL;
|
request->sg_list = NULL;
|
||||||
@@ -56,28 +54,22 @@ periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request)
|
|||||||
ACQUIRE_BEN(&device->mutex);
|
ACQUIRE_BEN(&device->mutex);
|
||||||
|
|
||||||
if (res == B_OK && request->data_resid == 0) {
|
if (res == B_OK && request->data_resid == 0) {
|
||||||
capacity = (capacity_res.top_LBA << 24)
|
capacity = B_BENDIAN_TO_HOST_INT32(capacityResult.lba);
|
||||||
| (capacity_res.high_LBA << 16)
|
|
||||||
| (capacity_res.mid_LBA << 8)
|
|
||||||
| capacity_res.low_LBA;
|
|
||||||
|
|
||||||
// the command returns the index of the _last_ block,
|
// the command returns the index of the _last_ block,
|
||||||
// i.e. the size is one larger
|
// i.e. the size is one larger
|
||||||
++capacity;
|
++capacity;
|
||||||
|
|
||||||
block_size = (capacity_res.top_block_size << 24)
|
blockSize = B_BENDIAN_TO_HOST_INT32(capacityResult.block_size);
|
||||||
| (capacity_res.high_block_size << 16)
|
|
||||||
| (capacity_res.mid_block_size << 8)
|
|
||||||
| capacity_res.low_block_size;
|
|
||||||
} else {
|
} else {
|
||||||
capacity = 0;
|
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,
|
device->callbacks->set_capacity(device->periph_device,
|
||||||
capacity, block_size);
|
capacity, blockSize);
|
||||||
|
|
||||||
/* device->byte2blk_shift = log2( device->block_size );
|
/* device->byte2blk_shift = log2( device->block_size );
|
||||||
if( device->byte2blk_shift < 0 ) {
|
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.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//! Everything doing the real input/output stuff.
|
||||||
Part of Open SCSI Disk Driver
|
|
||||||
Everything doing the real input/output stuff.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "scsi_periph_int.h"
|
#include "scsi_periph_int.h"
|
||||||
#include <scsi.h>
|
#include <scsi.h>
|
||||||
@@ -25,28 +23,29 @@ static int periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *v
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
periph_read(scsi_periph_handle_info *handle, const phys_vecs *vecs, off_t pos,
|
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,
|
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
|
status_t
|
||||||
periph_write(scsi_periph_handle_info *handle, const phys_vecs *vecs, off_t pos,
|
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,
|
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
|
static int
|
||||||
periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *vecs,
|
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,
|
off_t pos64, size_t num_blocks, uint32 block_size,
|
||||||
int preferred_ccb_size, bool write)
|
size_t *bytes_transferred, int preferred_ccb_size, bool write)
|
||||||
{
|
{
|
||||||
scsi_periph_device_info *device = handle->device;
|
scsi_periph_device_info *device = handle->device;
|
||||||
scsi_ccb *request;
|
scsi_ccb *request;
|
||||||
@@ -90,8 +89,8 @@ periph_read_write(scsi_periph_handle_info *handle, const phys_vecs *vecs,
|
|||||||
|
|
||||||
request->data = NULL;
|
request->data = NULL;
|
||||||
request->sg_list = vecs->vec;
|
request->sg_list = vecs->vec;
|
||||||
request->data_len = num_bytes;
|
request->data_length = num_bytes;
|
||||||
request->sg_cnt = vecs->num;
|
request->sg_count = vecs->num;
|
||||||
request->sort = pos;
|
request->sort = pos;
|
||||||
request->timeout = device->std_timeout;
|
request->timeout = device->std_timeout;
|
||||||
// see whether daemon instructed us to post an ordered command;
|
// 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));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->opcode = write ? SCSI_OP_WRITE_6 : SCSI_OP_READ_6;
|
cmd->opcode = write ? SCSI_OP_WRITE_6 : SCSI_OP_READ_6;
|
||||||
cmd->high_LBA = (pos >> 16) & 0x1f;
|
cmd->high_lba = (pos >> 16) & 0x1f;
|
||||||
cmd->mid_LBA = (pos >> 8) & 0xff;
|
cmd->mid_lba = (pos >> 8) & 0xff;
|
||||||
cmd->low_LBA = pos & 0xff;
|
cmd->low_lba = pos & 0xff;
|
||||||
cmd->length = num_blocks;
|
cmd->length = num_blocks;
|
||||||
|
|
||||||
request->cdb_len = sizeof(*cmd);
|
request->cdb_length = sizeof(*cmd);
|
||||||
} else {
|
} else {
|
||||||
scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb;
|
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));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->opcode = write ? SCSI_OP_WRITE_10 : SCSI_OP_READ_10;
|
cmd->opcode = write ? SCSI_OP_WRITE_10 : SCSI_OP_READ_10;
|
||||||
cmd->RelAdr = 0;
|
cmd->relative_address = 0;
|
||||||
cmd->FUA = 0;
|
cmd->force_unit_access = 0;
|
||||||
cmd->DPO = 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;
|
request->cdb_length = sizeof(*cmd);
|
||||||
cmd->high_LBA = (pos >> 16) & 0xff;
|
|
||||||
cmd->mid_LBA = (pos >> 8) & 0xff;
|
|
||||||
cmd->low_LBA = pos & 0xff;
|
|
||||||
|
|
||||||
cmd->high_length = (num_blocks >> 8) & 0xff;
|
|
||||||
cmd->low_length = num_blocks & 0xff;
|
|
||||||
|
|
||||||
request->cdb_len = sizeof(*cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// last chance to detect errors that occured during concurrent accesses
|
// 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->data = cmd->data;
|
||||||
request->sg_list = NULL;
|
request->sg_list = NULL;
|
||||||
request->data_len = cmd->data_length;
|
request->data_length = cmd->data_length;
|
||||||
request->sort = -1;
|
request->sort = -1;
|
||||||
request->timeout = cmd->timeout;
|
request->timeout = cmd->timeout;
|
||||||
|
|
||||||
memcpy(request->cdb, cmd->command, SCSI_MAX_CDB_SIZE);
|
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);
|
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//! Handling of removable media.
|
||||||
Part of Open SCSI Peripheral Driver
|
|
||||||
|
|
||||||
Handling of removable media.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "scsi_periph_int.h"
|
#include "scsi_periph_int.h"
|
||||||
@@ -25,7 +23,7 @@ periph_media_changed(scsi_periph_device_info *device, scsi_ccb *request)
|
|||||||
bigtime_t backup_timeout;
|
bigtime_t backup_timeout;
|
||||||
uchar *backup_data;
|
uchar *backup_data;
|
||||||
const physical_entry *backup_sg_list;
|
const physical_entry *backup_sg_list;
|
||||||
uint16 backup_sg_cnt;
|
uint16 backup_sg_count;
|
||||||
uint32 backup_data_len;
|
uint32 backup_data_len;
|
||||||
|
|
||||||
// if there is no hook, the driver doesn't handle removal devices
|
// 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)
|
// path)
|
||||||
backup_flags = request->flags;
|
backup_flags = request->flags;
|
||||||
memcpy(backup_cdb, request->cdb, SCSI_MAX_CDB_SIZE);
|
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_sort = request->sort;
|
||||||
backup_timeout = request->timeout;
|
backup_timeout = request->timeout;
|
||||||
backup_data = request->data;
|
backup_data = request->data;
|
||||||
backup_sg_list = request->sg_list;
|
backup_sg_list = request->sg_list;
|
||||||
backup_sg_cnt = request->sg_cnt;
|
backup_sg_count = request->sg_count;
|
||||||
backup_data_len = request->data_len;
|
backup_data_len = request->data_length;
|
||||||
|
|
||||||
if (device->callbacks->media_changed != NULL)
|
if (device->callbacks->media_changed != NULL)
|
||||||
device->callbacks->media_changed(device->periph_device, request);
|
device->callbacks->media_changed(device->periph_device, request);
|
||||||
|
|
||||||
request->flags = backup_flags;
|
request->flags = backup_flags;
|
||||||
memcpy(request->cdb, backup_cdb, SCSI_MAX_CDB_SIZE);
|
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->sort = backup_sort;
|
||||||
request->timeout = backup_timeout;
|
request->timeout = backup_timeout;
|
||||||
request->data = backup_data;
|
request->data = backup_data;
|
||||||
request->sg_list = backup_sg_list;
|
request->sg_list = backup_sg_list;
|
||||||
request->sg_cnt = backup_sg_cnt;
|
request->sg_count = backup_sg_count;
|
||||||
request->data_len = backup_data_len;
|
request->data_length = backup_data_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -94,7 +92,7 @@ send_tur(scsi_periph_device_info *device, scsi_ccb *request)
|
|||||||
|
|
||||||
request->data = NULL;
|
request->data = NULL;
|
||||||
request->sg_list = NULL;
|
request->sg_list = NULL;
|
||||||
request->data_len = 0;
|
request->data_length = 0;
|
||||||
request->timeout = device->std_timeout;
|
request->timeout = device->std_timeout;
|
||||||
request->sort = -1;
|
request->sort = -1;
|
||||||
request->sg_list = NULL;
|
request->sg_list = NULL;
|
||||||
@@ -102,7 +100,7 @@ send_tur(scsi_periph_device_info *device, scsi_ccb *request)
|
|||||||
memset(cmd, 0, sizeof(*cmd));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->opcode = SCSI_OP_TUR;
|
cmd->opcode = SCSI_OP_TUR;
|
||||||
|
|
||||||
request->cdb_len = sizeof(*cmd);
|
request->cdb_length = sizeof(*cmd);
|
||||||
|
|
||||||
device->scsi->sync_io(request);
|
device->scsi->sync_io(request);
|
||||||
|
|
||||||
@@ -194,14 +192,13 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** send START/STOP command to device
|
/*! Send START/STOP command to device
|
||||||
* start - true for start, false for stop
|
start - true for start, false for stop
|
||||||
* with_LoEj - if true, then lock drive on start and eject on stop
|
withLoadEject - if true, then lock drive on start and eject on stop
|
||||||
*/
|
*/
|
||||||
|
|
||||||
err_res
|
err_res
|
||||||
periph_send_start_stop(scsi_periph_device_info *device, scsi_ccb *request,
|
periph_send_start_stop(scsi_periph_device_info *device, scsi_ccb *request,
|
||||||
bool start, bool with_LoEj)
|
bool start, bool withLoadEject)
|
||||||
{
|
{
|
||||||
scsi_cmd_ssu *cmd = (scsi_cmd_ssu *)request->cdb;
|
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->data = NULL;
|
||||||
request->sg_list = NULL;
|
request->sg_list = NULL;
|
||||||
request->data_len = 0;
|
request->data_length = 0;
|
||||||
request->timeout = device->std_timeout;
|
request->timeout = device->std_timeout;
|
||||||
request->sort = -1;
|
request->sort = -1;
|
||||||
request->sg_list = NULL;
|
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;
|
cmd->opcode = SCSI_OP_START_STOP;
|
||||||
// we don't want to poll; we give a long timeout instead
|
// we don't want to poll; we give a long timeout instead
|
||||||
// (well - the default timeout _is_ large)
|
// (well - the default timeout _is_ large)
|
||||||
cmd->immed = 0;
|
cmd->immediately = 0;
|
||||||
cmd->start = start;
|
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);
|
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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
//! Main file.
|
||||||
Part of Open SCSI Peripheral Driver
|
|
||||||
|
|
||||||
Main file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "scsi_periph_int.h"
|
#include "scsi_periph_int.h"
|
||||||
|
|
||||||
@@ -20,8 +19,8 @@ device_manager_info *pnp;
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
periph_simple_exec(scsi_periph_device_info *device, void *cdb, uchar cdb_len,
|
periph_simple_exec(scsi_periph_device_info *device, void *cdb, uchar cdbLength,
|
||||||
void *data, size_t data_len, int ccb_flags)
|
void *data, size_t dataLength, int ccb_flags)
|
||||||
{
|
{
|
||||||
scsi_ccb *ccb;
|
scsi_ccb *ccb;
|
||||||
status_t res;
|
status_t res;
|
||||||
@@ -34,15 +33,15 @@ periph_simple_exec(scsi_periph_device_info *device, void *cdb, uchar cdb_len,
|
|||||||
|
|
||||||
ccb->flags = ccb_flags;
|
ccb->flags = ccb_flags;
|
||||||
|
|
||||||
memcpy(ccb->cdb, cdb, cdb_len);
|
memcpy(ccb->cdb, cdb, cdbLength);
|
||||||
ccb->cdb_len = cdb_len;
|
ccb->cdb_length = cdbLength;
|
||||||
|
|
||||||
ccb->sort = -1;
|
ccb->sort = -1;
|
||||||
ccb->timeout = device->std_timeout;
|
ccb->timeout = device->std_timeout;
|
||||||
|
|
||||||
ccb->data = data;
|
ccb->data = data;
|
||||||
ccb->sg_list = NULL;
|
ccb->sg_list = NULL;
|
||||||
ccb->data_len = data_len;
|
ccb->data_length = dataLength;
|
||||||
|
|
||||||
res = periph_safe_exec(device, ccb);
|
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
|
// ask generic peripheral layer what to do now
|
||||||
res = periph_check_error(device, request);
|
res = periph_check_error(device, request);
|
||||||
|
|
||||||
if (res.action == err_act_start) {
|
if (res.action == err_act_start) {
|
||||||
// backup request, as we need it temporarily for sending "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
|
// (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;
|
bigtime_t backup_timeout;
|
||||||
uchar *backup_data;
|
uchar *backup_data;
|
||||||
const physical_entry *backup_sg_list;
|
const physical_entry *backup_sg_list;
|
||||||
uint16 backup_sg_cnt;
|
uint16 backup_sg_count;
|
||||||
uint32 backup_data_len;
|
uint32 backup_data_len;
|
||||||
|
|
||||||
backup_flags = request->flags;
|
backup_flags = request->flags;
|
||||||
memcpy(backup_cdb, request->cdb, SCSI_MAX_CDB_SIZE);
|
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_sort = request->sort;
|
||||||
backup_timeout = request->timeout;
|
backup_timeout = request->timeout;
|
||||||
backup_data = request->data;
|
backup_data = request->data;
|
||||||
backup_sg_list = request->sg_list;
|
backup_sg_list = request->sg_list;
|
||||||
backup_sg_cnt = request->sg_cnt;
|
backup_sg_count = request->sg_count;
|
||||||
backup_data_len = request->data_len;
|
backup_data_len = request->data_length;
|
||||||
|
|
||||||
SHOW_INFO0( 2, "Sending start to init LUN" );
|
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;
|
request->flags = backup_flags;
|
||||||
memcpy(request->cdb, backup_cdb, SCSI_MAX_CDB_SIZE);
|
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->sort = backup_sort;
|
||||||
request->timeout = backup_timeout;
|
request->timeout = backup_timeout;
|
||||||
request->data = backup_data;
|
request->data = backup_data;
|
||||||
request->sg_list = backup_sg_list;
|
request->sg_list = backup_sg_list;
|
||||||
request->sg_cnt = backup_sg_cnt;
|
request->sg_count = backup_sg_count;
|
||||||
request->data_len = backup_data_len;
|
request->data_length = backup_data_len;
|
||||||
|
|
||||||
if (res.action == err_act_ok)
|
if (res.action == err_act_ok)
|
||||||
res.action = err_act_retry;
|
res.action = err_act_retry;
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Bruno Albuquerque, bga@bug-br.org.br
|
* Bruno Albuquerque, bga@bug-br.org.br
|
||||||
*
|
*
|
||||||
* Copyright 2004-2006 yellowTAB GMbH. This file is
|
* Copyright 2004-2006 yellowTAB GMbH. This file is
|
||||||
* based on work I did for ZETA while employed by
|
* based on work I did for ZETA while employed by
|
||||||
* yellowTAB and is used under permission.
|
* yellowTAB and is used under permission.
|
||||||
*
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include "scsi_periph_int.h"
|
#include "scsi_periph_int.h"
|
||||||
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
err_res
|
err_res
|
||||||
periph_synchronize_cache(scsi_periph_device_info *device, scsi_ccb *request)
|
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->data = NULL;
|
||||||
request->sg_list = NULL;
|
request->sg_list = NULL;
|
||||||
request->data_len = 0;
|
request->data_length = 0;
|
||||||
request->timeout = device->std_timeout;
|
request->timeout = device->std_timeout;
|
||||||
request->sort = -1;
|
request->sort = -1;
|
||||||
|
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
|
|
||||||
cmd->opcode = SCSI_OP_SYNCHRONIZE_CACHE;
|
cmd->opcode = SCSI_OP_SYNCHRONIZE_CACHE;
|
||||||
cmd->immed = 0;
|
cmd->immediately = 0;
|
||||||
|
|
||||||
// TODO(bga): Maybe we will actually want to set those one day...
|
// TODO: Maybe we will actually want to set this one day...
|
||||||
cmd->nblocks_high = 0;
|
cmd->block_count = 0;
|
||||||
cmd->nblocks_low = 0;
|
|
||||||
|
|
||||||
request->cdb_len = sizeof(*cmd);
|
request->cdb_length = sizeof(*cmd);
|
||||||
|
|
||||||
device->scsi->sync_io(request);
|
device->scsi->sync_io(request);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user