* Copyright (c) 1988 Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Digital Equipment Corp.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)if_qe.c 7.10 (Berkeley) 10/22/88
/* from @(#)if_qe.c 1.15 (ULTRIX) 4/16/86 */
/****************************************************************
* Licensed from Digital Equipment Corporation *
* Digital Equipment Corporation *
* Maynard, Massachusetts *
* The Information in this software is subject to change *
* without notice and should not be construed as a commitment *
* by Digital Equipment Corporation. Digital makes no *
* representations about the suitability of this software for *
* any purpose. It is supplied "As Is" without expressed or *
* If the Regents of the University of California or its *
* licensees modify the software in a manner creating *
* derivative copyright rights, appropriate copyright *
* legends may be placed on the derivative work in addition *
* to that set forth above. *
****************************************************************/
/* ---------------------------------------------------------------------
* Rename "unused_multi" to "qunused_multi" for extending Generic
* 18-mar-86 -- jaw br/cvec changed to NOT use registers.
* 12 March 86 -- Jeff Chase
* Modified to handle the new MCLGET macro
* Changed if_qe_data.c to use more receive buffers
* Added a flag to poke with adb to log qe_restarts on console
* Changed the watch dog timer from 30 seconds to 3. VMS is using
* less than 1 second in their's. Also turned the printf into an
* 09/16/85 -- Larry Cohen
* Add 43bsd alpha tape changes for subnet routing
* Panic on a non-existent memory interrupt and the case where a packet
* was chained. The first should never happen because non-existant
* memory interrupts cause a bus reset. The second should never happen
* because we hang 2k input buffers on the device.
* Fixed the broadcast loopback code to handle Clusters without
* Return default hardware address on ioctl request.
* Added internal extended loopback capability.
* Fixed bug that caused every other transmit descriptor to be used
* instead of every descriptor.
* Added watchdog timer to mask hardware bug that causes device lockup.
* Reworked driver to use q-bus mapping routines. MicroVAX-I now does
* copying instead of m-buf shuffleing.
* A number of deficencies in the hardware/firmware were compensated
* for. See comments in qestart and qerint.
* Added usage counts for multicast addresses.
* Updated general protocol support to allow access to the Ethernet
* Added support for new ioctls to add and delete multicast addresses
* and set the physical address.
* Add support for general protocols.
* Integrated Shannon changes. (allow arp above 1024 and ? )
* Initial version of driver. derived from IL driver.
* ---------------------------------------------------------------------
* Digital Q-BUS to NI Adapter
#include "../net/netisr.h"
#include "../net/route.h"
#include "../netinet/in.h"
#include "../netinet/in_systm.h"
#include "../netinet/in_var.h"
#include "../netinet/ip.h"
#include "../netinet/if_ether.h"
#include "../netns/ns_if.h"
#include "../vaxuba/ubareg.h"
#include "../vaxuba/ubavar.h"
#define NRCV 15 /* Receive descriptors */
#define NRCV 20 /* Receive descriptors */
#define NXMT 5 /* Transmit descriptors */
#define NTOT (NXMT + NRCV)
#define QETIMEOUT 2 /* transmit timeout, must be > 1 */
* This constant should really be 60 because the qna adds 4 bytes of crc.
* However when set to 60 our packets are ignored by deuna's , 3coms are
* okay ??????????????????????????????????????????
* Ethernet software status per interface.
* Each interface is referenced by a network interface structure,
* qe_if, which the routing code uses to locate the interface.
* This structure contains the output queue for the interface, its address, ...
struct arpcom qe_ac
; /* Ethernet common part */
#define qe_if qe_ac.ac_if /* network-visible interface */
#define qe_addr qe_ac.ac_enaddr /* hardware Ethernet address */
struct ifubinfo qe_uba
; /* Q-bus resources */
struct ifrw qe_ifr
[NRCV
]; /* for receive buffers; */
struct ifxmt qe_ifw
[NXMT
]; /* for xmit buffers; */
int qe_flags
; /* software state */
int setupaddr
; /* mapping info for setup pkts */
int ipl
; /* interrupt priority */
struct qe_ring
*rringaddr
; /* mapping info for rings */
struct qe_ring
*tringaddr
; /* "" */
struct qe_ring rring
[NRCV
+1]; /* Receive ring descriptors */
struct qe_ring tring
[NXMT
+1]; /* Transmit ring descriptors */
u_char setup_pkt
[16][8]; /* Setup packet */
int rindex
; /* Receive index */
int tindex
; /* Transmit index */
int otindex
; /* Old transmit index */
int qe_intvec
; /* Interrupt vector */
struct qedevice
*addr
; /* device addr */
int setupqueued
; /* setup packet queued */
int nxmit
; /* Transmits in progress */
int qe_restarts
; /* timeouts */
struct uba_device
*qeinfo
[NQE
];
extern struct timeval time
;
int qeprobe(), qeattach(), qeintr(), qetimeout();
int qeinit(), qeoutput(), qeioctl(), qereset();
struct uba_driver qedriver
=
{ qeprobe
, 0, qeattach
, 0, qestd
, "qe", qeinfo
};
#define QEUNIT(x) minor(x)
* The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header)
* but will actually take in up to 2048 bytes. To guard against the receiver
* chaining buffers (which we aren't prepared to handle) we allocate 2kb
#define MAXPACKETSIZE 2048 /* Should really be ETHERMTU */
* Probe the QNA to see if it's there
register int br
, cvec
; /* r11, r10 value-result */
register struct qedevice
*addr
= (struct qedevice
*)reg
;
register struct qe_ring
*rp
;
register struct qe_ring
*prp
; /* physical rp */
register struct qe_softc
*sc
= &qe_softc
[ui
->ui_unit
];
br
= 0; cvec
= br
; br
= cvec
;
* The QNA interrupts on i/o operations. To do an I/O operation
* we have to setup the interface by transmitting a setup packet.
addr
->qe_csr
&= ~QE_RESET
;
addr
->qe_vector
= (uba_hd
[numuba
].uh_lastiv
-= 4);
* Map the communications area and the setup packet.
uballoc(0, (caddr_t
)sc
->setup_pkt
, sizeof(sc
->setup_pkt
), 0);
sc
->rringaddr
= (struct qe_ring
*) uballoc(0, (caddr_t
)sc
->rring
,
sizeof(struct qe_ring
) * (NTOT
+2), 0);
prp
= (struct qe_ring
*)UBAI_ADDR((int)sc
->rringaddr
);
* The QNA will loop the setup packet back to the receive ring
* for verification, therefore we initialize the first
* receive & transmit ring descriptors and link the setup packet
qeinitdesc(sc
->tring
, (caddr_t
)UBAI_ADDR(sc
->setupaddr
),
qeinitdesc(sc
->rring
, (caddr_t
)UBAI_ADDR(sc
->setupaddr
),
rp
= (struct qe_ring
*)sc
->tring
;
rp
->qe_flag
= rp
->qe_status1
= QE_NOTYET
;
rp
= (struct qe_ring
*)sc
->rring
;
rp
->qe_flag
= rp
->qe_status1
= QE_NOTYET
;
* Get the addr off of the interface and place it into the setup
* packet. This code looks strange due to the fact that the address
* is placed in the setup packet in col. major order.
for( i
= 0 ; i
< 6 ; i
++ )
sc
->setup_pkt
[i
][1] = addr
->qe_sta_addr
[i
];
* Start the interface and wait for the packet.
addr
->qe_csr
= QE_INT_ENABLE
| QE_XMIT_INT
| QE_RCV_INT
;
addr
->qe_rcvlist_lo
= (short)prp
;
addr
->qe_rcvlist_hi
= (short)((int)prp
>> 16);
addr
->qe_xmtlist_lo
= (short)prp
;
addr
->qe_xmtlist_hi
= (short)((int)prp
>> 16);
* All done with the bus resources.
ubarelse(0, &sc
->setupaddr
);
ubarelse(0, (int *)&sc
->rringaddr
);
sc
->ipl
= br
= qbgetpri();
return( sizeof(struct qedevice
) );
* Interface exists: make available by filling in network interface
* record. System will initialize the interface when it is ready
register struct qe_softc
*sc
= &qe_softc
[ui
->ui_unit
];
register struct ifnet
*ifp
= &sc
->qe_if
;
register struct qedevice
*addr
= (struct qedevice
*)ui
->ui_addr
;
ifp
->if_unit
= ui
->ui_unit
;
ifp
->if_flags
= IFF_BROADCAST
;
* Read the address from the prom and save it.
sc
->setup_pkt
[i
][1] = sc
->qe_addr
[i
] = addr
->qe_sta_addr
[i
] & 0xff;
printf("qe%d: %s, hardware address %s\n", ui
->ui_unit
,
addr
->qe_vector
&01 ? "delqa":"deqna",
ether_sprintf(sc
->qe_addr
));
* Save the vector for initialization at reset time.
sc
->qe_intvec
= addr
->qe_vector
;
ifp
->if_output
= qeoutput
;
ifp
->if_watchdog
= qetimeout
;
sc
->qe_uba
.iff_flags
= UBA_CANTWAIT
;
* Reset of interface after UNIBUS reset.
* If interface is on specified uba, reset its state.
register struct uba_device
*ui
;
if (unit
>= NQE
|| (ui
= qeinfo
[unit
]) == 0 || ui
->ui_alive
== 0 ||
qe_softc
[unit
].qe_if
.if_flags
&= ~IFF_RUNNING
;
* Initialization of interface.
register struct qe_softc
*sc
= &qe_softc
[unit
];
register struct uba_device
*ui
= qeinfo
[unit
];
register struct qedevice
*addr
= (struct qedevice
*)ui
->ui_addr
;
register struct ifnet
*ifp
= &sc
->qe_if
;
if (ifp
->if_addrlist
== (struct ifaddr
*)0)
if (sc
->qe_flags
& QEF_RUNNING
)
if ((ifp
->if_flags
& IFF_RUNNING
) == 0) {
* map the communications area onto the device
i
= uballoc(0, (caddr_t
)sc
->rring
,
sizeof(struct qe_ring
) * (NTOT
+2), 0);
sc
->rringaddr
= (struct qe_ring
*)UBAI_ADDR(i
);
sc
->tringaddr
= sc
->rringaddr
+ NRCV
+ 1;
i
= uballoc(0, (caddr_t
)sc
->setup_pkt
,
sizeof(sc
->setup_pkt
), 0);
sc
->setupaddr
= UBAI_ADDR(i
);
if (if_ubaminit(&sc
->qe_uba
, ui
->ui_ubanum
,
sizeof (struct ether_header
), (int)btoc(MAXPACKETSIZE
),
sc
->qe_ifr
, NRCV
, sc
->qe_ifw
, NXMT
) == 0) {
printf("qe%d: can't initialize\n", unit
);
sc
->qe_if
.if_flags
&= ~IFF_UP
;
* Init the buffer descriptors and indexes for each of the lists and
* loop them back to form a ring.
for (i
= 0; i
< NRCV
; i
++) {
qeinitdesc( &sc
->rring
[i
],
(caddr_t
)UBAI_ADDR(sc
->qe_ifr
[i
].ifrw_info
), MAXPACKETSIZE
);
sc
->rring
[i
].qe_flag
= sc
->rring
[i
].qe_status1
= QE_NOTYET
;
sc
->rring
[i
].qe_valid
= 1;
qeinitdesc(&sc
->rring
[i
], (caddr_t
)NULL
, 0);
sc
->rring
[i
].qe_addr_lo
= (short)sc
->rringaddr
;
sc
->rring
[i
].qe_addr_hi
= (short)((int)sc
->rringaddr
>> 16);
sc
->rring
[i
].qe_chain
= 1;
sc
->rring
[i
].qe_flag
= sc
->rring
[i
].qe_status1
= QE_NOTYET
;
sc
->rring
[i
].qe_valid
= 1;
for( i
= 0 ; i
<= NXMT
; i
++ )
qeinitdesc(&sc
->tring
[i
], (caddr_t
)NULL
, 0);
sc
->tring
[i
].qe_addr_lo
= (short)sc
->tringaddr
;
sc
->tring
[i
].qe_addr_hi
= (short)((int)sc
->tringaddr
>> 16);
sc
->tring
[i
].qe_chain
= 1;
sc
->tring
[i
].qe_flag
= sc
->tring
[i
].qe_status1
= QE_NOTYET
;
sc
->tring
[i
].qe_valid
= 1;
sc
->nxmit
= sc
->otindex
= sc
->tindex
= sc
->rindex
= 0;
* Take the interface out of reset, program the vector,
* enable interrupts, and tell the world we are up.
addr
->qe_vector
= sc
->qe_intvec
;
addr
->qe_csr
= QE_RCV_ENABLE
| QE_INT_ENABLE
| QE_XMIT_INT
|
addr
->qe_rcvlist_lo
= (short)sc
->rringaddr
;
addr
->qe_rcvlist_hi
= (short)((int)sc
->rringaddr
>> 16);
ifp
->if_flags
|= IFF_UP
| IFF_RUNNING
;
sc
->qe_flags
|= QEF_RUNNING
;
* Start output on interface.
struct uba_device
*ui
= qeinfo
[unit
];
register struct qe_softc
*sc
= &qe_softc
[unit
];
register struct qedevice
*addr
;
register struct qe_ring
*rp
;
addr
= (struct qedevice
*)ui
->ui_addr
;
* The deqna doesn't look at anything but the valid bit
* to determine if it should transmit this packet. If you have
* a ring and fill it the device will loop indefinately on the
* packet and continue to flood the net with packets until you
* break the ring. For this reason we never queue more than n-1
* packets in the transmit ring.
* The microcoders should have obeyed their own defination of the
* flag and status words, but instead we have to compensate.
sc
->tring
[index
].qe_valid
== 0 && sc
->nxmit
< (NXMT
-1) ;
sc
->tindex
= index
= ++index
% NXMT
){
buf_addr
= sc
->setupaddr
;
IF_DEQUEUE(&sc
->qe_if
.if_snd
, m
);
buf_addr
= sc
->qe_ifw
[index
].ifw_info
;
len
= if_ubaput(&sc
->qe_uba
, &sc
->qe_ifw
[index
], m
);
* Does buffer end on odd byte ?
rp
->qe_buf_len
= -(len
/2);
buf_addr
= UBAI_ADDR(buf_addr
);
rp
->qe_flag
= rp
->qe_status1
= QE_NOTYET
;
rp
->qe_addr_lo
= (short)buf_addr
;
rp
->qe_addr_hi
= (short)(buf_addr
>> 16);
rp
->qe_flag
= rp
->qe_status1
= QE_NOTYET
;
sc
->qe_if
.if_timer
= QETIMEOUT
;
* See if the xmit list is invalid.
if( addr
->qe_csr
& QE_XL_INVALID
) {
buf_addr
= (int)(sc
->tringaddr
+index
);
addr
->qe_xmtlist_lo
= (short)buf_addr
;
addr
->qe_xmtlist_hi
= (short)(buf_addr
>> 16);
* Ethernet interface interrupt processor
register struct qe_softc
*sc
= &qe_softc
[unit
];
struct qedevice
*addr
= (struct qedevice
*)qeinfo
[unit
]->ui_addr
;
addr
->qe_csr
= QE_RCV_ENABLE
| QE_INT_ENABLE
| QE_XMIT_INT
| QE_RCV_INT
| QE_ILOOP
;
if( csr
& QE_NEX_MEM_INT
)
panic("qe: Non existant memory interrupt");
if( addr
->qe_csr
& QE_RL_INVALID
&& sc
->rring
[sc
->rindex
].qe_status1
== QE_NOTYET
) {
buf_addr
= (int)&sc
->rringaddr
[sc
->rindex
];
addr
->qe_rcvlist_lo
= (short)buf_addr
;
addr
->qe_rcvlist_hi
= (short)(buf_addr
>> 16);
* Ethernet interface transmit interrupt.
register struct qe_softc
*sc
= &qe_softc
[unit
];
register struct qe_ring
*rp
;
register struct ifxmt
*ifxp
;
while( sc
->otindex
!= sc
->tindex
&& sc
->tring
[sc
->otindex
].qe_status1
!= QE_NOTYET
&& sc
->nxmit
> 0 ) {
* Save the status words from the descriptor so that it can
rp
= &sc
->tring
[sc
->otindex
];
status1
= rp
->qe_status1
;
setupflag
= rp
->qe_setup
;
len
= (-rp
->qe_buf_len
) * 2;
* Init the buffer descriptor
bzero((caddr_t
)rp
, sizeof(struct qe_ring
));
sc
->qe_if
.if_collisions
+= ( status1
& QE_CCNT
) >> 4;
* If this was a broadcast packet loop it
* back because the hardware can't hear its own
ifxp
= &sc
->qe_ifw
[sc
->otindex
];
if (bcmp((caddr_t
)((struct ether_header
*)ifxp
->ifw_addr
)->ether_dhost
,
(caddr_t
)etherbroadcastaddr
,
sizeof(etherbroadcastaddr
)) == 0)
len
- sizeof(struct ether_header
));
m_freem(ifxp
->ifw_xtofree
);
sc
->otindex
= ++sc
->otindex
% NXMT
;
* Ethernet interface receiver interrupt.
* If can't determine length from type, then have to drop packet.
* Othewise decapsulate packet based on type and pass to type specific
* higher-level input routine.
register struct qe_softc
*sc
= &qe_softc
[unit
];
register struct qe_ring
*rp
;
int len
, status1
, status2
;
* Traverse the receive ring looking for packets to pass back.
* The search is complete when we find a descriptor not in use.
* As in the transmit case the deqna doesn't honor it's own protocols
* so there exists the possibility that the device can beat us around
* the ring. The proper way to guard against this is to insure that
* there is always at least one invalid descriptor. We chose instead
* to make the ring large enough to minimize the problem. With a ring
* size of 4 we haven't been able to see the problem. To be safe we
for( ; sc
->rring
[sc
->rindex
].qe_status1
!= QE_NOTYET
; sc
->rindex
= ++sc
->rindex
% NRCV
){
rp
= &sc
->rring
[sc
->rindex
];
status1
= rp
->qe_status1
;
status2
= rp
->qe_status2
;
bzero((caddr_t
)rp
, sizeof(struct qe_ring
));
if( (status1
& QE_MASK
) == QE_MASK
)
panic("qe: chained packet");
len
= ((status1
& QE_RBL_HI
) | (status2
& QE_RBL_LO
)) + 60;
if (status1
& QE_ERROR
) {
if ((status1
& QE_RUNT
) == 0)
* We don't process setup packets.
if( !(status1
& QE_ESETUP
) )
qeread(sc
, &sc
->qe_ifr
[sc
->rindex
],
len
- sizeof(struct ether_header
));
* Return the buffer to the ring
bufaddr
= (int)UBAI_ADDR(sc
->qe_ifr
[sc
->rindex
].ifrw_info
);
rp
->qe_buf_len
= -((MAXPACKETSIZE
)/2);
rp
->qe_addr_lo
= (short)bufaddr
;
rp
->qe_addr_hi
= (short)((int)bufaddr
>> 16);
rp
->qe_flag
= rp
->qe_status1
= QE_NOTYET
;
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
* Use trailer local net encapsulation if enough data in first
* packet leaves a multiple of 512 bytes of data in remainder.
register struct qe_softc
*is
= &qe_softc
[ifp
->if_unit
];
register struct mbuf
*m
= m0
;
register struct ether_header
*eh
;
if ((ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) != (IFF_UP
|IFF_RUNNING
)) {
switch (dst
->sa_family
) {
idst
= ((struct sockaddr_in
*)dst
)->sin_addr
;
if (!arpresolve(&is
->qe_ac
, m
, &idst
, edst
, &usetrailers
))
return (0); /* if not yet resolved */
off
= ntohs((u_short
)mtod(m
, struct ip
*)->ip_len
) - m
->m_len
;
if (usetrailers
&& off
> 0 && (off
& 0x1ff) == 0 &&
m
->m_off
>= MMINOFF
+ 2 * sizeof (u_short
)) {
type
= ETHERTYPE_TRAIL
+ (off
>>9);
m
->m_off
-= 2 * sizeof (u_short
);
m
->m_len
+= 2 * sizeof (u_short
);
*mtod(m
, u_short
*) = htons((u_short
)ETHERTYPE_IP
);
*(mtod(m
, u_short
*) + 1) = htons((u_short
)m
->m_len
);
bcopy((caddr_t
)&(((struct sockaddr_ns
*)dst
)->sns_addr
.x_host
),
(caddr_t
)edst
, sizeof (edst
));
eh
= (struct ether_header
*)dst
->sa_data
;
bcopy((caddr_t
)eh
->ether_dhost
, (caddr_t
)edst
, sizeof (edst
));
printf("qe%d: can't handle af%d\n", ifp
->if_unit
,
* Packet to be sent as trailer: move first packet
* (control information) to end of chain.
* Add local net header. If no space in first mbuf,
if (m
->m_off
> MMAXOFF
||
MMINOFF
+ sizeof (struct ether_header
) > m
->m_off
) {
m
= m_get(M_DONTWAIT
, MT_HEADER
);
m
->m_len
= sizeof (struct ether_header
);
m
->m_off
-= sizeof (struct ether_header
);
m
->m_len
+= sizeof (struct ether_header
);
eh
= mtod(m
, struct ether_header
*);
eh
->ether_type
= htons((u_short
)type
);
bcopy((caddr_t
)edst
, (caddr_t
)eh
->ether_dhost
, sizeof (edst
));
bcopy((caddr_t
)is
->qe_addr
, (caddr_t
)eh
->ether_shost
, sizeof (is
->qe_addr
));
* Queue message on interface, and start output if interface
if (IF_QFULL(&ifp
->if_snd
)) {
IF_ENQUEUE(&ifp
->if_snd
, m
);
* Process an ioctl request.
register struct ifnet
*ifp
;
struct qe_softc
*sc
= &qe_softc
[ifp
->if_unit
];
struct ifaddr
*ifa
= (struct ifaddr
*)data
;
int s
= splimp(), error
= 0;
switch(ifa
->ifa_addr
.sa_family
) {
((struct arpcom
*)ifp
)->ac_ipaddr
=
arpwhohas((struct arpcom
*)ifp
, &IA_SIN(ifa
)->sin_addr
);
register struct ns_addr
*ina
= &(IA_SNS(ifa
)->sns_addr
);
ina
->x_host
= *(union ns_host
*)(sc
->qe_addr
);
qe_setaddr(ina
->x_host
.c_host
, ifp
->if_unit
);
if ((ifp
->if_flags
& IFF_UP
) == 0 &&
sc
->qe_flags
& QEF_RUNNING
) {
(qeinfo
[ifp
->if_unit
]->ui_addr
))->qe_csr
= QE_RESET
;
sc
->qe_flags
&= ~QEF_RUNNING
;
} else if ((ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) ==
IFF_RUNNING
&& (sc
->qe_flags
& QEF_RUNNING
) == 0)
* set ethernet address for unit
qe_setaddr(physaddr
, unit
)
register struct qe_softc
*sc
= &qe_softc
[unit
];
sc
->setup_pkt
[i
][1] = sc
->qe_addr
[i
] = physaddr
[i
];
sc
->qe_flags
|= QEF_SETADDR
;
if (sc
->qe_if
.if_flags
& IFF_RUNNING
)
* Initialize a ring descriptor with mbuf allocation side effects
qeinitdesc(rp
, addr
, len
)
register struct qe_ring
*rp
;
caddr_t addr
; /* mapped address */
* clear the entire descriptor
bzero((caddr_t
)rp
, sizeof(struct qe_ring
));
rp
->qe_buf_len
= -(len
/2);
rp
->qe_addr_lo
= (short)addr
;
rp
->qe_addr_hi
= (short)((int)addr
>> 16);
* Build a setup packet - the physical address will already be present
* Copy the target address to the rest of the entries in this row.
for ( j
= 0; j
< 6 ; j
++ )
for ( i
= 2 ; i
< 8 ; i
++ )
sc
->setup_pkt
[j
][i
] = sc
->setup_pkt
[j
][1];
* Duplicate the first half.
bcopy((caddr_t
)sc
->setup_pkt
[0], (caddr_t
)sc
->setup_pkt
[8], 64);
* Fill in the broadcast address.
for ( i
= 0; i
< 6 ; i
++ )
sc
->setup_pkt
[i
][2] = 0xff;
* Pass a packet to the higher levels.
* We deal with the trailer protocol here.
register struct qe_softc
*sc
;
* Deal with trailer protocol: if type is INET trailer
* get true type from first 16-bit word past data.
* Remember that type was trailer by setting off.
eh
= (struct ether_header
*)ifrw
->ifrw_addr
;
eh
->ether_type
= ntohs((u_short
)eh
->ether_type
);
#define qedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
if (eh
->ether_type
>= ETHERTYPE_TRAIL
&&
eh
->ether_type
< ETHERTYPE_TRAIL
+ETHERTYPE_NTRAILER
) {
off
= (eh
->ether_type
- ETHERTYPE_TRAIL
) * 512;
eh
->ether_type
= ntohs(*qedataaddr(eh
,off
, u_short
*));
resid
= ntohs(*(qedataaddr(eh
, off
+2, u_short
*)));
* Pull packet off interface. Off is nonzero if packet
* has trailing header; qeget will then force this header
* information to be at the front, but we still have to drop
* the type and length which are at the front of any trailer data.
m
= if_ubaget(&sc
->qe_uba
, ifrw
, len
, off
, &sc
->qe_if
);
ifp
= *(mtod(m
, struct ifnet
**));
m
->m_off
+= 2 * sizeof (u_short
);
m
->m_len
-= 2 * sizeof (u_short
);
*(mtod(m
, struct ifnet
**)) = ifp
;
switch (eh
->ether_type
) {
* Watchdog timeout routine. There is a condition in the hardware that
* causes the board to lock up under heavy load. This routine detects
* the hang up and restarts the device.
register struct qe_softc
*sc
;
log(LOG_ERR
, "qe%d: transmit timeout, restarted %d\n",
unit
, ++sc
->qe_restarts
);
* Restart for board lockup problem.
register struct qe_softc
*sc
;
register struct ifnet
*ifp
= &sc
->qe_if
;
register struct qedevice
*addr
= sc
->addr
;
register struct qe_ring
*rp
;
for (i
= 0, rp
= sc
->tring
; i
< NXMT
; rp
++, i
++) {
rp
->qe_flag
= rp
->qe_status1
= QE_NOTYET
;
sc
->nxmit
= sc
->otindex
= sc
->tindex
= sc
->rindex
= 0;
addr
->qe_csr
= QE_RCV_ENABLE
| QE_INT_ENABLE
| QE_XMIT_INT
|
addr
->qe_rcvlist_lo
= (short)sc
->rringaddr
;
addr
->qe_rcvlist_hi
= (short)((int)sc
->rringaddr
>> 16);
sc
->qe_flags
|= QEF_RUNNING
;