⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_snnew.c

📁 T-kernel Tcp/ip Protocol Stack Sample
💻 C
📖 第 1 页 / 共 5 页
字号:
	            tmp_reg = (unsigned short)(*(mtod(m, caddr_t) + m->m_len - 1)) & 0x00FF;
	            outw(BASE + DATA_REG_W, tmp_reg);

	            /* roll back the pointer */
	            outw(BASE + POINTER_REG_W, ptr_reg + 1);
#else
	            outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1));
#endif
#ifdef DEBUG
tm_putstring("snstart2.\n");
#endif
		}
	    }
	    else {
	        /* Even begin address */
	        /* Push out words.
	         */
	        outsw(BASE + DATA_REG_W,
			(unsigned short *)mtod(m, caddr_t), m->m_len / 2);
 
	        /* Push out remaining byte.
	         */
	        if (m->m_len & 1) {
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	            ptr_reg = inw (BASE + POINTER_REG_W);

	            /* cannot access with byte length */
	            tmp_reg = (unsigned short)(*(mtod(m, caddr_t) + m->m_len - 1)) & 0x00FF;
	            outw(BASE + DATA_REG_W, tmp_reg);

	            /* roll back the pointer */
	            outw(BASE + POINTER_REG_W, ptr_reg + 1);
#else
	            outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1));
#endif
#ifdef DEBUG
tm_putstring("snstart3.\n");
#endif
		}
	    }
	}

	/* Push out padding.
	 */
	while (pad > 1) {
	    outw(BASE + DATA_REG_W, 0);
	    pad -= 2;
	}
	if (pad) {
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	    ptr_reg = inw (BASE + POINTER_REG_W);

	    /* cannot access with byte length */
	    outw(BASE + DATA_REG_W, 0);

	    /* roll back the pointer */
	    outw(BASE + POINTER_REG_W, ptr_reg + 1);
#else
	    outb(BASE + DATA_REG_B, 0);
#endif
#ifdef DEBUG
tm_putstring("snstart4.\n");
#endif
	}
#endif /* CHECK_PRO */

	/* Push out control byte and unused packet byte
	 * The control byte is 0 meaning the packet is
	 * even lengthed and no special CRC handling is
	 * desired.
	 */
	outw(BASE + DATA_REG_W, 0);

	/* Enable the interrupts and let the chipset deal with it
	 * Also set a watchdog in case we miss the interrupt.
	 */
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	/* cannot access with byte length */
	tmp_reg = inw( BASE + INTR_MASK_REG_W );
	mask = (u_char)(tmp_reg >> 8) | (IM_TX_INT | IM_TX_EMPTY_INT);
	tmp_reg = (u_short)(mask << 8);
	outw( BASE + INTR_MASK_REG_W, tmp_reg );
#else
	mask = inb( BASE + INTR_MASK_REG_B ) | (IM_TX_INT | IM_TX_EMPTY_INT);
	outb( BASE + INTR_MASK_REG_B, mask );
#endif
	sc->intr_mask = mask;

	outw( BASE + MMU_CMD_REG_W, MMUCR_ENQUEUE );

	sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
	sc->arpcom.ac_if.if_timer = 1;

	sc->arpcom.ac_if.if_opackets++;
	m_freem(top);

readcheck:
	/*
	 * Is another packet coming in?  We don't want to overflow the
	 * tiny RX FIFO.  If nothing has arrived then attempt to queue
	 * another transmit packet.
	 */
	if (inw( BASE + FIFO_PORTS_REG_W ) & FIFO_REMPTY )
	    goto startagain;

	splx(s);
	return;
}

/* Resume a packet transmit operation after a memory allocation
 * has completed.
 *
 * This is basically a hacked up copy of snstart() which handles
 * a completed memory allocation the same way snstart() does.
 * It then passes control to snstart to handle any other queued
 * packets.
 */
