📄 rclanmtl.c
字号:
pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; pMsg[3] = ResourceFlags << 16; /* resource flags */ pPab->p_atu->InQueue = off; /* send it to the I2O device */ if (CallbackFunction == (PFNCALLBACK) NULL) { /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc or until timer goes off */ while (pPab->pCallbackFunc == (PFNCALLBACK) NULL) { RCProcI2OMsgQ (dev); mdelay (1); timeout++; if (timeout > 200) { dprintk (KERN_WARNING "RCShutdownLANCard(): timeout\n"); break; } } if (ReturnAddr != (PU32) NULL) *ReturnAddr = (U32) pPab->pCallbackFunc; } return RC_RTN_NO_ERROR;}/*** =========================================================================** RCSetRavlinIPandMask()**** Set the Ravlin 45/PCI cards IP address and network mask.**** IP address and mask must be in network byte order.** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be** 0x04030201 and 0x00FFFFFF on a little endian machine.**** =========================================================================*/RC_RETURNRCSetRavlinIPandMask (struct net_device * dev, U32 ipAddr, U32 netMask){ volatile PU32 pMsg; U32 off; PPAB pPab = ((PDPA) dev->priv)->pPab; if (pPab == NULL) return RC_RTN_ADPTR_NOT_REGISTERED; off = pPab->p_atu->InQueue; /* get addresss of message */ if (0xFFFFFFFF == off) return RC_RTN_FREE_Q_EMPTY; pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); /* setup private message */ pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0; pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; pMsg[2] = 0; /* initiator context */ pMsg[3] = 0x219; /* transaction context */ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK; pMsg[5] = ipAddr; pMsg[6] = netMask; pPab->p_atu->InQueue = off; /* send it to the I2O device */ return RC_RTN_NO_ERROR;}/*** =========================================================================** RCGetRavlinIPandMask()**** get the IP address and MASK from the card** ** =========================================================================*/RC_RETURNRCGetRavlinIPandMask (struct net_device * dev, PU32 pIpAddr, PU32 pNetMask, PFNWAITCALLBACK WaitCallback){ U32 off, i; PU32 pMsg, p32; PPAB pPab = ((PDPA) dev->priv)->pPab; PATU p_atu; dprintk ("RCGetRavlinIPandMask: pIpAddr is 0x%x, *IpAddr is 0x%x\n", (u32) pIpAddr, *pIpAddr); if (pPab == NULL) return RC_RTN_ADPTR_NOT_REGISTERED; p_atu = pPab->p_atu; off = p_atu->InQueue; /* get addresss of message */ if (0xFFFFFFFF == off) return RC_RTN_FREE_Q_EMPTY; p32 = (volatile PU32) pPab->pLinOutMsgBlock; *p32 = 0xFFFFFFFF; pMsg = (PU32) (pPab->pPci45LinBaseAddr + off); dprintk ("RCGetRavlinIPandMask: p_atu 0x%x, off 0x%x, p32 0x%x\n", (u32) p_atu, off, (u32) p32); /* setup private message */ pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID; pMsg[2] = 0; /* initiator context */ pMsg[3] = 0x218; /* transaction context */ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK; pMsg[5] = pPab->outMsgBlockPhyAddr; p_atu->InQueue = off; /* send it to the I2O device */ dprintk ("RCGetRavlinIPandMask: p_atu 0x%x, off 0x%x, p32 0x%x\n", (u32) p_atu, off, (u32) p32); /* wait for the rcpci45 board to update the info */ i = 0; while (0xffffffff == *p32) { if (i++ > 0xff) { dprintk ("RCGetRavlinIPandMask: Timeout\n"); return RC_RTN_MSG_REPLY_TIMEOUT; } udelay(50); } dprintk ("RCGetRavlinIPandMask: after time out\np32[0] (IpAddr) 0x%x, p32[1] (IPmask) 0x%x\n", p32[0], p32[1]); /* send IP and mask to user's space */ *pIpAddr = p32[0]; *pNetMask = p32[1]; dprintk ("RCGetRavlinIPandMask: pIpAddr is 0x%x, *IpAddr is 0x%x\n", (u32) pIpAddr, *pIpAddr); return RC_RTN_NO_ERROR;}/* ** /////////////////////////////////////////////////////////////////////////** /////////////////////////////////////////////////////////////////////////**** local functions**** /////////////////////////////////////////////////////////////////////////** /////////////////////////////////////////////////////////////////////////*//*** =========================================================================** SendI2OOutboundQInitMsg()**** =========================================================================*/static intSendI2OOutboundQInitMsg (PPAB pPab){ U32 msgOffset, phyOutQFrames, i; volatile PU32 pMsg; volatile PU32 p32; msgOffset = pPab->p_atu->InQueue; if (msgOffset == 0xFFFFFFFF) { dprintk ("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n"); return RC_RTN_FREE_Q_EMPTY; } /* calc virtual address of msg - virtual already mapped to physical */ pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); dprintk ("SendI2OOutboundQInitMsg - pMsg = 0x%x, InQ msgOffset = 0x%x\n", (u32) pMsg, msgOffset); pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6; pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; pMsg[3] = 0x106; /* transaction context */ pMsg[4] = 4096; /* Host page frame size */ pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; /* outbound msg frame size and Initcode */ pMsg[6] = 0xD0000004; /* simple sgl element LE, EOB */ /* phys address to return status - area right after PAB */ pMsg[7] = pPab->outMsgBlockPhyAddr; /* virtual pointer to return buffer - clear first two dwords */ p32 = (PU32) pPab->pLinOutMsgBlock; p32[0] = 0; /* post to Inbound Post Q */ pPab->p_atu->InQueue = msgOffset; /* wait for response */ i = 0; while (!p32[0]) { if (i++ > 0xff) { printk("rc: InitOutQ timeout\n"); return RC_RTN_NO_I2O_STATUS; } udelay(50); } if (p32[0] != I2O_EXEC_OUTBOUND_INIT_COMPLETE) { printk("rc: exec outbound init failed (%x)\n", p32[0]); return RC_RTN_NO_I2O_STATUS; } /* load PCI outbound free Q with MF physical addresses */ phyOutQFrames = pPab->outMsgBlockPhyAddr; for (i = 0; i < NMBR_MSG_FRAMES; i++) { pPab->p_atu->OutQueue = phyOutQFrames; phyOutQFrames += MSG_FRAME_SIZE; } return RC_RTN_NO_ERROR;}/*** =========================================================================** GetI2OStatus()**** Send StatusGet Msg, wait for results return directly to buffer.**** =========================================================================*/static intGetI2OStatus (PPAB pPab){ U32 msgOffset, i; PU32 pMsg; volatile PU32 p32; msgOffset = pPab->p_atu->InQueue; dprintk ("GetI2OStatus: msg offset = 0x%x\n", msgOffset); if (msgOffset == 0xFFFFFFFF) { dprintk ("GetI2OStatus(): Inbound Free Q empty!\n"); return RC_RTN_FREE_Q_EMPTY; } /* calc virtual address of msg - virtual already mapped to physical */ pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0; pMsg[1] = I2O_EXEC_STATUS_GET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; pMsg[2] = 0; /* universal context */ pMsg[3] = 0; /* universal context */ pMsg[4] = 0; /* universal context */ pMsg[5] = 0; /* universal context */ /* phys address to return status - area right after PAB */ pMsg[6] = pPab->outMsgBlockPhyAddr; pMsg[7] = 0; pMsg[8] = 88; /* return 88 bytes */ /* virtual pointer to return buffer - clear first two dwords */ p32 = (volatile PU32) pPab->pLinOutMsgBlock; p32[0] = 0; p32[1] = 0; dprintk ("GetI2OStatus - pMsg:0x%x, msgOffset:0x%x, [1]:0x%x, [6]:0x%x\n", (u32) pMsg, msgOffset, pMsg[1], pMsg[6]); /* post to Inbound Post Q */ pPab->p_atu->InQueue = msgOffset; dprintk ("Return status to p32 = 0x%x\n", (u32) p32); /* wait for response */ i = 0; while (!p32[0] || !p32[1]) { if (i++ > 0xff) { dprintk ("Timeout waiting for status from IOP\n"); return RC_RTN_NO_I2O_STATUS; } udelay(50); } dprintk ("0x%x:0x%x:0x%x:0x%x\n", p32[0], p32[1], p32[2], p32[3]); dprintk ("0x%x:0x%x:0x%x:0x%x\n", p32[4], p32[5], p32[6], p32[7]); dprintk ("0x%x:0x%x:0x%x:0x%x\n", p32[8], p32[9], p32[10], p32[11]); /* get IOP state */ pPab->IOPState = ((volatile PU8) p32)[10]; pPab->InboundMFrameSize = ((volatile PU16) p32)[6]; dprintk ("IOP state 0x%x InFrameSize = 0x%x\n", pPab->IOPState, pPab->InboundMFrameSize); return RC_RTN_NO_ERROR;}/*** =========================================================================** SendEnableSysMsg()****** =========================================================================*/static intSendEnableSysMsg (PPAB pPab){ U32 msgOffset; volatile PU32 pMsg; msgOffset = pPab->p_atu->InQueue; if (msgOffset == 0xFFFFFFFF) { dprintk ("SendEnableSysMsg(): Inbound Free Q empty!\n"); return RC_RTN_FREE_Q_EMPTY; } /* calc virtual address of msg - virtual already mapped to physical */ pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset); dprintk ("SendEnableSysMsg - pMsg = 0x%x, InQ msgOffset = 0x%x\n", (u32) pMsg, msgOffset); pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0; pMsg[1] = I2O_EXEC_SYS_ENABLE << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID; pMsg[2] = DEFAULT_RECV_INIT_CONTEXT; pMsg[3] = 0x110; /* transaction context */ pMsg[4] = 0x50657465; /* RedCreek Private */ /* post to Inbound Post Q */ pPab->p_atu->InQueue = msgOffset; return RC_RTN_NO_ERROR;}/*** =========================================================================** FillI2OMsgFromTCB()**** inputs pMsgU32 - virtual pointer (mapped to physical) of message frame** pXmitCntrlBlock - pointer to caller buffer control block.**** fills in LAN SGL after Transaction Control Word or Bucket Count.** =========================================================================*/static intFillI2OMsgSGLFromTCB (PU32 pMsgFrame, PRCTCB pTransCtrlBlock){ unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags; PU32 pTCB, pMsg; /* SGL element flags */#define EOB 0x40000000#define LE 0x80000000#define SIMPLE_SGL 0x10000000#define BC_PRESENT 0x01000000 pTCB = (PU32) pTransCtrlBlock; pMsg = pMsgFrame; nmbrDwords = 0; dprintk ("FillI2OMsgSGLFromTCBX\n"); dprintk ("TCB 0x%x:0x%x:0x%x:0x%x:0x%x\n", pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]); dprintk ("pTCB 0x%x, pMsg 0x%x\n", (u32) pTCB, (u32) pMsg); nmbrBuffers = *pTCB++; if (!nmbrBuffers) { return -1; } do { context = *pTCB++; /* buffer tag (context) */ nmbrSeg = *pTCB++; /* number of segments */ if (!nmbrSeg) { return -1; } flags = SIMPLE_SGL | BC_PRESENT; if (1 == nmbrSeg) { flags |= EOB; if (1 == nmbrBuffers) flags |= LE; } /* 1st SGL buffer element has context */ pMsg[0] = pTCB[0] | flags; /* send over count (segment size) */ pMsg[1] = context; pMsg[2] = pTCB[1]; /* send buffer segment physical address */ nmbrDwords += 3; pMsg += 3; pTCB += 2; if (--nmbrSeg) { do { flags = SIMPLE_SGL; if (1 == nmbrSeg) { flags |= EOB; if (1 == nmbrBuffers) flags |= LE; } pMsg[0] = pTCB[0] | flags; /* send over count */ pMsg[1] = pTCB[1]; /* send buffer segment physical address */ nmbrDwords += 2; pTCB += 2; pMsg += 2; } while (--nmbrSeg); } } while (--nmbrBuffers); return nmbrDwords;}/*** =========================================================================** ProcessOutboundI2OMsg()**** process I2O reply message** * change to msg structure *** =========================================================================*/static voidProcessOutboundI2OMsg (PPAB pPab, U32 phyAddrMsg){ PU8 p8Msg; PU32 p32;/* U16 count; */ p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr); p32 = (PU32) p8Msg; dprintk ("VXD: ProcessOutboundI2OMsg - pPab 0x%x, phyAdr 0x%x, linAdr 0x%x\n", (u32) pPab, phyAddrMsg, (u32) p8Msg); dprintk ("msg :0x%x:0x%x:0x%x:0x%x\n", p32[0], p32[1], p32[2], p32[3]); dprintk ("msg :0x%x:0x%x:0x%x:0x%x\n", p32[4], p32[5], p32[6], p32[7]); if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS) { dprintk ("Message reply status not success\n"); return; } switch (p8Msg[7]) { /* function code byte */ case I2O_EXEC_SYS_TAB_SET: msgFlag = 1; dprintk ("Received I2O_EXEC_SYS_TAB_SET reply\n"); break; case I2O_EXEC_HRT_GET: msgFlag = 1; dprintk ("Received I2O_EXEC_HRT_GET reply\n"); break; case I2O_EXEC_LCT_NOTIFY: msgFlag = 1; dprintk ("Received I2O_EXEC_LCT_NOTIFY reply\n"); break; case I2O_EXEC_SYS_ENABLE: msgFlag = 1; dprintk ("Received I2O_EXEC_SYS_ENABLE reply\n"); break; default: dprintk ("Received UNKNOWN reply\n"); break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -