Example #1
0
static void rts(struct pi_local *lp, int x)
{
    int tc;
    long br;
    int cmd;
    int dummy;

    /* assumes interrupts are off */
    cmd = CTL + lp->base;

    /* Reprogram BRG and turn on transmitter to send flags */
    if (x == ON) {		/* Turn Tx ON and Receive OFF */
	/* Exints off first to avoid abort int */
	wrtscc(lp->cardbase, cmd, R15, 0);
	wrtscc(lp->cardbase, cmd, R3, Rx8);	/* Rx off */
	lp->rstate = IDLE;
	if (cmd & 2) {		/* if channel a */
	    /* Set up for TX dma */
	    wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);
	} else {
	    wrtscc(lp->cardbase, cmd, R1, 0);	/* No interrupts */
	}

	if (!lp->clockmode) {
	    if (lp->speed) {	/* if internally clocked */
		br = lp->speed;	/* get desired speed */
		tc = (lp->xtal / br) - 2;	/* calc 1X BRG divisor */
		wrtscc(lp->cardbase, cmd, R12, tc & 0xFF);	/* lower byte */
		wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF);	/* upper byte */
	    }
	}
Example #2
0
static void tdelay(struct pi_local *lp, int time)
{
    int port;
    unsigned int t1;
    unsigned char sc;

    if (lp->base & 2) {		/* If A channel */
	sc = SC1;
	t1 = time;
	port = lp->cardbase + TMR1;
    } else {
	sc = SC2;
	t1 = 10 * time;		/* 10s of milliseconds for the B channel */
	port = lp->cardbase + TMR2;
	wrtscc(lp->cardbase, lp->base + CTL, R1, INT_ALL_Rx | EXT_INT_ENAB);
    }

    /* Setup timer sc */
    outb_p(sc | LSB_MSB | MODE0, lp->cardbase + TMRCMD);

    /* times 2 to make millisecs */
    outb_p((t1 << 1) & 0xFF, port);
    outb_p((t1 >> 7) & 0xFF, port);

    /* Enable correct int for timeout */
    wrtscc(lp->cardbase, lp->base + CTL, R15, CTSIE);
    wrtscc(lp->cardbase, lp->base + CTL, R0, RES_EXT_INT);
}
Example #3
0
static void a_txint(struct pi_local *lp)
{
    int cmd;
    unsigned long flags;

    save_flags(flags);
    cli();

    cmd = CTL + lp->base;

    switch (lp->tstate) {
    case IDLE:
	/* Transmitter idle. Find a frame for transmission */
	if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
	    rts(lp, OFF);
	    restore_flags(flags);
	    return;
	}
	/* If a buffer to send, we drop thru here */
    case DEFER:
	/* we may have deferred prev xmit attempt */
	/* Check DCD - debounce it
         * See Intel Microcommunications Handbook, p2-308
         */
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
	    lp->tstate = DEFER;
	    tdelay(lp, 100);
	    /* defer until DCD transition or timeout */
	    wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
	    restore_flags(flags);
	    return;
	}
	if (random() > lp->persist) {
	    lp->tstate = DEFER;
	    tdelay(lp, lp->slotime);
	    restore_flags(flags);
	    return;
	}
	/* Assert RTS early minimize collision window */
	wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
	rts(lp, ON);		/* Transmitter on */
	lp->tstate = ST_TXDELAY;
	tdelay(lp, lp->txdelay);
	restore_flags(flags);
	return;
    default:
	break;
    }				/* end switch(lp->state) */

    restore_flags(flags);
}				/*a_txint */
Example #4
0
static void setup_rx_dma(struct pt_local *lp)
{
	unsigned long flags;
	int cmd;
	unsigned long dma_abs;
	unsigned char dmachan;

	save_flags(flags);
	cli();

	dma_abs = (unsigned long) (lp->rcvbuf->data);
	dmachan = lp->dmachan;
	cmd = lp->base + CTL;

	if(!valid_dma_page(dma_abs, DMA_BUFF_SIZE + sizeof(struct mbuf)))
		panic("PI: RX buffer violates DMA boundary!");

	/* Get ready for RX DMA */
	wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);

	disable_dma(dmachan);
	clear_dma_ff(dmachan);

	/*
	 *	Set DMA mode register to single transfers, incrementing address,
	 *	auto init, writes
	 */

	set_dma_mode(dmachan, DMA_MODE_READ | 0x10);
	set_dma_addr(dmachan, dma_abs);
	set_dma_count(dmachan, lp->bufsiz);
	enable_dma(dmachan);

	/*
	 *	If a packet is already coming in, this line is supposed to
	 *	avoid receiving a partial packet.
	 */

	wrtscc(lp->cardbase, cmd, R0, RES_Rx_CRC);

	/* Enable RX dma */
	wrtscc(lp->cardbase, cmd, R1,
		WT_RDY_ENAB | WT_FN_RDYFN | WT_RDY_RT | INT_ERR_Rx | EXT_INT_ENAB);

	restore_flags(flags);
}
Example #5
0
/* Pi SIO External/Status interrupts (for the B channel)
 * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM.
 * Receiver automatically goes to Hunt on an abort.
 *
 * If the Tx Underrun interrupt hits, change state and
 * issue a reset command for it, and return.
 */