static void
snresume(struct ifnet *ifp)
{
	register struct sn_softc *sc = &sn_softc0;
	register u_int len;
	register struct mbuf *m;
	struct mbuf *top;
	int pad;
#if defined(ORG)
	int mask;
#else
	u_char mask;
#endif
	u_short length;
	u_short numPages;
	u_short pages_wanted;
	u_char packet_no;
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	volatile unsigned short tmp_reg, ptr_reg;
#endif

	if (sc->pages_wanted < 0)
	    return;

	pages_wanted = sc->pages_wanted;
	sc->pages_wanted = -1;

	/* Sneak a peek at the next packet
	 */
	m = sc->arpcom.ac_if.if_snd.ifq_head;
	if (m == 0) {
#ifdef PRINTON
	    printf("sn%d: snresume() with nothing to send\n", ifp->if_unit);
#endif
	    return;
	}

	/* Compute the frame length and set pad to give an overall
	 * even number of bytes.  Below we assume that the packet
	 * length is even.
	 */
	for (len = 0, top = m; m; m = m->m_next)
	    len += m->m_len;

	pad = (len & 1);

	/*
	 * We drop packets that are too large. Perhaps we should truncate
	 * them instead?
	 */
	if (len + pad > ETHER_MAX_LEN) {
#ifdef PRINTON
	    printf("sn%d: large packet discarded (B)\n", ifp->if_unit);
#endif
	    ++sc->arpcom.ac_if.if_oerrors;
	    IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
	    m_freem(m);
	    return;
	}

#ifdef SW_PAD
	/* If HW padding is not turned on, then pad to
	 * ETHER_MIN_LEN.
	 */
	if (len < ETHER_MIN_LEN)
	   pad = ETHER_MIN_LEN - len;
#endif

	length = pad + len;

#if defined(LAN91C111)
	/* the size of "page" is 2048 byte */
	numPages = (length + 6) >> 11;
#else
	/*
	 * The MMU wants the number of pages to be the number of 256 byte
	 * 'pages', minus 1 (A packet can't ever have 0 pages.
	 * We also include space for the status word, byte count and
	 * control bytes in the allocation request.
	 */
	numPages = (length + 6) >> 8;
#endif

	SMC_SELECT_BANK( 2 );

	/* The memory allocation completed.  Check the results.
	 * If it failed, we simply set a watchdog timer and hope
	 * for the best.
	 */
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	/* cannot access with byte length */
	tmp_reg = inw( BASE + ALLOC_RESULT_REG_W );
	packet_no = (u_char)(tmp_reg << 8);
#else
	packet_no = inb( BASE + ALLOC_RESULT_REG_B );
#endif
	if ( packet_no & ARR_FAILED ) {
#ifdef PRINTON
	    printf("sn%d: Memory allocation failed.  Weird.\n", ifp->if_unit);
#endif
	    sc->arpcom.ac_if.if_timer = 1;

	    goto try_start;
	    return;
	}

	/* We have a packet number, so tell the card to use it.
	 */
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	/* cannot access with byte length */
	tmp_reg = (u_short)packet_no & 0x00FF;
	outw( BASE + PACKET_NUM_REG_W, tmp_reg );
#else
	outb( BASE + PACKET_NUM_REG_B, packet_no );
#endif

	/* Now, numPages should match the pages_wanted recorded
	 * when the memory allocation was initiated.
	 */
	if (pages_wanted != numPages) {
#ifdef PRINTON
	    printf("sn%d: memory allocation wrong size.  Weird.\n", ifp->if_unit);
#endif
	    /* If the allocation was the wrong size
	     * we simply release the memory once it
	     * is granted.
	     * Wait for the MMU to be un-busy.
	     */
	    outw( BASE + MMU_CMD_REG_W, MMUCR_FREEPKT );
	    while ( inw( BASE + MMU_CMD_REG_W ) & MMUCR_BUSY ) /*NOTHING*/ ;

	    return;
	}

	/* Point to the beginning of the packet
	 */
	outw( BASE + POINTER_REG_W, PTR_AUTOINC | 0x0000 );

	/* Send the packet length (+6 for status, length and control byte)
	 * and the status word (set to zeros)
	 */
	outw( BASE + DATA_REG_W, 0 );

#if defined(OLD)
	outb( BASE + DATA_REG_B, (length + 6) & 0xFF );
	outb( BASE + DATA_REG_B, (length + 6) >> 8 );
#else
	outw( BASE + DATA_REG_W, (length + 6) );
#endif

    /***********************************
     Set Data:
        b15                           b0
        +------------------------------+
      0 |Status Word (=0)              |
        +------------------------------+
      2 |(length+6)/256 |(length+6)%256|
        +------------------------------+
      4 |Data Area                     |
        +------------------------------+
        |                              |
        +------------------------------+
   2046 |Control Byte                  | Last Data Byte if odd.
    max +------------------------------+
    **********************************/

	/* Get the packet from the kernel.  This will include the
	 * Ethernet frame header, MAC Addresses etc.
	 */
	IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);

	/* Push out the data to the card.
	 */
	for (top = m; m != 0; m = m->m_next) {
	    if ( (int)mtod(m, caddr_t) & 1) {
	        /* Odd begin address 
	         */
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	        ptr_reg = inw (BASE + POINTER_REG_W);

	        /* cannot access with byte length */
	        tmp_reg = (unsigned short)*(mtod(m, caddr_t)) & 0x00FF;
	        outw(BASE + DATA_REG_W, tmp_reg);

	        /* roll back the pointer */
	        outw(BASE + POINTER_REG_W, ptr_reg + 1);
#else
	        outb(BASE + DATA_REG_B, *(mtod(m, caddr_t)));
#endif
#ifdef DEBUG
tm_putstring("snresume1.\n");
#endif

	        /* Push out words.
	         */
	        outsw(BASE + DATA_REG_W,
			(unsigned short *)(mtod(m, caddr_t)+1), (m->m_len-1) / 2);

	        /* Push out remaining byte.
	         */
	        if ((m->m_len-1) & 1) {
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	            ptr_reg = inw (BASE + POINTER_REG_W);

	            /* cannot access with byte length */
	            tmp_reg = (unsigned short)(*(mtod(m, caddr_t) + m->m_len - 1)) & 0x00FF;
	            outw(BASE + DATA_REG_W, tmp_reg);

	            /* roll back the pointer */
	            outw(BASE + POINTER_REG_W, ptr_reg + 1);
#else
	            outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1));
#endif
#ifdef DEBUG
tm_putstring("snresume2.\n");
#endif
	        }
	    }
	    else {
	        /* Even begin address */
	        /* Push out words.
	         */
	        outsw(BASE + DATA_REG_W,
			(unsigned short *)mtod(m, caddr_t), m->m_len / 2);
 
	        /* Push out remaining byte.
	         */
	        if (m->m_len & 1) {
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	            ptr_reg = inw (BASE + POINTER_REG_W);

	            /* cannot access with byte length */
	            tmp_reg = (unsigned short)(*(mtod(m, caddr_t) + m->m_len - 1)) & 0x00FF;
	            outw(BASE + DATA_REG_W, tmp_reg);

	            /* roll back the pointer */
	            outw(BASE + POINTER_REG_W, ptr_reg + 1);
#else
	            outb(BASE + DATA_REG_B, *(mtod(m, caddr_t) + m->m_len - 1));
#endif
#ifdef DEBUG
tm_putstring("snresume3.\n");
#endif
	        }
	    }
	}

	/* Push out padding.
	 */
	while (pad > 1) {
	    outw(BASE + DATA_REG_W, 0);
	    pad -= 2;
	}
	if (pad) {
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	    ptr_reg = inw (BASE + POINTER_REG_W);

	    /* cannot access with byte length */
	    outw(BASE + DATA_REG_W, 0);

	    /* roll back the pointer */
	    outw(BASE + POINTER_REG_W, ptr_reg + 1);
#else
	    outb(BASE + DATA_REG_B, 0);
#endif
#ifdef DEBUG
tm_putstring("snresume4.\n");
#endif
	}

	/* Push out control byte and unused packet byte
	 * The control byte is 0 meaning the packet is
	 * even lengthed and no special CRC handling is
	 * desired.
	 */
	outw(BASE + DATA_REG_W, 0);

	/* Enable the interrupts and let the chipset deal with it
	 * Also set a watchdog in case we miss the interrupt.
	 */
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	/* cannot access with byte length */
	tmp_reg = inw( BASE + INTR_MASK_REG_W );
	mask = (u_char)(tmp_reg >> 8) | (IM_TX_INT | IM_TX_EMPTY_INT);
	tmp_reg = (u_short)(mask << 8);
	outw( BASE + INTR_MASK_REG_W, tmp_reg );
