Esempio n. 1
0
/*------------------------------------------------------------------------
 * 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;
}
Esempio n. 2
0
/*------------------------------------------------------------------------
 * 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;
}
Esempio n. 3
0
//------------------------------------------------------------------------
// 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);
	}
}
Esempio n. 4
0
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;
	
}
Esempio n. 5
0
/*------------------------------------------------------------------------
 *  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;
}
Esempio n. 6
0
/**
 * 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 = &ethptr->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;
    }
}
Esempio n. 7
0
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");
}
Esempio n. 8
0
/**
 * 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();
    }
}
Esempio n. 9
0
/*------------------------------------------------------------------------
 *  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;
	}
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
/*------------------------------------------------------------------------
 *  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;
}
Esempio n. 13
0
/**
 * 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();
    }
}