/*------------------------------------------------------------------------ * e1000_txPackets - handler for transmitter interrupts *------------------------------------------------------------------------ */ local void e1000_txPackets( struct ether *ethptr /* ptr to control block */ ) { struct e1000_tx_desc *descptr;/* ptr to ring descriptor */ uint32 head; /* pos to reclaim descriptor */ char *pktptr; /* ptr used during packet copy */ int numdesc; /* num. of descriptor reclaimed */ for (numdesc = 0; numdesc < ethptr->txRingSize; numdesc++) { head = ethptr->txHead; descptr = (struct e1000_tx_desc *)ethptr->txRing + head; if (!(descptr->upper.data & E1000_TXD_STAT_DD)) break; /* Clear the write-back descriptor and buffer */ descptr->lower.data = 0; descptr->upper.data = 0; pktptr = (char *)((uint32)(descptr->buffer_addr & ADDR_BIT_MASK)); memset(pktptr, '\0', ETH_BUF_SIZE); ethptr->txHead = (ethptr->txHead + 1) % ethptr->txRingSize; } signaln(ethptr->osem, numdesc); return; }
/*------------------------------------------------------------------------ * e1000_rxPackets - handler for receiver interrupts *------------------------------------------------------------------------ */ local void e1000_rxPackets( struct ether *ethptr /* ptr to control block */ ) { struct e1000_rx_desc *descptr;/* ptr to ring descriptor */ uint32 tail; /* pos to insert next packet */ uint32 status; /* status of ring descriptor */ int numdesc; /* num. of descriptor reclaimed */ for (numdesc = 0; numdesc < ethptr->rxRingSize; numdesc++) { /* Insert new arrived packet to the tail */ tail = ethptr->rxTail; descptr = (struct e1000_rx_desc *)ethptr->rxRing + tail; status = descptr->status; if (status == 0) { break; } ethptr->rxTail = (ethptr->rxTail + 1) % ethptr->rxRingSize; } signaln(ethptr->isem, numdesc); return; }
//------------------------------------------------------------------------ // ttyoin -- lower-half tty device driver for output interrupts //------------------------------------------------------------------------ void ttyoin(struct tty *iptr) { struct csr *cptr; int ct; cptr = iptr->ioaddr; if (iptr->ehead != iptr->etail) { cptr->tbufa = iptr->ebuff[iptr->etail++]; if (iptr->etail >= EBUFLEN) iptr->etail = 0; return; } if (iptr->oheld) { // honor flow control iptr->imr &= ~DUART_TxINTABLE; cptr->imr = iptr->imr; return; } if ((ct = scount(iptr->osem)) >= OBUFLEN) { iptr->imr &= ~DUART_TxINTABLE; cptr->imr = iptr->imr; return; } cptr->tbufa = iptr->obuff[iptr->otail++]; if (iptr->otail >= OBUFLEN) iptr->otail = 0; if (ct > OBMINSP) signal(iptr->osem); else if (++(iptr->odsend) == OBMINSP) { iptr->odsend = 0; signaln(iptr->osem, OBMINSP); } }
void e100_rxPackets(struct ether *ethptr){ struct e100_rx_desc *descptr; uint32 tail; /* pos to insert next packet */ uint32 status; /* status of ring descriptor */ int numdesc; /* num. of descriptor reclaimed */ //kprintf("Enter e100_rxPackets\r\n"); for (numdesc = 0; numdesc < E100_BLK_PER_INT; numdesc++) { /* Insert new arrived packet to the tail */ tail = ethptr->rxTail; descptr = (struct e100_rx_desc *)ethptr->rxRing + tail; status = descptr->status; if (!(status & cb_complete)) { break; } ethptr->rxTail = (ethptr->rxTail + 1) % ethptr->rxRingSize; } signaln(ethptr->isem, numdesc); return; }
/*------------------------------------------------------------------------ * ttyoin -- lower-half tty device driver for output interrupts *------------------------------------------------------------------------ */ INTPROC ttyoin( register struct tty *iptr ) { register struct csr *cptr; int ct; cptr = iptr->ioaddr; if ( iptr->ehead != iptr->etail ) { cptr->ctbuf = iptr->ebuff[iptr->etail++]; cptr->ctstat = cptr->ctstat | SLUREADYON; if ( iptr->etail >= EBUFLEN ) iptr->etail = 0; return; } if ( iptr->oheld ) { /* honor flow control */ cptr->ctstat = SLUDISABLE; return; } if ( ( ct = scount( iptr->osem ) ) < OBUFLEN ) { cptr->ctbuf = iptr->obuff[iptr->otail++]; cptr->ctstat = cptr->ctstat | SLUREADYON; if ( iptr->otail >= OBUFLEN ) iptr->otail = 0; if ( ct > OBMINSP ) signal( iptr->osem ); else if ( ++( iptr->odsend ) == OBMINSP ) { iptr->odsend = 0; signaln( iptr->osem, OBMINSP ); } } else { cptr->ctstat = SLUDISABLE; } return; }
/** * Receive packet interrupt handler. */ void rxPackets(struct ether *ethptr, struct ag71xx *nicptr) { struct dmaDescriptor *dmaptr; struct ethPktBuffer *pkt = NULL; int head = 0; while (1) { head = ethptr->rxHead % ETH_RX_RING_ENTRIES; dmaptr = ðptr->rxRing[head]; if (dmaptr->control & ETH_DESC_CTRL_EMPTY) { nicptr->rxStatus = RX_STAT_RECVD; break; } pkt = ethptr->rxBufs[head]; pkt->length = dmaptr->control & ETH_DESC_CTRL_LEN; if (ethptr->icount < ETH_IBLEN) { allocRxBuffer(ethptr, head); ethptr->in[(ethptr->istart + ethptr->icount) % ETH_IBLEN] = pkt; ethptr->icount++; signaln(ethptr->isema, 1); } else { ethptr->ovrrun++; bzero(pkt->buf, pkt->length); } ethptr->rxHead++; // Clear Rx interrupt. nicptr->rxStatus = RX_STAT_RECVD; // FIXME break; } }
int main(void *arg) { int sem, i; (void)arg; assert(screate(-2) == -1); assert((sem = screate(2)) >= 0); assert(signaln(sem, -4) < 0); assert(sreset(sem, -3) == -1); assert(scount(sem) == 2); assert(signaln(sem, 32760) == 0); assert(signaln(sem, 6) == -2); assert(scount(sem) == 32762); assert(wait(sem) == 0); assert(scount(sem) == 32761); assert(signaln(sem, 30000) == -2); assert(scount(sem) == 32761); assert(wait(sem) == 0); assert(scount(sem) == 32760); assert(signaln(sem, -2) < 0); assert(scount(sem) == 32760); assert(wait(sem) == 0); assert(scount(sem) == 32759); assert(signaln(sem, 8) == 0); assert(scount(sem) == 32767); assert(signaln(sem, 1) == -2); assert(scount(sem) == 32767); assert(signal(sem) == -2); assert(scount(sem) == 32767); for (i=0; i<32767; i++) { assert(wait(sem) == 0); } assert(try_wait(sem) == -3); assert(scount(sem) == 0); assert(sdelete(sem) == 0); printf("ok.\n"); }
/** * Decode hardware interrupt request from UART device. */ interrupt uartInterrupt(void) { int u = 0, iir = 0, lsr = 0, count = 0; char c; struct uart *uartptr = NULL; struct uart_csreg *regptr = NULL; resdefer = 1; /* deferral rescheduling. */ for (u = 0; u < NUART; u++) { uartptr = &uarttab[u]; if (NULL == uartptr) { continue; } regptr = (struct uart_csreg *)uartptr->csr; if (NULL == regptr) { continue; } /* Check interrupt identification register */ iir = regptr->iir; if (iir & UART_IIR_IRQ) { continue; } /* * Decode interrupt cause based upon the value taken from the * UART interrupt identification register. Clear interrupt source, * and perform the appropriate handling to coordinate properly * with the upper half of the driver. */ /* Decode interrupt cause */ iir &= UART_IIR_IDMASK; switch (iir) { /* Receiver line status interrupt */ case UART_IIR_RLSI: lsr = regptr->lsr; uartptr->lserr++; break; /* Receiver data available or timed out */ case UART_IIR_RDA: case UART_IIR_RTO: uartptr->iirq++; count = 0; while (regptr->lsr & UART_LSR_DR) { c = regptr->buffer; if (uartptr->icount < UART_IBLEN) { uartptr->in [(uartptr->istart + uartptr->icount) % UART_IBLEN] = c; uartptr->icount++; count++; } else { uartptr->ovrrn++; } } uartptr->cin += count; signaln(uartptr->isema, count); break; /* Transmitter holding register empty */ case UART_IIR_THRE: uartptr->oirq++; lsr = regptr->lsr; /* Read from LSR to clear interrupt */ count = 0; if (uartptr->ocount > 0) { /* Write characters to the lower half of the UART. */ do { count++; uartptr->ocount--; regptr->buffer = uartptr->out[uartptr->ostart]; uartptr->ostart = (uartptr->ostart + 1) % UART_OBLEN; } while ((count < UART_FIFO_LEN) && (uartptr->ocount > 0)); } if (count) { uartptr->cout += count; signaln(uartptr->osema, count); } /* If no characters were written, set the output idle flag. */ else { uartptr->oidle = TRUE; } break; /* Modem status change */ case UART_IIR_MSC: break; } } #ifdef FLUKE_ARM // Tell the VIC that the interrupt was handled. irq_handled(); #endif if (--resdefer > 0) { resdefer = 0; resched(); } }
/*------------------------------------------------------------------------ * ttyInter_in -- handle one arriving char (interrupts disabled) *------------------------------------------------------------------------ */ void ttyInter_in ( struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *uptr /* address of UART's CSRs */ ) { char ch; /* next char from device */ int32 avail; /* chars available in buffer */ ch = uptr->buffer; /* extract char. from device */ /* Compute chars available */ avail = semcount(typtr->tyisem); if (avail < 0) { /* one or more processes waiting*/ avail = 0; } /* Handle raw mode */ if (typtr->tyimode == TY_IMRAW) { if (avail >= TY_IBUFLEN) { /* no space => ignore input */ return; } /* Place char in buffer with no editing */ *typtr->tyitail++ = ch; /* Wrap buffer pointer */ if (typtr->tyitail >= &typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } /* Signal input semaphore and return */ signal(typtr->tyisem); return; } /* Handle cooked and cbreak modes (common part) */ if ( (ch == TY_RETURN) && typtr->tyicrlf ) { ch = TY_NEWLINE; } /* If flow control is in effect, handle ^S and ^Q */ if (typtr->tyoflow) { if (ch == typtr->tyostart) { /* ^Q starts output */ typtr->tyoheld = FALSE; ttyKickOut(typtr, uptr); return; } else if (ch == typtr->tyostop) { /* ^S stops output */ typtr->tyoheld = TRUE; return; } } typtr->tyoheld = FALSE; /* Any other char starts output */ if (typtr->tyimode == TY_IMCBREAK) { /* Just cbreak mode */ /* If input buffer is full, send bell to user */ if (avail >= TY_IBUFLEN) { eputc(typtr->tyifullc, typtr, uptr); } else { /* Input buffer has space for this char */ *typtr->tyitail++ = ch; /* Wrap around buffer */ if (typtr->tyitail>=&typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } if (typtr->tyiecho) { /* are we echoing chars?*/ echoch(ch, typtr, uptr); } } return; } else { /* Just cooked mode (see common code above) */ /* Line kill character arrives - kill entire line */ if (ch == typtr->tyikillc && typtr->tyikill) { typtr->tyitail -= typtr->tyicursor; if (typtr->tyitail < typtr->tyibuff) { typtr->tyihead += TY_IBUFLEN; } typtr->tyicursor = 0; eputc(TY_RETURN, typtr, uptr); eputc(TY_NEWLINE, typtr, uptr); return; } /* Erase (backspace) character */ if ( (ch == typtr->tyierasec) && typtr->tyierase) { if (typtr->tyicursor > 0) { typtr->tyicursor--; erase1(typtr, uptr); } return; } /* End of line */ if ( (ch == TY_NEWLINE) || (ch == TY_RETURN) ) { if (typtr->tyiecho) { echoch(ch, typtr, uptr); } *typtr->tyitail++ = ch; if (typtr->tyitail>=&typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } /* Make entire line (plus \n or \r) available */ signaln(typtr->tyisem, typtr->tyicursor + 1); typtr->tyicursor = 0; /* Reset for next line */ return; } /* Character to be placed in buffer - send bell if */ /* buffer has overflowed */ avail = semcount(typtr->tyisem); if (avail < 0) { avail = 0; } if ((avail + typtr->tyicursor) >= TY_IBUFLEN-1) { eputc(typtr->tyifullc, typtr, uptr); return; } /* EOF character: recognize at beginning of line, but */ /* print and ignore otherwise. */ if (ch == typtr->tyeofch && typtr->tyeof) { if (typtr->tyiecho) { echoch(ch, typtr, uptr); } if (typtr->tyicursor != 0) { return; } *typtr->tyitail++ = ch; signal(typtr->tyisem); return; } /* Echo the character */ if (typtr->tyiecho) { echoch(ch, typtr, uptr); } /* Insert character in the input buffer */ typtr->tyicursor++; *typtr->tyitail++ = ch; /* Wrap around if needed */ if (typtr->tyitail >= &typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } return; } }
process test_semaphore(bool8 verbose) { pid32 apid; bool8 passed = TRUE; sid32 s; byte testResult = 0; char msg[50]; /* Single semaphore tests */ testPrint(verbose, "Semaphore creation: "); s = semcreate(0); if (isbadsem(s)) { passed = FALSE; sprintf(msg, "%d", s); testFail(verbose, msg); } else if (test_checkSemCount(s, 0, verbose)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Wait on semaphore: "); if ((SYSERR != resume(apid = create((void *)test_semWaiter, INITSTK, 31, "SEMAPHORE-A", 3, s, 1, &testResult))) && test_checkProcState(apid, PR_WAIT, verbose) && test_checkSemCount(s, -1, verbose) && test_checkResult(testResult, 0, verbose)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signal semaphore: "); if ((OK == signal(s)) && test_checkProcState(apid, PR_FREE, verbose) && test_checkSemCount(s, 0, verbose) && test_checkResult(testResult, 1, verbose)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signaln semaphore (valid count): "); if ((OK == signaln(s, 5)) && test_checkProcState(apid, PR_FREE, verbose) && test_checkSemCount(s, 5, verbose) && test_checkResult(testResult, 1, verbose)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signaln semaphore (invalid count): "); if (SYSERR == signaln(s, -5)) { testPass(verbose, ""); } else { passed = FALSE; } /* Free semaphore, single semaphore tests */ testPrint(verbose, "Delete valid semaphore: "); if ((OK == semdelete(s)) && (semtab[s].sstate == S_FREE) && isempty(semtab[s].squeue)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Delete invalid semaphore: "); if (SYSERR == semdelete(-1)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Delete free semaphore: "); if (SYSERR == semdelete(s)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signal bad semaphore id: "); if (SYSERR == signal(-1)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signal free semaphore: "); if (SYSERR == signal(s)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signaln bad semaphore id: "); if (SYSERR == signaln(-1, 4)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Signaln free semaphore: "); if (SYSERR == signaln(s, 4)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Wait on bad semaphore id: "); if (SYSERR == wait(-1)) { testPass(verbose, ""); } else { passed = FALSE; } testPrint(verbose, "Wait on free semaphore: "); if (SYSERR == wait(s)) { testPass(verbose, ""); } else { passed = FALSE; } /* Process A should be dead, but in case the test failed. */ kill(apid); /* General semaphore pass/fail */ if (TRUE == passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }
/*------------------------------------------------------------------------ * ttyInter_out - handle an output on a tty device by sending more * characters to the device FIFO (interrupts disabled) *------------------------------------------------------------------------ */ void ttyInter_out( struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *csrptr /* address of UART's CSRs */ ) { int32 ochars; /* number of output chars sent */ /* to the UART */ int32 avail; /* available chars in output buf*/ int32 uspace; /* space left in onboard UART */ /* output FIFO */ byte ier = 0; /* If output is currently held, simply ignore the call */ if (typtr->tyoheld) { inb( (int)&csrptr->lsr ); /* Clear the interrupt */ return; } /* If echo and output queues empty, turn off interrupts */ if ( (typtr->tyehead == typtr->tyetail) && (semcount(typtr->tyosem) >= TY_OBUFLEN) ) { ier = inb((int)&csrptr->ier); outb((int)&csrptr->ier, ier & ~UART_IER_ETBEI); return; } /* Initialize uspace to the size of the transmit FIFO */ uspace = UART_FIFO_SIZE; /* While onboard FIFO is not full and the echo queue is */ /* nonempty, xmit chars from the echo queue */ while ( (uspace>0) && typtr->tyehead != typtr->tyetail) { outb( (int)&csrptr->buffer, *typtr->tyehead++); if (typtr->tyehead >= &typtr->tyebuff[TY_EBUFLEN]) { typtr->tyehead = typtr->tyebuff; } uspace--; } /* While onboard FIFO is not full and the output queue */ /* is nonempty, xmit chars from the output queue */ ochars = 0; avail = TY_OBUFLEN - semcount(typtr->tyosem); while ( (uspace>0) && (avail > 0) ) { outb( (int)&csrptr->buffer, *typtr->tyohead++ ); if (typtr->tyohead >= &typtr->tyobuff[TY_OBUFLEN]) { typtr->tyohead = typtr->tyobuff; } avail--; uspace--; ochars++; } if (ochars > 0) { signaln(typtr->tyosem, ochars); } return; }
/*------------------------------------------------------------------------ * ttyInter_out - handle an output on a tty device by sending more * characters to the device FIFO (interrupts disabled) *------------------------------------------------------------------------ */ void ttyInter_out( struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *uptr /* address of UART's CSRs */ ) { int32 ochars; /* number of output chars sent */ /* to the UART */ int32 avail; /* available chars in output buf*/ int32 uspace; /* space left in onboard UART */ /* output FIFO */ /* If output is currently held, turn off output interrupts */ if (typtr->tyoheld) { uptr->uart_int_en &= (~UART_TX_EMPTY_INT_EN); return; } /* If echo and output queues empty, turn off output interrupts */ if ( (typtr->tyehead == typtr->tyetail) && (semcount(typtr->tyosem) >= TY_OBUFLEN) ) { uptr->uart_int_en &= (~UART_TX_EMPTY_INT_EN); return; } /* Initialize uspace to the size of the transmit FIFO */ uspace = UART_FIFO_SIZE; /* While onboard FIFO is not full and the echo queue is */ /* nonempty, xmit chars from the echo queue */ while ( (uspace>0) && typtr->tyehead != typtr->tyetail) { uptr->uart_data = ((*typtr->tyehead++) | UART_TX_CSR); if (typtr->tyehead >= &typtr->tyebuff[TY_EBUFLEN]) { typtr->tyehead = typtr->tyebuff; } uspace--; } /* While onboard FIFO is not full and the output queue */ /* is nonempty, xmit chars from the output queue */ ochars = 0; avail = TY_OBUFLEN - semcount(typtr->tyosem); while ( (uspace>0) && (avail > 0) ) { uptr->uart_data = ((*typtr->tyohead++) | UART_TX_CSR); if (typtr->tyohead >= &typtr->tyobuff[TY_OBUFLEN]) { typtr->tyohead = typtr->tyobuff; } avail--; uspace--; ochars++; } if (ochars > 0) { signaln(typtr->tyosem, ochars); } return; }
/** * Decode hardware interrupt request from UART device. */ interrupt uartInterrupt(void) { //int u = 0, iir = 0, lsr = 0, count = 0; int u = 0, ris = 0, lsr = 0, count = 0; char c; struct uart *uartptr = NULL; struct uart_csreg *regptr = NULL; resdefer = 1; /* deferral rescheduling. */ for (u = 0; u < NUART; u++) { uartptr = &uarttab[u]; if (NULL == uartptr) //if no UART { continue; } regptr = (struct uart_csreg *)uartptr->csr; if (NULL == regptr) //if no register pointer { continue; } /* Check raw interrupt status register */ ris = regptr->ris; if (ris == 0) //if there is no interrupt { continue; } //handle whatever interrupt occurred if(ris & PL011_RIS_TXRIS){ //if the transmitter FIFO ran out uartptr->oirq++; //increment output IRQ count regptr->icr |= PL011_ICR_TXIC; //clear transmitter interrupt count = 0; if (uartptr->ocount > 0) //if we have bytes in the buffer { /* Write characters to the lower half of the UART. */ do { count++; uartptr->ocount--; regptr->buffer = uartptr->out[uartptr->ostart]; //write a character to the FIFO uartptr->ostart = (uartptr->ostart + 1) % UART_OBLEN; } while ((count < PL011_FIFO_LEN) && (uartptr->ocount > 0)); } if (count) { uartptr->cout += count; } /* If no characters were written, set the output idle flag. */ else { uartptr->oidle = TRUE; } }else if(ris & PL011_RIS_RXRIS){ //if the receiver FIFO is full uartptr->iirq++; //increment input IRQ count count = 0; while ((regptr->fr & PL011_FR_RXFE) == 0) //while the receive FIFO is not empty { c = regptr->buffer; //get a character from the FIFO if (uartptr->icount < UART_IBLEN) { uartptr->in [(uartptr->istart + uartptr->icount) % UART_IBLEN] = c; uartptr->icount++; count++; } else { uartptr->ovrrn++; } } uartptr->cin += count; signaln(uartptr->isema, count); } } #ifdef FLUKE_ARM // Tell the VIC that the interrupt was handled. irq_handled(); #endif if (--resdefer > 0) { resdefer = 0; resched(); } }