#else
	mask = inb( BASE + INTR_MASK_REG_B ) | (IM_TX_INT | IM_TX_EMPTY_INT);
	outb( BASE + INTR_MASK_REG_B, mask );
#endif
	sc->intr_mask = mask;
	outw( BASE + MMU_CMD_REG_W, MMUCR_ENQUEUE );

	sc->arpcom.ac_if.if_opackets++;
	m_freem(top);

try_start:
	/* Now pass control to snstart() to queue any additional packets
	 */
	sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
	snstart(ifp);

	/* We've sent something, so we're active.  Set a watchdog
	 * in case the TX_EMPTY interrupt is lost.
	 */
	sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
	sc->arpcom.ac_if.if_timer = 1;

	return;
}

void
#if defined(T_KERNEL)
snintr(UINT dintno, VP sp)
#endif
{
	snintr_sc();

#if defined(_MIC_SH7145_)
	if (in_h(ISR) & 0x0010) {
		out_h(ISR, in_h(ISR) & ~(0x0010) );	/* IRQ3 request clear */
	}
#endif

#if defined(T_KERNEL)
	return;
#endif
}

void
snintr_sc(void)
{
#if defined(ORG)
	int status, interrupts;
#else
	u_char status, interrupts;
#endif
	register struct sn_softc *sc=&sn_softc0;
	struct ifnet *ifp = &sc->arpcom.ac_if;
	int x;
	int flags;

	/* Chip state registers
	 */
	u_char mask;
	u_char packet_no;
#if defined(_STD_SH7727_) || defined(_MIC_SH7145_)
	volatile unsigned short tmp_reg;
#endif
	u_short tx_status;
	u_short card_stats;

	/* if_ep.c did this, so I do too.  Yet if_ed.c doesn't.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -