Files
m241Neelima/components/ip_net2-6.9/ipfreescale/sec2/1_2/sec2_request.c
T
2026-07-30 11:19:44 +05:30

722 lines
26 KiB
C

/****************************************************************************
* sec2_request.c - request/response handler
****************************************************************************
* Copyright (c) 2003-2005 Freescale Semiconductor
* All Rights Reserved. Proprietary and Confidential.
*
* NOTICE: The information contained in this file is proprietary
* to Freescale Semiconductor, and is being made available to
* Freescale's customers under strict license agreements.
* Use or disclosure of this information is permissible only
* under the terms of the existing license agreement.
***************************************************************************/
/* Revision History:
* 1.0 Aug 24,2003 dgs - adapted from the final version of mpc18x
* Jun 04,2004 sec - add completion cleanup for scatter pointers
* 1.1.0 Nov 16,2004 sec - integrate linux changes from prior versions, eliminate
* StartDescriptor() function
* 1.1.1 Dec 16,2004 sec - remove lock variable, remove old diagnostics, add
* minor optimizations
* 1.2 Jan 27,2005 sec - add CHA details to error dump
*/
#include "Sec2Driver.h"
/* Interpeak begin */
#define MAX_NUM_CHANNELS 4
#undef NUM_CHANNELS
#define NUM_CHANNELS (num_channels)
extern int num_channels;
/* Interpeak end */
/* Interpeak begin */
#ifdef __KERNEL__
static inline void ctx_element_enqueue(Ctx_queue_header *hdr, Ctx_queue_element *item)
{
item->next = NULL;
if (hdr->head)
{
/* Place item in the end of the queue */
hdr->tail->next = item;
hdr->tail = item;
}
else
{
/* Queue is empty */
hdr->head = item;
hdr->tail = item;
}
}
#endif
/* Interpeak end */
/********************************************************************************/
/* Function Name: ProcessRequest */
/* Purpose: To handle the IO request routine */
/* Input: req - the pointer of the IO request */
/* callingTaskId - the task Id */
/* Output: req - the pointer of the IO request buffer */
/* Return: SEC2_Success if success, otherwise error code */
/********************************************************************************/
int ProcessRequest(GENERIC_REQ *req, int callingTaskId)
{
register int freeChannel;
int status;
QUEUE_ENTRY *newEntry;
BOOLEAN bAvailableCHA;
/* Interpeak begin */
/* schedule queued requests on any freed channels */
ScheduleNext();
/* Interpeak end */
/* check to see if the required CHA is available */
bAvailableCHA = FALSE;
if (CheckChas(req->opId) == SEC2_SUCCESS)
bAvailableCHA = TRUE;
IOLockChannelAssignment();
if (bAvailableCHA && FreeChannels > 0)
{
/* dynamic request, see if there are any free channels */
for (freeChannel=0;freeChannel<NUM_CHANNELS;freeChannel++)
{
if (ChannelAssignments[freeChannel].assignment == CHANNEL_FREE)
{
SEC2Dump(DBGTXT_SETRQ, ("ProcessRequest(): free channel = %d\n", freeChannel));
/* reserve this free channel for this operation */
ChannelAssignments[freeChannel].assignment = CHANNEL_DYNAMIC;
ChannelAssignments[freeChannel].ownerTaskId = callingTaskId;
ChannelAssignments[freeChannel].pReq = req;
FreeChannels--;
IOUnLockChannelAssignment();
/* translate this request into DPD's */
status = RequestToDpd(req, freeChannel);
if (status != SEC2_SUCCESS)
return CompleteRequest(freeChannel, status, FALSE, NULL);
/* write the address of the first DPD to the channel */
/* this starts the request */
*(ChannelNextDescriptorRegister[freeChannel]+1) = __vpa((unsigned long)(ChannelAssignments[freeChannel].Dpds[0]));
#ifdef __KERNEL__
/* Interpeak begin */
if(!in_interrupt())
/* Interpeak end */
schedule();
#endif
return SEC2_SUCCESS;
}
}
/* Interpeak begin */
goto queue;
/* Interpeak end */
} else {
/* Interpeak begin */
queue:
/* Interpeak end */
IOUnLockChannelAssignment();
if (QueueEntryDepth >= QUEUE_ENTRY_DEPTH)
return (SEC2_INSUFFICIENT_REQS);
#ifndef __KERNEL__
semTake (QueueSemId, 100);
#endif
newEntry = ProcessQueueBottom;
ProcessQueueBottom = ProcessQueueBottom->next;
/* fill in the queue structure */
newEntry->pReq = req;
newEntry->requestingTaskId = callingTaskId;
QueueEntryDepth++;
#ifndef __KERNEL__
semGive (QueueSemId);
#endif
SEC2Dump(DBGTXT_SETRQ, ("Queueing Up->newEntry=0x%lx\n", (unsigned long)newEntry));
}
return SEC2_SUCCESS;
} /* end of ProcessDynamicRequest() */
#ifdef __KERNEL__
void ProcessingComplete(unsigned long not_used)
#else
void ProcessingComplete(void)
#endif
{
register int channel;
register int cha;
/* Interpeak begin */
int status[MAX_NUM_CHANNELS]; /* The status for the channel */
BOOLEAN bIsComplete[MAX_NUM_CHANNELS]; /* Indicates that the channel is done */
/* Interpeak end */
DEVICE_REGS *pRegs; /* register? */
static DEVICE_REGS regs;
#ifdef DBG
int i;
#endif
pRegs = &regs;
/* we sit here forever, waiting for register content messages from the ISR */
while (1)
{
#ifdef VXWORKS
/* wait for register content message from the ISR */
if (msgQReceive(IsrMsgQId,
(char*)pRegs,
sizeof(DEVICE_REGS),
WAIT_FOREVER) != sizeof(DEVICE_REGS))
continue;
#else
QmsgWait();
#endif
#ifdef DBG
SEC2Dump(DBGTXT_SVCRQ, ("ProcessingComplete(): IntStatus - "));
if ((pRegs->IntStatus[0] & ALL_CHANNEL_INT_ERROR_MASK) ||
(pRegs->IntStatus[1] & ALL_CHA_INT_ERROR_MASK))
{
SEC2Dump(DBGTXT_SVCRQ, ("Error "));
if (pRegs->IntStatus[0] & CHANNEL_INT_ERROR_1) SEC2Dump(DBGTXT_SVCRQ, ("ch1 "));
if (pRegs->IntStatus[0] & CHANNEL_INT_ERROR_2) SEC2Dump(DBGTXT_SVCRQ, ("ch2 "));
if (pRegs->IntStatus[0] & CHANNEL_INT_ERROR_3) SEC2Dump(DBGTXT_SVCRQ, ("ch3 "));
if (pRegs->IntStatus[0] & CHANNEL_INT_ERROR_4) SEC2Dump(DBGTXT_SVCRQ, ("ch4 "));
if (pRegs->IntStatus[1] & CHA_INT_ERROR_DEU) SEC2Dump(DBGTXT_SVCRQ, ("DES "));
if (pRegs->IntStatus[1] & CHA_INT_ERROR_AESU) SEC2Dump(DBGTXT_SVCRQ, ("AES "));
if (pRegs->IntStatus[1] & CHA_INT_ERROR_MDEU) SEC2Dump(DBGTXT_SVCRQ, ("MD "));
if (pRegs->IntStatus[1] & CHA_INT_ERROR_AFEU) SEC2Dump(DBGTXT_SVCRQ, ("AF "));
if (pRegs->IntStatus[1] & CHA_INT_ERROR_RNG) SEC2Dump(DBGTXT_SVCRQ, ("RNG "));
if (pRegs->IntStatus[1] & CHA_INT_ERROR_PKEU) SEC2Dump(DBGTXT_SVCRQ, ("PK "));
SEC2Dump(DBGTXT_SVCRQ, ("\n"));
for (i = 0; i < NUM_CHANNELS; i++)
SEC2Dump(DBGTXT_SVCRQ, ("Ch %d ptr status: 0x%08lx%08lx\n",
i + 1,
pRegs->ChannelError[i][0],
pRegs->ChannelError[i][1]));
SEC2Dump(DBGTXT_SVCRQ, ("DES int status: 0x%08lx\n", pRegs->ChaError[cha_idx[0]][1]));
SEC2Dump(DBGTXT_SVCRQ, ("AES int status: 0x%08lx\n", pRegs->ChaError[cha_idx[1]][1]));
SEC2Dump(DBGTXT_SVCRQ, ("MDEU int status: 0x%08lx\n", pRegs->ChaError[cha_idx[2]][1]));
SEC2Dump(DBGTXT_SVCRQ, ("AFEU int status: 0x%08lx\n", pRegs->ChaError[cha_idx[3]][1]));
SEC2Dump(DBGTXT_SVCRQ, ("RNG int status: 0x%08lx\n", pRegs->ChaError[cha_idx[4]][1]));
SEC2Dump(DBGTXT_SVCRQ, ("PKEU int status: 0x%08lx\n", pRegs->ChaError[cha_idx[5]][1]));
}
else
if ((pRegs->IntStatus[0] & ALL_CHANNEL_INT_DONE_MASK) ||
(pRegs->IntStatus[1] & ALL_CHA_INT_DONE_MASK))
{
SEC2Dump(DBGTXT_SVCRQ, ("Done "));
if (pRegs->IntStatus[0] & CHANNEL_INT_DONE_1) SEC2Dump(DBGTXT_SVCRQ, ("ch1 "));
if (pRegs->IntStatus[0] & CHANNEL_INT_DONE_2) SEC2Dump(DBGTXT_SVCRQ, ("ch2 "));
if (pRegs->IntStatus[0] & CHANNEL_INT_DONE_3) SEC2Dump(DBGTXT_SVCRQ, ("ch3 "));
if (pRegs->IntStatus[0] & CHANNEL_INT_DONE_4) SEC2Dump(DBGTXT_SVCRQ, ("ch4 "));
if (pRegs->IntStatus[1] & CHA_INT_DONE_DEU) SEC2Dump(DBGTXT_SVCRQ, ("DES "));
if (pRegs->IntStatus[1] & CHA_INT_DONE_AESU) SEC2Dump(DBGTXT_SVCRQ, ("AES "));
if (pRegs->IntStatus[1] & CHA_INT_DONE_MDEU) SEC2Dump(DBGTXT_SVCRQ, ("MD "));
if (pRegs->IntStatus[1] & CHA_INT_DONE_AFEU) SEC2Dump(DBGTXT_SVCRQ, ("AF "));
if (pRegs->IntStatus[1] & CHA_INT_DONE_RNG) SEC2Dump(DBGTXT_SVCRQ, ("RNG "));
if (pRegs->IntStatus[1] & CHA_INT_DONE_PKEU) SEC2Dump(DBGTXT_SVCRQ, ("PK "));
}
else
SEC2Dump(DBGTXT_SVCRQ, ("Unknown"));
SEC2Dump(DBGTXT_SVCRQ, ("\n"));
#endif
for (channel = 0; channel < NUM_CHANNELS; channel++)
{
bIsComplete[channel] = FALSE;
status[channel] = SEC2_SUCCESS;
}
/* deal with any channel done interrupts */
if ((pRegs->IntStatus[0] & ALL_CHANNEL_INT_DONE_MASK) != 0)
/* found at least one channel done interrupt */
for (channel = 0; channel < NUM_CHANNELS; channel++)
if ((pRegs->IntStatus[0] & ChannelDoneInterruptMasks[channel]) != 0)
/* found a channel done interrupt */
bIsComplete[channel] = TRUE;
/* deal with any CHA done (manual/debug/target mode) interrupts */
if ((pRegs->IntStatus[1] & ALL_CHA_INT_DONE_MASK) != 0)
/* found at least one CHA done interrupt */
for (cha=0; cha<NUM_CHAS; cha++)
if ((pRegs->IntStatus[1] & ChaDoneInterruptMasks[cha]) != 0)
{
/* found a CHA done interrupt, notify application */
if (cha < 4)
channel = (pRegs->ChaAssignmentStatus[0] >> (cha * 8)) & 0xF;
else
channel = (pRegs->ChaAssignmentStatus[1] >> ((cha - 4) * 8)) & 0xF;
if (channel > 0 && channel < (NUM_CHANNELS+1))
bIsComplete[channel-1] = TRUE;
SEC2Dump(DBGTXT_SVCRQ,
("ProcessingComplete(): Channel %d Assigned\n",
channel));
} /* if (CHA int status) */
/* deal with any error interrupts */
if (((pRegs->IntStatus[0] & ALL_INT_ERRORS_MASK_LOW) != 0) ||
((pRegs->IntStatus[1] & ALL_INT_ERRORS_MASK_HIGH) != 0))
{
/* need to find the channel */
/* deal with CHA error interrupts */
for (cha=0; cha<NUM_CHAS; cha++)
{
if (cha < 4)
channel = (pRegs->ChaAssignmentStatus[0] >> (cha * 8)) & 0xF;
else
channel = (pRegs->ChaAssignmentStatus[1] >> ((cha - 4) * 8)) & 0xF;
if (channel > 0 && channel < (NUM_CHANNELS+1) &&
(pRegs->IntStatus[0] & ChannelErrorInterruptMasks[channel-1]) != 0)
{
status[channel-1] = SEC2_CHA_ERROR;
bIsComplete[channel-1] = TRUE;
}
} /* end for cha loop */
for (channel=0; channel<NUM_CHANNELS; channel++)
{
if ((pRegs->IntStatus[0] & ChannelErrorInterruptMasks[channel]) != 0)
{
bIsComplete[channel] = TRUE;
/* this was a channel error then */
/* return the error code with some sort of quasi-priority, since */
/* multiples could occur */
status[channel] = SEC2_UNKNOWN_ERROR;
if ((pRegs->ChannelError[channel][1] & CHANNEL_CHA_ERROR) ||
(pRegs->ChannelError[channel][1] & CHANNEL_CHA_ASSIGN_ERROR))
status[channel] = SEC2_CHA_ERROR;
if (pRegs->ChannelError[channel][1] & CHANNEL_UNRECOGNIZED_HEADER_ERROR)
status[channel] = SEC2_INVALID_OPERATION_ID;
if (pRegs->ChannelError[channel][1] & CHA_PARITY_SYSTEM_ERROR)
status[channel] = SEC2_PARITY_SYSTEM_ERROR;
if (pRegs->ChannelError[channel][1] & CHANNEL_NULL_FETCH_POINTER)
status[channel] = SEC2_INCOMPLETE_POINTER;
if ((pRegs->ChannelError[channel][1] & CHANNEL_SCATTER_LENGTH_ERROR) ||
(pRegs->ChannelError[channel][1] & CHANNEL_SCATTER_BOUND_ERROR) ||
(pRegs->ChannelError[channel][1] & CHANNEL_GATHER_LENGTH_ERROR) ||
(pRegs->ChannelError[channel][1] & CHANNEL_GATHER_BOUND_ERROR) ||
(pRegs->ChannelError[channel][1] & CHANNEL_ZERO_SCATTER_LEN_ERROR))
status[channel] = SEC2_SCATTER_LIST_ERROR;
if (pRegs->ChannelError[channel][1] & CHANNEL_BUS_MASTER_ERROR)
status[channel] = SEC2_BUS_MASTER_ERROR;
if ((pRegs->ChannelError[channel][1] & CHANNEL_FETCH_FIFO_NEARMISS_ERROR) ||
(pRegs->ChannelError[channel][1] & CHANNEL_FETCH_FIFO_OVERFLOW_ERROR))
status[channel] = SEC2_FETCH_FIFO_OVERFLOW;
} /* if (valid interrupt) */
} /* for (channels) */
} /* if (cha int done) */
for (channel = 0; channel < NUM_CHANNELS; channel++)
if (bIsComplete[channel])
CompleteRequest(channel, status[channel], TRUE, pRegs);
/* schedule queued requests on any freed channels */
ScheduleNext();
} /* if (message from queue) */
SEC2Dump(DBGTXT_SVCRQ, ("ProcessingComplete Done\n"));
} /* End of ProcessingComplete */
void RemoveQueueEntry(QUEUE_ENTRY *entry)
{
SEC2Dump(DBGTXT_SVCRQ, ("RemoveQueueEntry->Entry=0x%lx\n", (unsigned long)entry));
semTake (QueueSemId, 100);
if (QueueEntryDepth > 0) {
QueueEntryDepth--;
entry->requestingTaskId = 0;
entry->pReq = NULL;
SEC2Dump(DBGTXT_SVCRQ, ("RemoveQueueEntry->QueueEntryDepth=0x%lx\n", QueueEntryDepth));
ProcessQueueTop = ProcessQueueTop->next;
SEC2Dump(DBGTXT_SVCRQ, ("RemoveQueueEntry->ProcessQueueTop=0x%lx\n", (unsigned long)ProcessQueueTop));
}
semGive (QueueSemId);
return;
} /* end of RemoveQueueEntry */
/* does not return a status value -- all errors are returned to the requesting
application through the request structure status value */
/* this should only be called with channel assignments locked */
void ScheduleNext()
{
register unsigned int channel;
int status;
IOLockChannelAssignment();
channel = 0;
while (channel < NUM_CHANNELS)
{
if (ChannelAssignments[channel].assignment != CHANNEL_FREE)
{
channel++;
continue;
}
/* Is there anything queued up? */
if (QueueEntryDepth > 0) {
if (CheckChas(ProcessQueueTop->pReq->opId) != SEC2_SUCCESS) {
SEC2Dump(DBGTXT_SETRQ, ("ScheduleNext->Breaking Out CheckChas fails 0x%lx\n", ProcessQueueTop->pReq->opId));
break;
}
ChannelAssignments[channel].assignment = CHANNEL_DYNAMIC;
ChannelAssignments[channel].pReq = ProcessQueueTop->pReq;
ChannelAssignments[channel].ownerTaskId = ProcessQueueTop->requestingTaskId;
RemoveQueueEntry(ProcessQueueTop);
FreeChannels--;
SEC2Dump(DBGTXT_SETRQ, ("ScheduleNext->FreeChannels 0x%x\n", FreeChannels));
IOUnLockChannelAssignment();
status = RequestToDpd(ChannelAssignments[channel].pReq, channel);
if (status != SEC2_SUCCESS)
{
/* Problem with request, return error to the application */
CompleteRequest(channel, status, TRUE, NULL);
IOLockChannelAssignment();
continue;
}
else
{
/* write the address of the first DPD to the channel */
/* this starts hardware processing the request */
*(ChannelNextDescriptorRegister[channel]+1) = __vpa((unsigned long)(ChannelAssignments[channel].Dpds[0]));
#ifdef __KERNEL__
/* Interpeak begin */
if(!in_interrupt())
/* Interpeak end */
schedule();
#endif
IOLockChannelAssignment();
}
}
/* finished with this channel */
channel++;
}
IOUnLockChannelAssignment();
}
/* As T2.0 is designed, output from PKHA will be "front loaded" in the output */
/* buffer such that data starts at the zeroth element in the output buffer */
/* As long as the output and the modulus size match, this is fine. If the */
/* output is larger than the modulus, then we would normally expect the */
/* output to be at the far end of the buffer (leading zeros at the start) */
/* However, it puts the modulated output "up front". Normally, there's no */
/* reason for the output > modulus, but if it exists, this corrects for it */
#ifdef PKHA_OUTPUT_SHIFT
static void fixPKHAresult(DPD *pkDesc)
{
int i;
unsigned long modlen, outlen, shift, *outbuf;
unsigned long *src, *dest;
modlen = (pkDesc->fld[0].len & 0xffff0000) >> 16;
outlen = (pkDesc->fld[4].len & 0xffff0000) >> 16;
outbuf = (unsigned long *)pkDesc->fld[4].ptr;
/* Check difference and save, if not different, exit */
if (outlen > modlen)
shift = (outlen - modlen)/4;
else
return;
dest = &outbuf[(outlen / 4) - 1];
src = &outbuf[(modlen / 4) - 1];
for (i = 0; i < shift; i++)
{
*(dest--) = *(src);
*(src--) = 0;
}
}
#endif
int CompleteRequest(int channel, int status, BOOLEAN bDoNotify, DEVICE_REGS *pRegs)
{
register GENERIC_REQ *req = NULL;
int i, j;
IOLockChannelAssignment();
if (ChannelAssignments[channel].pReq != NULL)
req = ChannelAssignments[channel].pReq;
else
{
/* Interpeak begin */
IOUnLockChannelAssignment();
/* Interpeak end */
return -1;
}
SEC2Dump(DBGTXT_SVCRQ, ("CompleteRequest->channel %d, request=0x%lx\n", channel, (unsigned long)req));
((GENERIC_REQ*)req)->status = status;
ChannelAssignments[channel].pReq = NULL;
#ifdef PKHA_OUTPUT_SHIFT
/* This is here as a workaround for completing PKHA */
for (i = 0; i < MAX_DPDS; i++)
if (ChannelAssignments[channel].Dpds[i] != NULL)
if ((ChannelAssignments[channel].Dpds[i]->header & 0xf8) == 0x00000080) /* PKHA? */
fixPKHAresult(ChannelAssignments[channel].Dpds[i]);
#endif
/* Walk through the request's descriptor list. For any DPD that was in use, */
/* if they used scatter lists, we have to return the free elements to the */
/* fragment pool. So check for scattered pointers, and unmap them */
for (i = 0; i < MAX_DPDS; i++)
if (ChannelAssignments[channel].Dpds[i] != NULL)
for (j = 0; j < NUM_DPD_FLDS; j++)
if (ChannelAssignments[channel].Dpds[i]->fld[j].len & PTRTYPE_JBIT)
UnmapScatterFragments((void *)ChannelAssignments[channel].Dpds[i]->fld[j].ptr);
/* Change the assignment state. This is the last thing to be done
since the channel becomes immediately available when you set it
to FREE (dynamic) or ASSIGNED (static).
*/
if (ChannelAssignments[channel].assignment == CHANNEL_DYNAMIC)
{
FreeChannels++;
ChannelAssignments[channel].assignment = CHANNEL_FREE;
}
/* Interpeak begin */
#ifdef __KERNEL__
if (bDoNotify)
{
if (status == SEC2_SUCCESS)
{
if (((GENERIC_REQ *)req)->notifyFlags & NOTIFY_IS_PID)
{
Ctx_queue_element *item;
item = kmalloc(sizeof(Ctx_queue_element), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (item != NULL)
{
item->pid = (int)((GENERIC_REQ *)req)->notify;
item->ctx = ((GENERIC_REQ*)req)->pNotifyCtx;
ctx_element_enqueue(&ctx_done_queue, item);
}
}
}
else
{
if (((GENERIC_REQ *)req)->notifyFlags & NOTIFY_ERROR_IS_PID)
{
Ctx_queue_element *item;
item = kmalloc(sizeof(Ctx_queue_element), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (item != NULL)
{
item->pid = (int)((GENERIC_REQ *)req)->notify_on_error;
item->ctx = ((GENERIC_REQ*)req)->pNotifyCtx;
ctx_element_enqueue(&ctx_error_queue, item);
}
}
}
}
#endif
/* Interpeak end */
IOUnLockChannelAssignment();
if (bDoNotify)
{
if (status == SEC2_SUCCESS)
{
/* This is a normal completion notifier */
SEC2Dump(DBGTXT_SVCRQ, ("CompleteReqest(): success notifier in process\n"));
if (((GENERIC_REQ *)req)->notifyFlags & NOTIFY_IS_PID)
{
#ifdef __KERNEL__
send_sig(SIGUSR1, find_task_by_pid((long)((GENERIC_REQ*)req)->notify), 0);
#endif
#ifdef VXWORKS
(void)kill((long)((GENERIC_REQ*)req)->notify, SIGUSR1);
#endif
}
else
{
if ((((GENERIC_REQ*)req)->notify) != NULL)
(((GENERIC_REQ*)req)->notify)(((GENERIC_REQ*)req)->pNotifyCtx);
}
}
else
{
/* else this is an error notifier... */
SEC2Dump(DBGTXT_SVCRQ, ("CompleteReqest(): error notifier in process\n"));
if (((GENERIC_REQ *)req)->notifyFlags & NOTIFY_ERROR_IS_PID)
{
#ifdef __KERNEL__
send_sig(SIGUSR2, find_task_by_pid((long)((GENERIC_REQ *)req)->notify_on_error), 0);
#endif
#ifdef VXWORKS
(void)kill((long)((GENERIC_REQ*)req)->notify_on_error, SIGUSR2);
#endif
}
else
{
if ((((GENERIC_REQ*)req)->notify_on_error) != NULL)
{
/* first, do the error context save */
((GENERIC_REQ*)req)->ctxNotifyOnErr.errorcode = ((GENERIC_REQ*)req)->status;
if (pRegs == NULL)
memset(&(((GENERIC_REQ*)req)->ctxNotifyOnErr.driverstatus),0,sizeof(STATUS_REQ));
else
CopyRegsToStatus(&(((GENERIC_REQ*)req)->ctxNotifyOnErr.driverstatus), pRegs);
((GENERIC_REQ*)req)->ctxNotifyOnErr.request = req;
/* now call the handler */
SEC2Dump(DBGTXT_SVCRQ, ("CompleteRequest(): calling error notifier with context\n"));
(((GENERIC_REQ*)req)->notify_on_error)(&(((GENERIC_REQ*)req)->ctxNotifyOnErr));
}
}
}
}
return status;
}
int GetStatus(STATUS_REQ *pStatus, int callingTaskId)
{
int i;
pStatus->ChaAssignmentStatusRegister[0] = *(unsigned long *)(ChaAssignmentStatusRegister);
pStatus->ChaAssignmentStatusRegister[1] = *(unsigned long *)(ChaAssignmentStatusRegister + 1);
pStatus->InterruptControlRegister[0] = *(unsigned long *)(InterruptControlRegister);
pStatus->InterruptControlRegister[1] = *(unsigned long *)(InterruptControlRegister + 1);
pStatus->InterruptStatusRegister[0] = *(unsigned long *)(InterruptStatusRegister);
pStatus->InterruptStatusRegister[1] = *(unsigned long *)(InterruptStatusRegister + 1);
pStatus->IdRegister = *(unsigned long *)(IdRegister);
for (i = 0; i < NUM_CHANNELS; i++)
{
pStatus->ChannelStatusRegister[i][0] = *(unsigned long *)(ChannelPointerStatusRegister[i]);
pStatus->ChannelStatusRegister[i][1] = *(unsigned long *)(ChannelPointerStatusRegister[i] + 1);
}
for (i = 0; i < NUM_CHANNELS; i++)
{
pStatus->ChannelConfigurationRegister[i][0] = *(unsigned long *)(ChannelConfigRegister[i]);
pStatus->ChannelConfigurationRegister[i][1] = *(unsigned long *)(ChannelConfigRegister[i] + 1);
}
for (i = 0; i < NUM_CHAS; i++)
{
pStatus->CHAInterruptStatusRegister[i][0] = *(unsigned long *)(ChaInterruptStatusRegister[i]);
pStatus->CHAInterruptStatusRegister[i][1] = *(unsigned long *)(ChaInterruptStatusRegister[i] + 1);
}
pStatus->QueueEntryDepth = QueueEntryDepth;
pStatus->FreeChannels = FreeChannels;
pStatus->FreeRngas = FreeRngas;
pStatus->FreeAfhas = FreeAfhas;
pStatus->FreeDesas = FreeDesas;
pStatus->FreeMdhas = FreeMdhas;
pStatus->FreePkhas = FreePkhas;
pStatus->FreeAesas = FreeAesas;
pStatus->FreeKeas = FreeKeas;
pStatus->BlockSize = BlockSize;
return SEC2_SUCCESS;
}
void CopyRegsToStatus(STATUS_REQ *pStatus, DEVICE_REGS *pRegs)
{
int channel, cha;
/* Build up the driver status structure. It will be passed back by
the notify on error routine
*/
pStatus->InterruptStatusRegister[0] = pRegs->IntStatus[0];
pStatus->InterruptStatusRegister[1] = pRegs->IntStatus[1];
pStatus->ChaAssignmentStatusRegister[0] = pRegs->ChaAssignmentStatus[0];
pStatus->ChaAssignmentStatusRegister[1] = pRegs->ChaAssignmentStatus[1];
for (channel=0; channel<NUM_CHANNELS; channel++)
{
pStatus->ChannelStatusRegister[channel][0] = pRegs->ChannelError[channel][0];
pStatus->ChannelStatusRegister[channel][1] = pRegs->ChannelError[channel][1];
}
for (cha=0; cha<NUM_CHAS; cha++)
{
pStatus->CHAInterruptStatusRegister[cha][0] = pRegs->ChaError[cha][0];
pStatus->CHAInterruptStatusRegister[cha][1] = pRegs->ChaError[cha][1];
}
}