[haiku-commits] r36988 - in haiku/trunk: headers/private/drivers src/add-ons/kernel/generic/scsi_periph

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 1 Jun 2010 15:37:55 +0200 (CEST)

Author: axeld
Date: 2010-06-01 15:37:55 +0200 (Tue, 01 Jun 2010)
New Revision: 36988
Changeset: http://dev.haiku-os.org/changeset/36988/haiku

Modified:
   haiku/trunk/headers/private/drivers/scsi_periph.h
   haiku/trunk/src/add-ons/kernel/generic/scsi_periph/io.cpp
   haiku/trunk/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp
   haiku/trunk/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h
Log:
* Added a read_write() function to the scsi_periph module.
* Internally, moved the contents of periph_io() into a static read_write()
  function, and use it from the new periph_read_write() as well.


Modified: haiku/trunk/headers/private/drivers/scsi_periph.h
===================================================================
--- haiku/trunk/headers/private/drivers/scsi_periph.h   2010-06-01 12:06:56 UTC 
(rev 36987)
+++ haiku/trunk/headers/private/drivers/scsi_periph.h   2010-06-01 13:37:55 UTC 
(rev 36988)
@@ -101,6 +101,9 @@
        status_t (*handle_free)(scsi_periph_handle handle);
 
        // *** default implementation for block devices ***
+       status_t (*read_write)(scsi_periph_device_info *device, scsi_ccb 
*request,
+               uint64 offset, size_t numBlocks, physical_entry* vecs, size_t 
vecCount,
+               bool isWrite, size_t* _bytesTransferred);
        status_t (*io)(scsi_periph_device device, io_operation *operation,
                size_t *_bytesTransferred);
 

Modified: haiku/trunk/src/add-ons/kernel/generic/scsi_periph/io.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/generic/scsi_periph/io.cpp   2010-06-01 
12:06:56 UTC (rev 36987)
+++ haiku/trunk/src/add-ons/kernel/generic/scsi_periph/io.cpp   2010-06-01 
13:37:55 UTC (rev 36988)
@@ -104,83 +104,24 @@
 }
 
 
-status_t
-periph_ioctl(scsi_periph_handle_info *handle, int op, void *buffer,
-       size_t length)
-{
-       switch (op) {
-               case B_GET_MEDIA_STATUS: {
-                       status_t res = B_OK;
-
-                       if (handle->device->removable)
-                               res = periph_get_media_status(handle);
-
-                       SHOW_FLOW(2, "%s", strerror(res));
-
-                       *(status_t *)buffer = res;
-                       return B_OK;
-               }
-
-               case B_SCSI_INQUIRY:
-                       return inquiry(handle->device, (scsi_inquiry *)buffer);
-
-               case B_SCSI_PREVENT_ALLOW:
-                       return prevent_allow(handle->device, *(bool *)buffer);
-
-               case B_RAW_DEVICE_COMMAND:
-                       return raw_command(handle->device, 
(raw_device_command*)buffer);
-
-               default:
-                       if (handle->device->scsi->ioctl != NULL) {
-                               return 
handle->device->scsi->ioctl(handle->device->scsi_device,
-                                       op, buffer, length);
-                       }
-
-                       SHOW_ERROR(4, "Unknown ioctl: %x", op);
-                       return B_BAD_VALUE;
-       }
-}
-
-
-/*!    Kernel daemon - once in a minute, it sets a flag so that the next 
command
-       is executed ordered; this way, we avoid starvation of SCSI commands 
inside
-       the SCSI queuing system - the ordered command waits for all previous
-       commands and thus no command can starve longer then a minute
-*/
-void
-periph_sync_queue_daemon(void *arg, int iteration)
-{
-       scsi_periph_device_info *device = (scsi_periph_device_info *)arg;
-
-       SHOW_FLOW0(3, "Setting ordered flag for next R/W access");
-       atomic_or(&device->next_tag_action, SCSI_ORDERED_QTAG);
-}
-
-
 /*! Universal read/write function */
