New struct ata_request.

Added ata_request as wrapper around scsi_ccb while they are executed in the ata stack.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23344 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2008-01-10 16:09:24 +00:00
parent 0625889c61
commit a3af33c75d
3 changed files with 187 additions and 0 deletions

View File

@ -6,6 +6,7 @@ UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
KernelAddon ide :
ata.c
ata_request.c
atapi.c
channels.c
devices.c

View File

@ -0,0 +1,153 @@
#include "ata_request.h"
#include "ide_internal.h"
#include "scsi_cmds.h"
#include <string.h>
#define TRACE dprintf
void
ata_request_init(ata_request *request, struct ide_device_info *device)
{
memset(request, 0, sizeof(request));
request->device = device;
}
/* Start the request, but don't clear sense to allow
* retrieving the previous sense data.
*/
void ata_request_start(ata_request **_request, struct ide_device_info *device, struct scsi_ccb *ccb)
{
ata_request *request;
IDE_LOCK(device->bus);
if (device->bus->state != ata_state_idle) {
request = NULL;
} else {
ASSERT(device->requestFree != NULL);
ASSERT(device->requestActive == NULL);
ASSERT(device->bus->active_device == NULL);
device->bus->state = ata_state_busy;
device->bus->active_device = device;
request = device->requestFree;
device->requestActive = request;
device->requestFree = NULL;
}
IDE_UNLOCK(device->bus);
*_request = request;
if (!request)
return; // bus was busy
ASSERT(request->device == device);
request->ccb = ccb;
request->is_write = 0;
request->uses_dma = 0;
request->packet_irq = 0;
ASSERT(request->ccb->subsys_status == SCSI_REQ_INPROG);
// pretend success
request->ccb->subsys_status = SCSI_REQ_CMP;
// device_status always remains set to SCSI_STATUS_GOOD
// except when ata_request_set_checkcondition() is called.
request->ccb->device_status = SCSI_STATUS_GOOD;
}
void
ata_request_clear_sense(ata_request *request)
{
request->senseKey = 0;
request->senseAsc = 0;
request->senseAscq = 0;
}
void
ata_request_set_status(ata_request *request, uint8 status)
{
ASSERT(status != SCSI_REQ_CMP);
request->ccb->subsys_status = status;
}
void
ata_request_set_sense(ata_request *request, uint8 key, uint16 asc_acq)
{
request->senseKey = key;
request->senseAsc = asc_acq >> 8;
request->senseAscq = asc_acq & 0xff;
}
void
ata_request_finish(ata_request *request, bool resubmit)
{
scsi_ccb *ccb;
TRACE("ata_request_finish: request %p, subsys_status 0x%02x, senseKey %02x\n",
request, request->ccb->subsys_status, request->senseKey);
// when the request completed and has set sense
// data, report this to the scsci stack by setting
// CHECK CONDITION status
if (request->ccb->subsys_status == SCSI_REQ_CMP && request->senseKey != 0) {
TRACE("ata_request_finish - setting check condition\n");
request->ccb->subsys_status = SCSI_REQ_CMP_ERR;
request->ccb->device_status = SCSI_STATUS_CHECK_CONDITION;
// copy sense data if caller requested it
if ((request->ccb->flags & SCSI_DIS_AUTOSENSE) == 0) {
scsi_sense sense;
int sense_len;
TRACE("ata_request_finish - copying autosense data\n");
// we cannot copy sense directly as sense buffer may be too small
scsi_set_sense(&sense, request);
ASSERT(sizeof(*request->ccb->sense) == SCSI_MAX_SENSE_SIZE);
sense_len = min(sizeof(*request->ccb->sense), sizeof(sense));
memcpy(request->ccb->sense, &sense, sense_len);
request->ccb->sense_resid = SCSI_MAX_SENSE_SIZE - sense_len;
request->ccb->subsys_status |= SCSI_AUTOSNS_VALID;
// device sense gets reset once it's read
ata_request_clear_sense(request);
ASSERT(request->ccb->subsys_status == SCSI_REQ_CMP_ERR);
ASSERT(request->ccb->device_status == SCSI_STATUS_CHECK_CONDITION);
}
}
ccb = request->ccb;
IDE_LOCK(request->device->bus);
ASSERT(request->device->bus->state == ata_state_busy);
ASSERT(request->device->bus->active_device == request->device);
ASSERT(request->device->requestActive == request);
ASSERT(request->device->requestFree == NULL);
request->device->bus->state = ata_state_idle;
request->device->bus->active_device = NULL;
request->device->requestActive = NULL;
request->device->requestFree = request;
IDE_UNLOCK(request->device->bus);
ACQUIRE_BEN(&request->device->bus->status_report_ben);
if (resubmit)
scsi->resubmit(ccb);
else
scsi->finished(ccb, 1);
RELEASE_BEN(&request->device->bus->status_report_ben);
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2008 Marcus Overhagen. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _ATA_REQUEST_H
#define _ATA_REQUEST_H
#include <SupportDefs.h>
typedef struct ata_request {
struct ide_device_info * device;
struct scsi_ccb * ccb; // basic scsi request
uint8 is_write : 1; // true for write request
uint8 uses_dma : 1; // true if using dma
uint8 packet_irq : 1; // true if waiting for command packet irq
uint8 senseKey;
uint8 senseAsc;
uint8 senseAscq;
} ata_request;
struct scsi_ccb;
struct ide_device_info;
void ata_request_init(ata_request *request, struct ide_device_info *device);
void ata_request_start(ata_request **_request, struct ide_device_info *device, struct scsi_ccb *ccb);
void ata_request_clear_sense(ata_request *request);
void ata_request_set_status(ata_request *request, uint8 status);
void ata_request_set_sense(ata_request *request, uint8 key, uint16 asc_acq);
void ata_request_finish(ata_request *request, bool resubmit);
#endif