📄 if_snnew.c
字号:
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 + -