-status_t
-periph_io(scsi_periph_device_info *device, io_operation *operation,
+static status_t
+read_write(scsi_periph_device_info *device, scsi_ccb *request,
+       io_operation *operation, uint64 offset, size_t originalNumBlocks,
+       physical_entry* vecs, size_t vecCount, bool isWrite,
        size_t* _bytesTransferred)
 {
        uint32 blockSize = device->block_size;
-       size_t numBlocks = operation->Length() / blockSize;
-       uint32 pos = operation->Offset() / blockSize;
-       scsi_ccb *request;
+       size_t numBlocks = originalNumBlocks;
+       uint32 pos = offset;
        err_res res;
        int retries = 0;
-       int err;
 
-       // don't test rw10_enabled restrictions - this flag may get changed
-       request = device->scsi->alloc_ccb(device->scsi_device);
-
-       if (request == NULL)
-               return B_NO_MEMORY;
-
        do {
                size_t numBytes;
-               bool is_rw10;
+               bool isReadWrite10;
 
-               request->flags = operation->IsWrite() ? SCSI_DIR_OUT : 
SCSI_DIR_IN;
+               request->flags = isWrite ? SCSI_DIR_OUT : SCSI_DIR_IN;
 
                // make sure we avoid 10 byte commands if they aren't supported
                if (!device->rw10_enabled || device->preferred_ccb_size == 6) {
@@ -190,10 +131,8 @@
                                numBlocks = 0x100;
 
                        // no way to break the 21 bit address limit
-                       if (pos > 0x200000) {
-                               err = B_BAD_VALUE;
-                               goto abort;
-                       }
+                       if (pos > 0x200000)
+                               return B_BAD_VALUE;
 
                        // don't allow transfer cross the 24 bit address limit
                        // (I'm not sure whether this is allowed, but this way 
we
@@ -203,13 +142,13 @@
                }
 
                numBytes = numBlocks * blockSize;
-               if (numBytes != operation->Length())
+               if (numBlocks != originalNumBlocks)
                        panic("I/O operation would need to be cut.");
 
                request->data = NULL;
-               request->sg_list = (physical_entry*)operation->Vecs();
+               request->sg_list = vecs;
                request->data_length = numBytes;
-               request->sg_count = operation->VecCount();
+               request->sg_count = vecCount;
                request->io_operation = operation;
                request->sort = pos;
                request->timeout = device->std_timeout;
@@ -223,11 +162,10 @@
                if (pos + numBlocks < 0x200000 && numBlocks <= 0x100) {
                        scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)request->cdb;
 
-                       is_rw10 = false;
+                       isReadWrite10 = false;
 
                        memset(cmd, 0, sizeof(*cmd));
-                       cmd->opcode = operation->IsWrite()
-                               ? SCSI_OP_WRITE_6 : SCSI_OP_READ_6;
+                       cmd->opcode = isWrite ? SCSI_OP_WRITE_6 : 
SCSI_OP_READ_6;
                        cmd->high_lba = (pos >> 16) & 0x1f;
                        cmd->mid_lba = (pos >> 8) & 0xff;
                        cmd->low_lba = pos & 0xff;
@@ -237,11 +175,10 @@
                } else {
                        scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb;
 
-                       is_rw10 = true;
+                       isReadWrite10 = true;
 
                        memset(cmd, 0, sizeof(*cmd));
-                       cmd->opcode = operation->IsWrite()
-                               ? SCSI_OP_WRITE_10 : SCSI_OP_READ_10;
+                       cmd->opcode = isWrite ? SCSI_OP_WRITE_10 : 
SCSI_OP_READ_10;
                        cmd->relative_address = 0;
                        cmd->force_unit_access = 0;
                        cmd->disable_page_out = 0;
@@ -251,12 +188,11 @@
                        request->cdb_length = sizeof(*cmd);
                }
 
-               // last chance to detect errors that occured during concurrent 
accesses
-               err = 0; // TODO: handle->pending_error;
+               // TODO: last chance to detect errors that occured during 
concurrent accesses
+               //status_t status = handle->pending_error;
+               //if (status != B_OK)
+               //      return status;
 
-               if (err)
-                       goto abort;
-
                device->scsi->async_io(request);
 
                acquire_sem(request->completion_sem);
@@ -280,7 +216,7 @@
                        case err_act_invalid_req:
                                // if this was a 10 byte command, the device 
probably doesn't
                                // support them, so disable them and retry
-                               if (is_rw10) {
+                               if (isReadWrite10) {
                                        atomic_and(&device->rw10_enabled, 0);
                                        res.action = err_act_retry;
                                } else
@@ -290,17 +226,98 @@
        } while ((res.action == err_act_retry && retries++ < 3)
                || (res.action == err_act_many_retries && retries++ < 30));
 
-       device->scsi->free_ccb(request);
-
        // peripheral layer only created "read" error, so we have to
        // map them to "write" errors if this was a write request
-       if (res.error_code == B_DEV_READ_ERROR && operation->IsWrite())
+       if (res.error_code == B_DEV_READ_ERROR && isWrite)
                return B_DEV_WRITE_ERROR;
 
        return res.error_code;
+}
 
-abort:
+
+// #pragma mark - public functions
+
+
+status_t
+periph_ioctl(scsi_periph_handle_info *handle, int op, void *buffer,
+       size_t length)
+{
+       switch (op) {
+               case B_GET_MEDIA_STATUS: {
+                       status_t res = B_OK;
+
+                       if (handle->device->removable)
+                               res = periph_get_media_status(handle);
+
+                       SHOW_FLOW(2, "%s", strerror(res));
+
+                       *(status_t *)buffer = res;
+                       return B_OK;
+               }
+
+               case B_SCSI_INQUIRY:
+                       return inquiry(handle->device, (scsi_inquiry *)buffer);
+
+               case B_SCSI_PREVENT_ALLOW:
+                       return prevent_allow(handle->device, *(bool *)buffer);
+
+               case B_RAW_DEVICE_COMMAND:
+                       return raw_command(handle->device, 
(raw_device_command*)buffer);
+
+               default:
+                       if (handle->device->scsi->ioctl != NULL) {
+                               return 
handle->device->scsi->ioctl(handle->device->scsi_device,
+                                       op, buffer, length);
+                       }
+
+                       SHOW_ERROR(4, "Unknown ioctl: %x", op);
+                       return B_BAD_VALUE;
+       }
+}
+
+
+/*!    Kernel daemon - once in a minute, it sets a flag so that the next 
command
+       is executed ordered; this way, we avoid starvation of SCSI commands 
inside
+       the SCSI queuing system - the ordered command waits for all previous
+       commands and thus no command can starve longer then a minute
+*/
+void
+periph_sync_queue_daemon(void *arg, int iteration)
+{
+       scsi_periph_device_info *device = (scsi_periph_device_info *)arg;
+
+       SHOW_FLOW0(3, "Setting ordered flag for next R/W access");
+       atomic_or(&device->next_tag_action, SCSI_ORDERED_QTAG);
+}
+
+
+status_t
+periph_read_write(scsi_periph_device_info *device, scsi_ccb *request,
+       uint64 offset, size_t numBlocks, physical_entry* vecs, size_t vecCount,
+       bool isWrite, size_t* _bytesTransferred)
+{
+       return read_write(device, request, NULL, offset, numBlocks, vecs, 
vecCount,
+               isWrite, _bytesTransferred);
+}
+
+
+status_t
+periph_io(scsi_periph_device_info *device, io_operation *operation,
+       size_t* _bytesTransferred)
+{
+       const uint32 blockSize = device->block_size;
+
+       // don't test rw10_enabled restrictions - this flag may get changed
+       scsi_ccb *request = device->scsi->alloc_ccb(device->scsi_device);
+       if (request == NULL)
+               return B_NO_MEMORY;
+
+       status_t status = read_write(device, request, operation,
+               operation->Offset() / blockSize, operation->Length() / 
blockSize,
+               (physical_entry *)operation->Vecs(), operation->VecCount(),
+               operation->IsWrite(), _bytesTransferred);
+
        device->scsi->free_ccb(request);
-       return err;
+       return status;
 }
 

Modified: haiku/trunk/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp
===================================================================
--- haiku/trunk/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp  
2010-06-01 12:06:56 UTC (rev 36987)
+++ haiku/trunk/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp  
2010-06-01 13:37:55 UTC (rev 36988)
@@ -131,6 +131,7 @@
        periph_handle_close,
        periph_handle_free,
 
+       periph_read_write,
        periph_io,
        periph_ioctl,
        periph_check_capacity,

Modified: haiku/trunk/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h
===================================================================
--- haiku/trunk/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h        
2010-06-01 12:06:56 UTC (rev 36987)
+++ haiku/trunk/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h        
2010-06-01 13:37:55 UTC (rev 36988)
@@ -91,6 +91,9 @@
 
 // io.c
 
+status_t periph_read_write(scsi_periph_device_info *device, scsi_ccb *request,
+       uint64 offset, size_t numBlocks, physical_entry* vecs, size_t vecCount,
+       bool isWrite, size_t* _bytesTransferred);
 status_t periph_io(scsi_periph_device_info* device, io_operation* operation,
        size_t *_bytesTransferred);
 status_t periph_ioctl(scsi_periph_handle_info *handle, int op,


Other related posts:

  • » [haiku-commits] r36988 - in haiku/trunk: headers/private/drivers src/add-ons/kernel/generic/scsi_periph - axeld