static void b_exint(struct pi_local *lp)
{
    unsigned long flags;
    char st;
    int cmd;
    char c;

    cmd = CTL + lp->base;
    save_flags(flags);
    cli();			/* disable interrupts */
    st = rdscc(lp->cardbase, cmd, R0);	/* Fetch status */
    /* reset external status latch */
    wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);


    switch (lp->tstate) {
    case ACTIVE:		/* Unexpected underrun */
	free_p(lp->sndbuf);
	lp->sndbuf = NULL;
	wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
	lp->tstate = FLAGOUT;
	lp->stats.tx_errors++;
	lp->stats.tx_fifo_errors++;
	tdelay(lp, lp->squeldelay);
	restore_flags(flags);
	return;
    case UNDERRUN:
	lp->tstate = CRCOUT;
	restore_flags(flags);
	return;
    case FLAGOUT:
	/* Find a frame for transmission */
	if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
	    /* Nothing to send - return to receive mode
             * Tx OFF now - flag should have gone
             */
	    rts(lp, OFF);
	    lp->tstate = IDLE;
	    restore_flags(flags);
	    return;
	}
	lp->txptr = lp->sndbuf->data;
	lp->txptr++;		/* Ignore KISS control byte */
	lp->txcnt = (int) lp->sndbuf->len - 1;
	/* Get first char to send */
	lp->txcnt--;
	c = *lp->txptr++;
	wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC);	/* reset for next frame */

	/* Send abort on underrun */
	if (lp->speed) {	/* If internally clocked */
	    wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
	} else {
	    wrtscc(lp->cardbase, cmd, R10, CRCPS | ABUNDER);
	}

	wrtscc(lp->cardbase, cmd, R8, c);	/* First char out now */
	wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);	/* Reset end of message latch */

#ifdef STUFF2
        /* stuff an extra one if we can */
	if (lp->txcnt) {
	    lp->txcnt--;
	    c = *lp->txptr++;
	    /* Wait for tx buffer empty */
	    while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)
		;   
	    wrtscc(lp->cardbase, cmd, R8, c);
	}
#endif

	/* select transmit interrupts to enable */

	wrtscc(lp->cardbase, cmd, R15, TxUIE);	/* allow Underrun int only */
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);	/* Tx/Ext ints */

	lp->tstate = ACTIVE;	/* char going out now */
	restore_flags(flags);
	return;

    case DEFER:
	/* Check DCD - debounce it
         * See Intel Microcommunications Handbook, p2-308
         */
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
	    lp->tstate = DEFER;
	    tdelay(lp, 100);
	    /* defer until DCD transition or timeout */
	    wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
	    restore_flags(flags);
	    return;
	}
	if (random() > lp->persist) {
	    lp->tstate = DEFER;
	    tdelay(lp, lp->slotime);
	    restore_flags(flags);
	    return;
	}
	rts(lp, ON);		/* Transmitter on */
	lp->tstate = ST_TXDELAY;
	tdelay(lp, lp->txdelay);
	restore_flags(flags);
	return;

    case ST_TXDELAY:

	/* Get first char to send */
	lp->txcnt--;
	c = *lp->txptr++;
	wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC);	/* reset for next frame */

	/* Send abort on underrun */
	if (lp->speed) {	/* If internally clocked */
	    wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);
	} else {
	    wrtscc(lp->cardbase, cmd, R10, CRCPS | ABUNDER);
	}

	wrtscc(lp->cardbase, cmd, R8, c);	/* First char out now */
	wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);	/* Reset end of message latch */

#ifdef STUFF2
        /* stuff an extra one if we can */
	if (lp->txcnt) {
	    lp->txcnt--;
	    c = *lp->txptr++;
	    /* Wait for tx buffer empty */
	    while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)
		;   
	    wrtscc(lp->cardbase, cmd, R8, c);
	}
#endif

	/* select transmit interrupts to enable */

	wrtscc(lp->cardbase, cmd, R15, TxUIE);	/* allow Underrun int only */
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	/* Tx/Extern ints on */
	wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);

	lp->tstate = ACTIVE;	/* char going out now */
	restore_flags(flags);
	return;
    }

    /* Receive Mode only
     * This triggers when hunt mode is entered, & since an ABORT
     * automatically enters hunt mode, we use that to clean up
     * any waiting garbage
     */
    if ((lp->rstate == ACTIVE) && (st & BRK_ABRT)) {
	(void) rdscc(lp->cardbase, cmd, R8);
	(void) rdscc(lp->cardbase, cmd, R8);
	(void) rdscc(lp->cardbase, cmd, R8);
	lp->rcp = lp->rcvbuf->data;
	lp->rcvbuf->cnt = 0;	/* rewind on DCD transition */
    }
    restore_flags(flags);
}
Example #6
0
static void b_txint(struct pi_local *lp)
{
    unsigned long flags;
    int cmd;
    unsigned char c;

    save_flags(flags);
    cli();
    cmd = CTL + lp->base;

    switch (lp->tstate) {
    case CRCOUT:
	lp->tstate = FLAGOUT;
	tdelay(lp, lp->squeldelay);
	restore_flags(flags);
	return;
    case IDLE:
	/* Transmitter idle. Find a frame for transmission */
	if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
	    /* Nothing to send - return to receive mode
             * Tx OFF now - flag should have gone
             */
	    rts(lp, OFF);
	 
	    restore_flags(flags);
	    return;
	}
	lp->txptr = lp->sndbuf->data;
	lp->txptr++;		/* Ignore KISS control byte */
	lp->txcnt = (int) lp->sndbuf->len - 1;
	/* If a buffer to send, we drop thru here */
    case DEFER:		/* we may have deferred prev xmit attempt */
	/* Check DCD - debounce it */
	/* See Intel Microcommunications Handbook, p2-308 */
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
	    lp->tstate = DEFER;
	    tdelay(lp, 100);
	    /* defer until DCD transition or timeout */
	    wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);
	    restore_flags(flags);
	    return;
	}
	if (random() > lp->persist) {
	    lp->tstate = DEFER;
	    tdelay(lp, lp->slotime);
	    restore_flags(flags);
	    return;
	}
	rts(lp, ON);		/* Transmitter on */
	lp->tstate = ST_TXDELAY;
	tdelay(lp, lp->txdelay);
	restore_flags(flags);
	return;

    case ACTIVE:
	/* Here we are actively sending a frame */
	if (lp->txcnt--) {
	    c = *lp->txptr++;
	    /* next char is gone */
	    wrtscc(lp->cardbase, cmd, R8, c);
	    /* stuffing a char satisfies Interrupt condition */
	} else {
	    /* No more to send */
	    free_p(lp->sndbuf);
	    lp->sndbuf = NULL;
	    if ((rdscc(lp->cardbase, cmd, R0) & 0x40)) {
		/* Did we underrun? */
		/* unexpected underrun */
		lp->stats.tx_errors++;
		lp->stats.tx_fifo_errors++;
		wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);
		lp->tstate = FLAGOUT;
		tdelay(lp, lp->squeldelay);
		restore_flags(flags);
		return;
	    }
	    lp->tstate = UNDERRUN;	/* Now we expect to underrun */
	    /* Send flags on underrun */
	    if (lp->speed) {	/* If internally clocked */
		wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
	    } else {
		wrtscc(lp->cardbase, cmd, R10, CRCPS);
	    }
	    wrtscc(lp->cardbase, cmd, R0, RES_Tx_P);	/* reset Tx Int Pend */
	}
	restore_flags(flags);
	return;			/* back to wait for interrupt */
    }				/* end switch */
    restore_flags(flags);
}
Example #7
0
static void b_rxint(struct device *dev, struct pi_local *lp)
{
    unsigned long flags;
    int cmd;
    char rse;
    struct sk_buff *skb;
    int sksize;
    int pkt_len;
    unsigned char *cfix;

    save_flags(flags);
    cli();			/* disable interrupts */
    cmd = CTL + lp->base;

    rse = rdscc(lp->cardbase, cmd, R1);	/* get status byte from R1 */

    if ((rdscc(lp->cardbase, cmd, R0)) & Rx_CH_AV) {
	/* there is a char to be stored
         * read special condition bits before reading the data char
         */
	if (rse & Rx_OVR) {
	    /* Rx overrun - toss buffer */
	    /* reset buffer pointers */
	    lp->rcp = lp->rcvbuf->data;
	    lp->rcvbuf->cnt = 0;

	    lp->rstate = RXERROR;	/* set error flag */
	    lp->stats.rx_errors++;
	    lp->stats.rx_over_errors++;
	} else if (lp->rcvbuf->cnt >= lp->bufsiz) {
	    /* Too large -- toss buffer */
	    /* reset buffer pointers */
	    lp->rcp = lp->rcvbuf->data;
	    lp->rcvbuf->cnt = 0;
	    lp->rstate = TOOBIG;/* when set, chars are not stored */
	}
	/* ok, we can store the received character now */
	if (lp->rstate == ACTIVE) {	/* If no errors... */
	    *lp->rcp++ = rdscc(lp->cardbase, cmd, R8);	/* char to rcv buff */
	    lp->rcvbuf->cnt++;	/* bump count */
	} else {
	    /* got to empty FIFO */
	    (void) rdscc(lp->cardbase, cmd, R8);
	    wrtscc(lp->cardbase, cmd, R0, ERR_RES);	/* reset err latch */
	    lp->rstate = ACTIVE;
	}
    }
    if (rse & END_FR) {
	/* END OF FRAME -- Make sure Rx was active */
	if (lp->rcvbuf->cnt > 0) {
	    if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (lp->rcvbuf->cnt < 10)) {
		if ((lp->rcvbuf->cnt >= 10) && (rse & CRC_ERR)) {
		    lp->stats.rx_crc_errors++;
		}
		lp->rcp = lp->rcvbuf->data;
		lp->rcvbuf->cnt = 0;
	    } else {
		/* Here we have a valid frame */
		pkt_len = lp->rcvbuf->cnt -= 2;	/* Toss 2 crc bytes */
		pkt_len += 1;	/* Make room for KISS control byte */

		/* Malloc up new buffer. */
		sksize = pkt_len;
		skb = dev_alloc_skb(sksize);
		if (skb == NULL) {
		    printk(KERN_ERR "PI: %s: Memory squeeze, dropping packet.\n", dev->name);
		    lp->stats.rx_dropped++;
		    restore_flags(flags);
		    return;
		}
		skb->dev = dev;

		/* KISS kludge -  prefix with a 0 byte */
		cfix=skb_put(skb,pkt_len);
		*cfix++=0;
		/* 'skb->data' points to the start of sk_buff data area. */
		memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
		skb->protocol=ntohs(ETH_P_AX25);
		skb->mac.raw=skb->data;
		IS_SKB(skb);
		netif_rx(skb);
		lp->stats.rx_packets++;
		/* packet queued - initialize buffer for next frame */
		lp->rcp = lp->rcvbuf->data;
		lp->rcvbuf->cnt = 0;

	    }			/* end good frame queued */
	}			/* end check for active receive upon EOF */
	lp->rstate = ACTIVE;	/* and clear error status */
    }				/* end EOF check */
    restore_flags(flags);
}
Example #8
0
/* Receive interrupt handler for the A channel
 */
