/***** Sample for UIRCC *****/ /***** Toshiba Confidential 1999/May/12 M.Tada *****/ /**** 1. Interrupt routine ****/ VOID FIR_ISR(IrDevice *thisDev) { UCHAR sts; UINT Len; PUCHAR newBuffer; PUCHAR *rcvTable; READ_IR_PORT( thisDev, SR3, &sts ); if( (sts & SR3_Rx_EOF) != 0 ) { // Get Packet Length. Len = FirGetReceiveLength(thisDev); if( Len == 0 ) { thisDev->packetsDropped++; FirDmaComplete(thisDev); FirDmaSetup(thisDev, DMA_Rx_MODE); return; } else { newBuffer = (PUCHAR)thisDev->resourceToReceive; newBuffer += thisDev->offsetToReceive; rcvTable = &newBuffer; QueueReceivePacket(thisDev, rcvTable, Len); /*** receive routine ***/ if( thisDev->offsetToReceive < (RCV_BUFFER_SIZE*(NUM_RCV_BUFS-1)) ) { if( Len % 2 ) thisDev->offsetToReceive += Len + 5; /*** add CRC 4 byte and adjust even number ***/ else thisDev->offsetToReceive += Len + 4; /*** add CRC 4 byte ***/ WRITE_IR_PORT(thisDev, CR0, CR0_Rx_RESET); return; } else { FirDmaComplete(thisDev); FirDmaSetup(thisDev, DMA_Rx_MODE); return; } } } if( ((sts & SR3_Rx_OVERRUN) !=0) || ((sts & SR3_Rx_FRAMING) !=0) ) { thisDev->packetsDropped++; if( FirDmaComplete(thisDev) != TRUE ) { DBGERR(("CompleteDmaError!!")); } FirDmaSetup(thisDev, DMA_Rx_MODE); return; } return; } //*** FIR_ISR ***************************************************************** UINT FirGetReceiveLength( IrDevice *thisDev ) { UCHAR LenLo, LenHi, CrcCheck; UINT Len; READ_IR_PORT(thisDev, SR0, &CrcCheck ); if( (CrcCheck & SR0_Rx_FRAMINGorCRC) != 0 ) Len = 0; else { READ_IR_PORT(thisDev, SR4, &LenLo ); READ_IR_PORT(thisDev, SR5, &LenHi ); Len = (UINT) LenHi; Len <<= 8; Len += (UINT)LenLo; if(Len < 4) Len = 0; else Len -= 4; // 4 = CRC } return(Len); } BOOLEAN FirDmaComplete(IrDevice *thisDev) { NDIS_STATUS status; PNDIS_BUFFER ndisBuffer; ULONG size; if( (thisDev->FirMode == TRUE) && (thisDev->dmaPending == TRUE) ) { if(thisDev->DownMode == DMA_Rx_MODE) { ndisBuffer = thisDev->bufferToReceive; size = RCV_BUFFER_SIZE * NUM_RCV_BUFS; } else { ndisBuffer = thisDev->bufferToSend; size = RCV_BUFFER_SIZE; thisDev->nowSending = FALSE; } NdisMCompleteDmaTransfer( &status, thisDev->NdisDmaHandle, ndisBuffer, (ULONG) 0, size, thisDev->DownMode ); if( status != NDIS_STATUS_SUCCESS) { DBGERR(("DmaComplete:%x",status)); return FALSE; } } thisDev->dmaPending = FALSE; return TRUE; } //*** FirDmaComplete ********************************************************** BOOLEAN FirDmaSetup(IrDevice *thisDev, BOOLEAN dmaMode) { NDIS_STATUS status; if( dmaMode == DMA_Tx_MODE ) { // // Send. // thisDev->DownMode = DMA_Tx_MODE; NdisMSetupDmaTransfer( &status, thisDev->NdisDmaHandle, thisDev->bufferToSend, (ULONG) 0, (ULONG) SND_BUFFER_SIZE, thisDev->DownMode ); thisDev->dmaPending = TRUE; } else { // // Receive. // thisDev->nowSending = FALSE; thisDev->DownMode = DMA_Rx_MODE; thisDev->offsetToReceive = 0; NdisMSetupDmaTransfer( &status, thisDev->NdisDmaHandle, thisDev->bufferToReceive, (ULONG) 0, (ULONG) RCV_BUFFER_SIZE * NUM_RCV_BUFS, thisDev->DownMode ); thisDev->dmaPending = TRUE; // Start Receive. WRITE_IR_PORT( thisDev, CR3, 0 ); WRITE_IR_PORT( thisDev, CR3, CR3_Rx_EN | CR3_Rx_CRCEN ); } return TRUE; } /**** 2. Send routine ****/ VOID SendPacketsHandler( UINT NumberofPackets) { NDIS_STATUS stat; UINT i; UINT sendPacket; if( thisDev->FirMode == TRUE ) { thisDev->nowSending = TRUE; // Now Sending. FirDmaComplete(thisDev); // Stop DMAC(RxMode). FirDmaSetup(thisDev, DMA_Tx_MODE ); // Start DMAC(TxMode). thisDev->offsetToSend = 0; // // Send Packets. // sendPacket = 0; do { UINT packetsNum = (NumberofPackets>NUM_SND_BUFS) ? NUM_SND_BUFS:NumberofPackets; for (i = 0; i < packetsNum; i++) { stat = SendFirMode(thisDev, PacketArray[sendPacket]); } NumberofPackets -= packetsNum; } while( NumberofPackets > 0 ); thisDev->nowSending = FALSE; // Do not Sending. FirDmaComplete(thisDev); // Stop DMAC(TxMode). FirDmaSetup(thisDev, DMA_Rx_MODE ); // Start DMAC(RxMode). } else { /*** Send on UART (SIR) ***/ } } return; } //*** SendPacketsHandler ****************************************************** BOOLEAN SendFirMode(IrDevice *thisDev, PNDIS_PACKET packetToSend) { PNDIS_IRDA_PACKET_INFO packetInfo; UCHAR sts; UINT i; // // Enforce the minimum turnaround time that must transpire // after the last receive. // packetInfo = GetPacketInfo(packetToSend); if (packetInfo->MinTurnAroundTime) { // // Don't want to call NdisStallExecution with more than // 8 msec or it will cause a task switch. // Make a series of calls with 8 msec or less. // UINT usecToWait = packetInfo->MinTurnAroundTime; do { UINT usec = (usecToWait > 8000) ? 8000 : usecToWait; NdisStallExecution(usec); usecToWait -= usec; } while (usecToWait > 0); } // // See if this was the last packet before we need to change speed. // if (packetToSend == thisDev->lastPacketAtOldSpeed) { thisDev->lastPacketAtOldSpeed = NULL; thisDev->setSpeedAfterCurrentSendPacket = TRUE; } // // Send one packet to the DMA. // DoSendFir(thisDev, packetToSend); for(i=0; i < thisDev->portCheckCount; i++) { READ_IR_PORT( thisDev, SR0, &sts ); if( (sts & SR0_Tx_ALLSENT) || (sts & SR0_TxUNDERRUN) || (sts & SR0_Rx_FRAMINGorCRC) ) { break; } } // // If we just sent the last frame to be sent at the old speed, // set the hardware to the new speed. // if (thisDev->setSpeedAfterCurrentSendPacket) { thisDev->setSpeedAfterCurrentSendPacket = FALSE; SetSpeed(thisDev); } return TRUE; } //*** SendFirMode ************************************************************* VOID DoSendFir(IrDevice *thisDev, PNDIS_PACKET packetToSend) { UINT bytesCopied=0; UCHAR crBuf; PUCHAR tmp; // // Copy the packet contents into our transmit buffer. // tmp = (PUCHAR)thisDev->resourceToSend; tmp += thisDev->offsetToSend; CopyPacketToBuffer( packetToSend, (PVOID)tmp, &bytesCopied ); if(bytesCopied % 2) { thisDev->offsetToSend += bytesCopied + 1; } else { thisDev->offsetToSend += bytesCopied; } // // Set Packet Length. // crBuf = (UCHAR)bytesCopied; WRITE_IR_PORT( thisDev, CR4, crBuf ); crBuf = (UCHAR)(bytesCopied>>8); WRITE_IR_PORT( thisDev, CR5, crBuf ); // // Start Send. // WRITE_IR_PORT( thisDev, CR3, 0 ); WRITE_IR_PORT( thisDev, CR3, CR3_Tx_EN | CR3_Tx_CRCEN ); return; } //*** DoSendFir *************************************************************** /**** 3. Change Mode FIR <-> SIR ****/ VOID FirChangeMode( IrDevice *thisDev, BOOLEAN mode ) { UCHAR sts; if( mode == FIR_MODE ) { if(thisDev->FirMode == TRUE) return; // // Interrupt signal is changed from UART to UIRCC. // _asm { push ax push bx push cx cli mov ah, 0FFh mov bx, 001Bh mov cx, 0001h in al, 0B2h mov [sts], ah sti pop cx pop bx pop ax } thisDev->FirMode = TRUE; thisDev->nowSending = FALSE; thisDev->dmaPending = FALSE; // reset. WRITE_IR_PORT( thisDev, CR0, CR0_CHANNEL_RESET ); WRITE_IR_PORT( thisDev, CR1, CR1_Rx_DMA | CR1_Tx_DMA | CR1_ALWAYS ); WRITE_IR_PORT( thisDev, CR2, CR2_EN_INT); WRITE_IR_PORT( thisDev, CR9, 1); WRITE_IR_PORT( thisDev, CR10, CR10_4MFIRTx_SEL | CR10_4MFIRRx_SEL ); WRITE_IR_PORT( thisDev, CR11, CR11_SINGLE_OUTPUT_EN | CR11_IRRX_REVERSE ); WRITE_IR_PORT( thisDev, CR15, thisDev->irChannel ); FirDmaSetup(thisDev, DMA_Rx_MODE); } else { WRITE_IR_PORT( thisDev, CR2, CR2_INT_MSK ); WRITE_IR_PORT( thisDev, CR3, 0 ); WRITE_IR_PORT( thisDev, CR0, CR0_CHANNEL_RESET ); // // Stop DMAC // WRITE_IR_PORT( thisDev, CR9, 1); // Select SIR WRITE_IR_PORT( thisDev, CR10, CR10_SIRTx_SEL | CR10_SIRRx_SEL ); WRITE_IR_PORT( thisDev, CR11, CR11_SINGLE_OUTPUT_EN | CR11_IRRX_REVERSE ); WRITE_IR_PORT( thisDev, CR15, thisDev->irChannel ); // // Interrupt signal is changed from UIRCC to UART. // _asm { push ax push bx push cx cli mov ah, 0FFh mov bx, 001Bh mov cx, 0000h in al, 0B2h mov [sts], ah sti pop cx pop bx pop ax } thisDev->FirMode = FALSE; thisDev->nowSending = FALSE; } return; } //*** FirChangeMode *********************************************************** /**** 4. Header ****/ #define CR0 0 #define CR1 1 #define CR2 2 #define CR3 3 #define CR4 4 #define CR5 5 #define CR6 6 #define CR7 7 #define CR8 8 #define CR9 9 #define CR10 10 #define CR11 11 #define CR12 12 #define CR13 13 #define CR14 14 #define CR15 15 #define SR0 0 #define SR1 1 #define SR2 2 #define SR3 3 #define SR4 4 #define SR5 5 #define SR6 6 #define SR7 7 #define SR8 8 #define SR9 9 #define SR10 10 #define SR11 11 #define SR12 12 #define SR13 13 #define SR14 14 #define SR15 15 // CR0 #define CR0_Tx_RESET 0x20 #define CR0_Rx_RESET 0x10 #define CR0_TIMER_RESET 8 #define CR0_CHANNEL_RESET 4 #define CR0_CARRIERSENSE_RESET 2 #define CR0_TxRxCOUNTER_SEL 1 // CR1 #define CR1_Rx_DMA 0x80 #define CR1_Tx_DMA 0x20 #define CR1_DMA_BURST 0x10 #define CR1_CRC_INITVALUE 8 #define CR1_FLAG 4 #define CR1_ALWAYS 0x0C // CR2 #define CR2_INT_MSK 0x7D #define CR2_Rx_OVERRUN 0x40 #define CR2_Rx_FRAMING 0x20 #define CR2_Rx_EOF 0x10 #define CR2_TIMER_TIMEOUT 8 #define CR2_Tx_UNDERRUN 4 #define CR2_Tx_ALLSENT 1 #define CR2_EN_INT 0x0D // CR3 extern volatile int uircc_cr3; #define CR3_SET(c){\ _uircc_cr3 |= (c);\ WRITE_IR_PORT(thisDev, CR3, _uircc_cr3);\ } #define CR3_RESET(c){\ _uircc_cr3 &= ~(c);\ WRITE_IR_PORT(thisDev, CR3, _uircc_cr3);\ } #define CR3_Tx_EN 0x80 #define CR3_Tx_CRCEN 0x40 #define CR3_Rx_EN 0x20 #define CR3_Rx_CRCEN 0x10 #define CR3_ADDRESS_EN 8 #define CR3_MULTICAST_EN 4 // CR9 #define CR9_SEL_IRRX2_FIR1M 0x80 #define CR9_SEL_IRRX2_SIR 0x20 #define CR9_SEL_IRRX2_ASK 0x10 // CR10 #define CR10_4MFIRTx_SEL 0x80 #define CR10_1MFIRTx_SEL 0x40 #define CR10_SIRTx_SEL 0x20 #define CR10_ASKTx_SEL 0x10 #define CR10_4MFIRRx_SEL 8 #define CR10_1MFIRRx_SEL 4 #define CR10_SIRRx_SEL 2 #define CR10_ASKRx_SEL 1 // CR11 #define CR11_SINGLE_OUTPUT_EN 0x80 #define CR11_IRRX_REVERSE 0x10 #define CR11_TIMER_EN 8 #define CR11_LOOPBACK 1 // CR15 #define CR15_A_CHANNEL_EN 2 #define CR15_B_CHANNEL_EN 1 // SR0 #define SR0_Rx_AVAILABLE 0x80 #define SR0_Rx_OVERRUN 0x40 #define SR0_Rx_FRAMINGorCRC 0x20 #define SR0_RxEOF 0x10 #define SR0_TxNOTFULL 8 #define SR0_TxUNDERRUN 4 #define SR0_4MPACKETBUSY 2 #define SR0_Tx_ALLSENT 1 #define SR0_Tx_DONE 5 #define SR0_Rx_DONE 0x70 // SR1 #define SR1_UNMASK 2 #define SR1_CARRIERSENSE 2 // SR2 #define SR2_UNMASK 0x7D #define SR2_ALWAYS1 0x82 // SR3 #define SR3_UNMASK 0x7D #define SR3_Rx_OVERRUN 0x40 #define SR3_Rx_FRAMING 0x20 #define SR3_Rx_EOF 0x10 #define SR3_TIMER_TIMEOUT 8 #define SR3_Tx_UNDERRUN 4 #define SR3_Tx_ALLSENT 1 #define SR3_Tx_INT 5 #define SR3_Rx_INT 0x70 // SR9 #define SR9_UNMASK 0x71 #define SR9_IRRX2FIR1M 0x40 #define SR9_IRRX2SIR 0x20 #define SR9_IRRX2ASK 0x10 #define SR9_MCLK16M 0 #define SR9_MCLK24M 2 #define SR9_MCLK32M 4 #define SR9_MCLK48M 6 #define SR9_SIP 1 //SR10 #define SR10_4MFIRTx_SEL 0x80 #define SR10_1MFIRTx_SEL 0x40 #define SR10_SIRTx_SEL 0x20 #define SR10_ASKTx_SEL 0x10 #define SR10_4MFIRRx_SEL 8 #define SR10_1MFIRRx_SEL 4 #define SR10_SIRRx_SEL 2 #define SR10_ASKRx_SEL 1 // SR11 #define SR11_UNMASK 0xDB #define SR11_SINGLE_OUTPUT_EN 0x80 #define SR11_SINGLE_PIN 0x40 #define SR11_IRRX_REVERSE 0x10 #define SR11_TIMER_EN 8 #define SR11_TIMER_1US 2 #define SR11_LOOP 1 #define NUM_SND_BUFS 7