* Cleaned up SCSI headers a bit.

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


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21105 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-05-10 14:13:37 +00:00
parent 4cad5aba3b
commit 6be1e37d94
23 changed files with 993 additions and 1142 deletions
+15 -17
View File
@@ -1,11 +1,11 @@
/* /*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved. * Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved. * 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
+5 -5
View File
@@ -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 */
+21 -26
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved. * Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved. * 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)
{ {
+17 -24
View File
@@ -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)
{ {
+36 -40
View File
@@ -1,13 +1,11 @@
/* /*
* Copyright 2004-2006, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2004-2007, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved. * 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);
+24 -29
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved. * Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002-2004, Thomas Kurschel. All rights reserved. * 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)
{ {
+98 -113
View File
@@ -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, &param_header, sizeof(param_header), false); copy_sg_data(request, 0, allocationLength, &param_header,
sizeof(param_header), false);
/*block_desc = (scsi_mode_param_block_desc *)(request->data /*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, &param_header, sizeof(param_header), true)) if (!copy_sg_data(request, 0, totalLength, &param_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;
} }
+102 -119
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved. * 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
+16 -18
View File
@@ -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
+16 -24
View File
@@ -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 ) {
+26 -33
View File
@@ -1,14 +1,12 @@
/* /*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved. * Copyright 2004-2007, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved. * 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);