static void a_rxint(struct device *dev, struct pi_local *lp)
{
    unsigned long flags;
    int cmd;
    int bytecount;
    char rse;
    struct sk_buff *skb;
    int sksize, pkt_len;
    struct mbuf *cur_buf;
    unsigned char *cfix;

    save_flags(flags);
    cli();			/* disable interrupts */
    cmd = lp->base + CTL;

    rse = rdscc(lp->cardbase, cmd, R1);	/* Get special condition bits from R1 */
    if (rse & Rx_OVR)
	lp->rstate = RXERROR;

    if (rse & END_FR) {
	/* If end of frame */
	/* figure length of frame from 8237 */
	clear_dma_ff(lp->dmachan);
	bytecount = lp->bufsiz - get_dma_residue(lp->dmachan);

	if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (bytecount < 10)) {
	    if ((bytecount >= 10) && (rse & CRC_ERR)) {
		lp->stats.rx_crc_errors++;
	    }
	    if (lp->rstate == RXERROR) {
		lp->stats.rx_errors++;
		lp->stats.rx_over_errors++;
	    }
	    /* Reset buffer pointers */
	    lp->rstate = ACTIVE;
	    setup_rx_dma(lp);
	} else {
	    /* Here we have a valid frame */
	    /* Toss 2 crc bytes , add one for KISS */
	    pkt_len = lp->rcvbuf->cnt = bytecount - 2 + 1;

	    /* Get buffer for next frame */
	    cur_buf = lp->rcvbuf;
	    switchbuffers(lp);
	    setup_rx_dma(lp);


	    /* Malloc up new buffer. */
	    sksize = pkt_len;

	    skb = dev_alloc_skb(sksize);
	    if (skb == NULL) {
		printk(KERN_ERR "PI: %s: Memory squeeze, dropping packet.\n", dev->name);
		lp->stats.rx_dropped++;
		restore_flags(flags);
		return;
	    }
	    skb->dev = dev;

	    /* KISS kludge -  prefix with a 0 byte */
	    cfix=skb_put(skb,pkt_len);
	    *cfix++=0;
	    /* 'skb->data' points to the start of sk_buff data area. */
	    memcpy(cfix, (char *) cur_buf->data,
		   pkt_len - 1);
	    skb->protocol=htons(ETH_P_AX25);
	    skb->mac.raw=skb->data;
	    IS_SKB(skb);
	    netif_rx(skb);
	    lp->stats.rx_packets++;
	}			/* end good frame */
    }				/* end EOF check */
    wrtscc(lp->cardbase, lp->base + CTL, R0, ERR_RES);	/* error reset */
    restore_flags(flags);
}
Example #9
0
static void a_exint(struct pi_local *lp)
{
    unsigned long flags;
    int cmd;
    char st;
    int length;

    save_flags(flags);
    cli();			/* disable interrupts */

    st = rdscc(lp->cardbase, lp->base + CTL, R0);	/* Fetch status */

    /* reset external status latch */
    wrtscc(lp->cardbase, CTL + lp->base, R0, RES_EXT_INT);
    cmd = lp->base + CTL;

    if ((lp->rstate >= ACTIVE) && (st & BRK_ABRT)) {
	setup_rx_dma(lp);
	lp->rstate = ACTIVE;
    }
    switch (lp->tstate) {
    case ACTIVE:
	free_p(lp->sndbuf);
	lp->sndbuf = NULL;
	lp->tstate = FLAGOUT;
	tdelay(lp, lp->squeldelay);
	break;
    case FLAGOUT:
	if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {
	    /* Nothing to send - return to receive mode */
	    lp->tstate = IDLE;
	    rts(lp, OFF);
	    restore_flags(flags);
	    return;
	}
	/* NOTE - fall through if more to send */
    case ST_TXDELAY:
	/* Disable DMA chan */
	disable_dma(lp->dmachan);

	/* Set up for TX dma */
	wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);


	/* Get all chars */
	/* Strip KISS control byte */
	length = lp->sndbuf->len - 1;
	memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);


	/* Setup DMA controller for tx */
	setup_tx_dma(lp, length);

	/* select transmit interrupts to enable */
	/* Allow DMA on chan */
	enable_dma(lp->dmachan);

	/* reset CRC, Txint pend*/
	wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);

	/* allow Underrun int only */
	wrtscc(lp->cardbase, cmd, R15, TxUIE);

	/* Enable TX DMA */
	wrtscc(lp->cardbase, cmd, R1, WT_RDY_ENAB | WT_FN_RDYFN | EXT_INT_ENAB);

	/* Send CRC on underrun */
	wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);


	/* packet going out now */
	lp->tstate = ACTIVE;
	break;
    case DEFER:
	/* we have deferred prev xmit attempt
         * See Intel Microcommunications Handbook, p2-308
         */
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);
	if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {
	    lp->tstate = DEFER;
	    tdelay(lp, 100);
	    /* Defer until dcd transition or 100mS timeout */
	    wrtscc(lp->cardbase, CTL + lp->base, R15, CTSIE | DCDIE);
	    restore_flags(flags);
	    return;
	}
	if (random() > lp->persist) {
	    lp->tstate = DEFER;
	    tdelay(lp, lp->slotime);
	    restore_flags(flags);
	    return;
	}
	/* Assert RTS early minimize collision window */
	wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);
	rts(lp, ON);		/* Transmitter on */
	lp->tstate = ST_TXDELAY;
	tdelay(lp, lp->txdelay);
	restore_flags(flags);
	return;
    }				/* switch(lp->tstate) */

    restore_flags(flags);
}				/* a_exint() */
Example #10
0
/*
 * This sets up all the registers in the SCC for the given channel
 * based upon tsync_hwint()
 */
