📄 c64xx_pci.c
字号:
*/
static Int mdSubmitChan(Ptr chanp, IOM_Packet *pPacket)
{
ChanHandle chan = (ChanHandle)chanp;
IOM_Packet* packet = pPacket;
Uns imask;
C64XX_PCI_Request *req;
C64XX_PCI_Request *curReq;
req = (C64XX_PCI_Request *)packet->addr;
req->reserved = chan;
/* IOM_READ or IOM_WRITE command handle in the same way */
if (packet->cmd == IOM_READ || packet->cmd == IOM_WRITE) {
imask = HWI_disable();
QUE_enqueue(chan->queue, packet);
if (device.curPacket == NULL) {
#ifndef TEST_RESET
processQueue();
#endif
}
HWI_restore(imask);
return (IOM_PENDING);
}
if (packet->cmd == IOM_FLUSH || packet->cmd == IOM_ABORT) {
imask = HWI_disable();
chan->flushAbortIop = packet;
/* check the channel of pending packet */
if (device.curPacket != NULL) {
curReq = (C64XX_PCI_Request *)device.curPacket->addr;
/* The pending packet is this channel. Let isr handles it */
if ((ChanHandle)curReq->reserved == chan) {
HWI_restore(imask);
return (IOM_PENDING);
}
}
/* the pending packet is not FLUSH/ABORT channel */
removePackets(chan, packet->cmd);
/* FLUSH/ABORT done */
if (chan->writeCount == 0) {
chan->flushAbortIop = NULL;
HWI_restore(imask);
return (IOM_COMPLETED);
}
HWI_restore(imask);
return (IOM_PENDING);
}
return (IOM_EBADIO);
}
/*
* ======== mdUnBindDev ========
* return status
*/
static Int mdUnBindDev(Ptr devp)
{
/* empty for now */
return (IOM_COMPLETED);
}
/*
* ======== C64XX_PCI_init ========
*/
Void C64XX_PCI_init(Void)
{
/* empty for now */
}
/*
* ======== isr ========
* interrupt service routine is runtime pluged in
*/
static Void isr(Void)
{
ChanHandle chan;
IOM_Packet *oldPacket;
C64XX_PCI_Request *oldReq;
Int status = IOM_EBADIO;
if (PCI_FGET(PCIIS, MASTEROK)) {
/* pci master transfer complete */
PCI_FSET(PCIIS, MASTEROK, 1);
status = IOM_COMPLETED;
}
else if (PCI_FGET(PCIIS, PCIMASTER)) {
/* pci master abort */
PCI_FSET(PCIIS, PCIMASTER, 1);
}
else if (PCI_FGET(PCIIS, PCITARGET)) {
/* pci target abort */
PCI_FSET(PCIIS, PCITARGET, 1);
}
else {
/* not registered interrupt, clear intr here */
PCI_RSET(PCIIS, 0x00000FFF);
/* error handling TBD */
return;
}
if (device.curPacket != NULL) {
oldPacket = device.curPacket;
oldReq = (C64XX_PCI_Request *)oldPacket->addr;
chan = (ChanHandle)oldReq->reserved;
device.curPacket = NULL;
if (chan->flushAbortIop == NULL) {
/* normal. process next request in the queues */
processQueue();
/* callback */
CALLBACK(chan,oldPacket,status);
return;
}
/* flush or abort cmd */
/* first do callback */
CALLBACK(chan,oldPacket,status);
if (chan->writeCount) {
chan->writeCount--;
}
else {
removePackets(chan, chan->flushAbortIop->cmd);
}
/* process next request in the queues */
processQueue();
/* if all write IOPs are done, call the callback for the FLUSH IOP */
if (chan->writeCount == 0) {
CALLBACK(chan,chan->flushAbortIop,IOM_COMPLETED);
chan->flushAbortIop = NULL;
}
return;
}
/* process next request in the queues */
processQueue();
}
/*
* ======== pciErrorIsr ========
* interrupt service routine is runtime pluged in for asynchronous error TBD
*/
#ifdef PCI_ERROR_ISR_IMPL
static Void pciErrorIsr(Void)
{
/* How to check PCI status register to identify the error source --
parity/system: TBD (on C6416, not accessable) use 'event' here to
represent the status register related content */
Bool report = FALSE;
Uns error = 0;
C64XX_PCI_Request *req;
IOM_Packet *packet;
if (device.errCallback == NULL) {
return;
}
if ((event == C64XX_PCI_EVT_PARITY_ERR) &&
(device.evtMask & C64XX_PCI_EVT_PARITY_ERR)) {
error = error | C64XX_PCI_EVT_PARITY_ERR;
report = TRUE;
}
else if ((event == C64XX_PCI_EVT_SYSTEM_ERR) &&
(device.evtMask & C64XX_PCI_EVT_SYSTEM_ERR)) {
error = error | C64XX_PCI_EVT_SYSTEM_ERR;
report = TRUE;
}
if (!report) {
return;
}
if (device.curPacket != NULL) {
packet = device.curPacket;
req = (C64XX_PCI_Request *)packet->addr;
device.errInfo->inprogressDstAddr = req->dstAddr;
device.errInfo->inprogressSrcAddr = req->srcAddr;
device.errInfo->statusReg = PCI_STATUS_REGISTER;
}
else {
device.errInfo->inprogressDstAddr = NULL;
device.errInfo->inprogressSrcAddr = NULL;
device.errInfo->statusReg = PCI_STATUS_REGISTER;
}
(device.errCallback)(error, (Ptr)device.errorInfo);
}
#endif
/*
* ======== doTransfer ========
*/
static Void doTransfer(C64XX_PCI_Request *request)
{
C64XX_PCI_Request *req = request;
PCI_ConfigXfr config;
Uns xfrMode;
xfrMode = C64XX_PCI_GETXFERMODE(request->options);
if (xfrMode == PCI_WRITE) {
config.dspma = (Uns)req->srcAddr;
config.pcima = (Uns)req->dstAddr;
config.pcimc = GET_BYTE_COUNT(req->byteCnt);
}
else if (xfrMode == PCI_READ_PREF || xfrMode == PCI_READ_NOPREF) {
config.dspma = (Uns)req->dstAddr;
config.pcima = (Uns)req->srcAddr;
config.pcimc = GET_BYTE_COUNT(req->byteCnt);
}
PCI_xfrConfig(&config);
PCI_xfrStart(xfrMode);
}
/*
* ======== processQueue ========
*/
static Void processQueue()
{
QUE_Handle que;
C64XX_PCI_Request *req;
que = &device.highPrioQue;
/* process next packet in queue */
if (QUE_empty(que)) {
que = &device.lowPrioQue;
if (QUE_empty(que)) {
return;
}
}
device.curPacket = QUE_dequeue(que);
req = (C64XX_PCI_Request *)device.curPacket->addr;
doTransfer(req);
}
/*
* ======== removePackets ========
*/
static Void removePackets(Ptr chanp, Int cmd)
{
ChanHandle chan = (ChanHandle)chanp;
QUE_Elem *next;
QUE_Elem *current;
C64XX_PCI_Request *curReq;
Int status;
if (cmd != IOM_FLUSH && cmd != IOM_ABORT) {
return;
}
current = QUE_head(chan->queue);
curReq = (C64XX_PCI_Request *)((IOM_Packet *)current)->addr;
while (chan->queue != current) {
next = QUE_next(current);
/* check the channel of the each IOM_Packet in the queue */
/* find the match. The packet and remove channels are identical */
if ((ChanHandle)curReq->reserved == chan) {
/* for write flush wait for complete */
if ( cmd == IOM_FLUSH &&
((IOM_Packet *)current)->cmd == IOM_WRITE ) {
chan->writeCount++;
} else {
/* for read flush or abort, do flush */
if (cmd == IOM_FLUSH) {
status = IOM_FLUSHED;
}
else {
status = IOM_ABORTED;
}
QUE_remove(current);
CALLBACK(chan, (IOM_Packet *)current, status);
}
}
current = next;
curReq = (C64XX_PCI_Request*)((IOM_Packet *)current)->addr;
} /* end while */
}
/*
* ======== resetChannel ========
*/
static Void resetChannel(Ptr chanp)
{
ChanHandle chan = (ChanHandle)chanp;
C64XX_PCI_Request *curReq;
Uns imask;
imask = HWI_disable();
/* assume reset async ? */
if (device.curPacket != NULL) {
curReq = (C64XX_PCI_Request *)((IOM_Packet *)device.curPacket)->addr;
if ((ChanHandle)curReq->reserved == chan) {
CALLBACK((ChanHandle)curReq->reserved,
(IOM_Packet *)device.curPacket, IOM_ABORTED);
device.curPacket = NULL;
}
}
removePackets(chanp, IOM_ABORT);
HWI_restore(imask);
}
/*
* ======== resetDevice ========
*/
static Void resetDevice()
{
QUE_Elem *next;
QUE_Elem *current;
QUE_Handle queue;
C64XX_PCI_Request *curReq;
Int i;
Uns imask;
imask = HWI_disable();
/* assume reset async ? */
if (device.curPacket != NULL) {
curReq = (C64XX_PCI_Request *)((IOM_Packet *)device.curPacket)->addr;
CALLBACK((ChanHandle)curReq->reserved,
(IOM_Packet *)device.curPacket, IOM_ABORTED);
device.curPacket = NULL;
}
for (i = 0; i < 2; i++) {
if (i == 0 ) {
queue = &device.highPrioQue;
}
else {
queue = &device.lowPrioQue;
}
/* remove all the elements in the high/low priority queue */
current = QUE_head(queue);
curReq = (C64XX_PCI_Request *)((IOM_Packet *)current)->addr;
while (queue != current) {
next = QUE_next(current);
QUE_remove(current);
CALLBACK((ChanHandle)curReq->reserved,
(IOM_Packet *)current, IOM_ABORTED);
current = next;
curReq = (C64XX_PCI_Request*)((IOM_Packet *)current)->addr;
} /* end while */
} /* end for */
HWI_restore(imask);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -