Calmed down SCSI bus manager a bit in case it got a non-DMA safe buffer

from block_io (which seem to happen frequently...).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13948 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-08-13 12:39:10 +00:00
parent b96ea69c37
commit 944eada15a
@@ -29,7 +29,8 @@
#include <string.h>
// check whether S/G list of request is supported DMA controller
/** check whether S/G list of request is supported DMA controller */
static bool
is_sg_list_dma_safe(scsi_ccb *request)
{
@@ -43,7 +44,7 @@ is_sg_list_dma_safe(scsi_ccb *request)
// not too many S/G list entries
if (sg_count > bus->dma_params.max_sg_blocks) {
SHOW_FLOW0( 0, "S/G-list too long" );
SHOW_FLOW0(1, "S/G-list too long");
return false;
}
@@ -101,7 +102,7 @@ scsi_copy_dma_buffer(scsi_ccb *request, uint32 size, bool to_buffer)
uint32 num_vecs = buffer->sg_cnt_orig;
char *buffer_data = buffer->address;
SHOW_FLOW(0, "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
size = min(size, request->data_len);
@@ -132,22 +133,25 @@ scsi_copy_dma_buffer(scsi_ccb *request, uint32 size, bool to_buffer)
}
// get log2
static int log2( uint32 x )
static int
log2(uint32 x)
{
int y;
for( y = 31; y >= 0; --y )
for (y = 31; y >= 0; --y) {
if (x == ((uint32)1 << y))
break;
}
return y;
}
static void scsi_free_dma_buffer( dma_buffer *buffer )
static void
scsi_free_dma_buffer(dma_buffer *buffer)
{
if (buffer->area > 0) {
SHOW_FLOW0( 0, "Destroying buffer" );
SHOW_FLOW0(1, "Destroying buffer");
delete_area(buffer->area);
buffer->area = 0;
@@ -180,17 +184,15 @@ scsi_alloc_dma_buffer(dma_buffer *buffer, dma_params *dma_params, uint32 size)
// calculate worst case number of S/G entries, i.e. if they are non-continuous;
// there is a controller limit and a limit by our own S/G manager to check
if( size / B_PAGE_SIZE > dma_params->max_sg_blocks ||
size / B_PAGE_SIZE > MAX_TEMP_SG_FRAGMENTS )
{
if (size / B_PAGE_SIZE > dma_params->max_sg_blocks
|| size / B_PAGE_SIZE > MAX_TEMP_SG_FRAGMENTS) {
uint32 boundary = dma_params->dma_boundary;
uchar *dma_buffer_address_unaligned;
// alright - a contiguous buffer is required to keep S/G table short
SHOW_INFO( 0, "need to setup contiguous DMA buffer of size %d",
SHOW_INFO(1, "need to setup contiguous DMA buffer of size %d",
(int)size);
// verify that we don't get problems with dma boundary
if (boundary != ~0UL) {
if (size > boundary + 1) {
@@ -294,7 +296,9 @@ scsi_alloc_dma_buffer(dma_buffer *buffer, dma_params *dma_params, uint32 size)
return true;
}
static void scsi_free_dma_buffer_sg_orig( dma_buffer *buffer )
static void
scsi_free_dma_buffer_sg_orig(dma_buffer *buffer)
{
if (buffer->sg_orig > 0) {
delete_area(buffer->sg_orig);
@@ -304,8 +308,10 @@ static void scsi_free_dma_buffer_sg_orig( dma_buffer *buffer )
}
// allocate S/G list to original data
static bool scsi_alloc_dma_buffer_sg_orig( dma_buffer *buffer, int size )
/** allocate S/G list to original data */
static bool
scsi_alloc_dma_buffer_sg_orig(dma_buffer *buffer, int size)
{
// free old list first
scsi_free_dma_buffer_sg_orig(buffer);
@@ -331,23 +337,27 @@ static bool scsi_alloc_dma_buffer_sg_orig( dma_buffer *buffer, int size )
}
// helper: dump S/G table
static void dump_sg_table( const physical_entry *sg_list,
/** helper: dump S/G table */
static void
dump_sg_table(const physical_entry *sg_list,
uint32 sg_list_count)
{
uint32 cur_idx;
SHOW_FLOW( 0, "count=%d", (int)sg_list_count );
SHOW_FLOW(1, "count=%d", (int)sg_list_count);
for (cur_idx = sg_list_count; cur_idx >= 1; --cur_idx, ++sg_list) {
SHOW_FLOW( 0, "addr=%x, size=%d", (int)sg_list->address,
SHOW_FLOW(1, "addr=%x, size=%d", (int)sg_list->address,
(int)sg_list->size);
}
}
// compose S/G list to original data of request
static bool scsi_dma_buffer_compose_sg_orig( dma_buffer *buffer, scsi_ccb *request )
/** compose S/G list to original data of request */
static bool
scsi_dma_buffer_compose_sg_orig(dma_buffer *buffer, scsi_ccb *request)
{
// enlarge buffer is required
if (buffer->sg_cnt_max_orig < request->sg_cnt) {
@@ -355,7 +365,7 @@ static bool scsi_dma_buffer_compose_sg_orig( dma_buffer *buffer, scsi_ccb *reque
return false;
}
SHOW_FLOW0( 0, "copy S/G list" );
SHOW_FLOW0(1, "copy S/G list");
memcpy(buffer->sg_list_orig, request->sg_list,
request->sg_cnt * sizeof(physical_entry));
@@ -365,9 +375,12 @@ static bool scsi_dma_buffer_compose_sg_orig( dma_buffer *buffer, scsi_ccb *reque
}
// init DMA buffer and copy data to it if required
// note: S/G list of request must already be setup
bool scsi_get_dma_buffer( scsi_ccb *request )
/** init DMA buffer and copy data to it if required
* note: S/G list of request must already be setup
*/
bool
scsi_get_dma_buffer(scsi_ccb *request)
{
scsi_device_info *device = request->device;
dma_buffer *buffer;
@@ -378,7 +391,7 @@ bool scsi_get_dma_buffer( scsi_ccb *request )
if( is_sg_list_dma_safe( request ))
return true;
SHOW_FLOW0( 0, "Buffer is not DMA safe" );
SHOW_FLOW0(1, "Buffer is not DMA safe" );
dump_sg_table(request->sg_list, request->sg_cnt);
@@ -402,10 +415,8 @@ bool scsi_get_dma_buffer( scsi_ccb *request )
if (buffer->size < request->data_len) {
if (!scsi_alloc_dma_buffer(buffer, &device->bus->dma_params,
request->data_len))
{
goto err;
}
}
// create S/G to original data (necessary for copying from-buffer on end
// of request, but also used during copying to-buffer in a second because
@@ -427,8 +438,7 @@ bool scsi_get_dma_buffer( scsi_ccb *request )
request->sg_list = buffer->sg_list;
request->sg_cnt = buffer->sg_cnt;
SHOW_INFO( 0, "bytes: %d", (int)request->data_len );
SHOW_INFO(1, "bytes: %d", (int)request->data_len);
SHOW_INFO0(3, "we can start now");
request->buffered = true;
@@ -449,20 +459,23 @@ err:
}
// copy data back and release DMA buffer;
// you must have called cleanup_tmp_sg before
void scsi_release_dma_buffer( scsi_ccb *request )
/** copy data back and release DMA buffer;
* you must have called cleanup_tmp_sg before
*/
void
scsi_release_dma_buffer(scsi_ccb *request)
{
scsi_device_info *device = request->device;
dma_buffer *buffer = request->dma_buffer;
SHOW_FLOW( 0, "Buffering finished, %x, %x",
SHOW_FLOW(1, "Buffering finished, %x, %x",
request->subsys_status & SCSI_SUBSYS_STATUS_MASK,
(int)(request->flags & SCSI_DIR_MASK));
// copy data from buffer if required and if operation succeeded
if( (request->subsys_status & SCSI_SUBSYS_STATUS_MASK) == SCSI_REQ_CMP &&
(request->flags & SCSI_DIR_MASK) == SCSI_DIR_IN )
if ((request->subsys_status & SCSI_SUBSYS_STATUS_MASK) == SCSI_REQ_CMP
&& (request->flags & SCSI_DIR_MASK) == SCSI_DIR_IN)
scsi_copy_dma_buffer(request, request->data_len - request->data_resid, false );
// restore request
@@ -484,8 +497,10 @@ void scsi_release_dma_buffer( scsi_ccb *request )
}
// dameon that deletes DMA buffer if not used for some time
void scsi_dma_buffer_daemon( void *dev, int counter )
/** dameon that deletes DMA buffer if not used for some time */
void
scsi_dma_buffer_daemon(void *dev, int counter)
{
scsi_device_info *device = dev;
dma_buffer *buffer;
@@ -494,9 +509,8 @@ void scsi_dma_buffer_daemon( void *dev, int counter )
buffer = &device->dma_buffer;
if( !buffer->inuse &&
buffer->last_use - system_time() > SCSI_DMA_BUFFER_CLEANUP_DELAY )
{
if (!buffer->inuse
&& buffer->last_use - system_time() > SCSI_DMA_BUFFER_CLEANUP_DELAY) {
scsi_free_dma_buffer(buffer);
scsi_free_dma_buffer_sg_orig(buffer);
}
@@ -504,13 +518,17 @@ void scsi_dma_buffer_daemon( void *dev, int counter )
RELEASE_BEN(&device->dma_buffer_lock);
}
void scsi_dma_buffer_free( dma_buffer *buffer )
void
scsi_dma_buffer_free(dma_buffer *buffer)
{
scsi_free_dma_buffer(buffer);
scsi_free_dma_buffer_sg_orig(buffer);
}
void scsi_dma_buffer_init( dma_buffer *buffer )
void
scsi_dma_buffer_init(dma_buffer *buffer)
{
buffer->area = 0;
buffer->size = 0;