static void scc_init(struct device *dev)
{
	unsigned long flags;
	struct pt_local *lp = (struct pt_local*) dev->priv;
	register int cmd = lp->base + CTL;
	int tc, br;

#ifdef PT_DEBUG
	printk(KERN_DEBUG "PT: scc_init(): (%d).\n", lp->base & CHANA);
#endif
	save_flags(flags);
	cli();

	/* We may put something here to enable_escc */

	if (cmd & CHANA)
	{
	        wrtscc(lp->cardbase, cmd, R9, CHRA);	/* Reset channel A */
	        wrtscc(lp->cardbase, cmd, R2, 0xff);	/* Initialise interrupt vector */
	}
	else
	    	wrtscc(lp->cardbase, cmd, R9, CHRB);	/* Reset channel B */

	/* Deselect all Rx and Tx interrupts */
	wrtscc(lp->cardbase, cmd, R1, 0);

	/* Turn off external interrupts (like CTS/CD) */
	wrtscc(lp->cardbase, cmd, R15, 0);

	/* X1 clock, SDLC mode */
	wrtscc(lp->cardbase, cmd, R4, SDLC | X1CLK);

	/* Preset CRC and set mode */
	if (lp->nrzi)
	    	/* Preset Tx CRC, put into NRZI mode */
		wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);
	else
		/* Preset Tx CRC, put into NRZ mode */
		wrtscc(lp->cardbase, cmd, R10, CRCPS);

	/* Tx/Rx parameters */
	if (lp->speed)		/* Use internal clocking */
	       /* Tx Clk from BRG. Rx Clk form DPLL, TRxC pin outputs DPLL */
	       wrtscc(lp->cardbase, cmd, R11, TCBR | RCDPLL | TRxCDP | TRxCOI);
	else	/* Use external clocking */
	{
		/* Tx Clk from TRxCL. Rx Clk from RTxCL, TRxC pin if input */
		wrtscc(lp->cardbase, cmd, R11, TCTRxCP | RCRTxCP | TRxCBR);
        	wrtscc(lp->cardbase,cmd, R14, 0);	/* wiz1 */
	}

	/* Null out SDLC start address */
	wrtscc(lp->cardbase, cmd, R6, 0);

	/* SDLC flag */
	wrtscc(lp->cardbase, cmd, R7, FLAG);

	/* Setup Tx but don't enable it */
	wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR);

	/* Setup Rx */
	wrtscc(lp->cardbase, cmd, R3, AUTO_ENAB | Rx8);

	/* Setup the BRG, turn it off first */
	wrtscc(lp->cardbase, cmd, R14, BRSRC);

	/* set the 32x time constant for the BRG in Rx mode */
	if (lp->speed)
	{
		br = lp->speed;
		tc = ((lp->xtal / 32) / (br * 2)) - 2;
		wrtscc(lp->cardbase, cmd, R12, tc & 0xff);		/* lower byte */
   		wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xff);	/* upper byte */
	}