/* if_uba.c 4.13 82/10/09 */
#include "../vaxif/if_uba.h"
* Routines supporting UNIBUS network interfaces.
* Support interfaces using only one BDP statically.
* Init UNIBUS for interface on uban whose headers of size hlen are to
* end on a page boundary. We allocate a UNIBUS map register for the page
* with the header, and nmr more UNIBUS map registers for i/o on the adapter,
* doing this twice: once for reading and once for writing. We also
* allocate page frames in the mbuffer pool for these pages.
if_ubainit(ifu
, uban
, hlen
, nmr
)
register struct ifuba
*ifu
;
ncl
= clrnd(nmr
+ CLSIZE
) / CLSIZE
;
if (ifu
->ifu_r
.ifrw_addr
)
cp
= ifu
->ifu_r
.ifrw_addr
- (CLBYTES
- hlen
);
cp
= m_clalloc(2 * ncl
, MPG_SPACE
);
ifu
->ifu_r
.ifrw_addr
= cp
+ CLBYTES
- hlen
;
ifu
->ifu_w
.ifrw_addr
= ifu
->ifu_r
.ifrw_addr
+ ncl
* CLBYTES
;
ifu
->ifu_uba
= uba_hd
[uban
].uh_uba
;
if (if_ubaalloc(ifu
, &ifu
->ifu_r
, nmr
) == 0)
if (if_ubaalloc(ifu
, &ifu
->ifu_w
, nmr
) == 0)
for (i
= 0; i
< nmr
; i
++)
ifu
->ifu_wmap
[i
] = ifu
->ifu_w
.ifrw_mr
[i
];
ubarelse(ifu
->ifu_uban
, &ifu
->ifu_r
.ifrw_info
);
ifu
->ifu_r
.ifrw_addr
= 0;
* Setup either a ifrw structure by allocating UNIBUS map registers,
* possibly a buffered data path, and initializing the fields of
* the ifrw structure to minimize run-time overhead.
if_ubaalloc(ifu
, ifrw
, nmr
)
register struct ifrw
*ifrw
;
uballoc(ifu
->ifu_uban
, ifrw
->ifrw_addr
, nmr
*NBPG
+ ifu
->ifu_hlen
,
ifrw
->ifrw_bdp
= UBAI_BDP(info
);
ifrw
->ifrw_proto
= UBAMR_MRV
| (UBAI_BDP(info
) << UBAMR_DPSHIFT
);
ifrw
->ifrw_mr
= &ifu
->ifu_uba
->uba_map
[UBAI_MR(info
) + 1];
* Pull read data off a interface.
* Len is length of data, with local net header stripped.
* Off is non-zero if a trailer protocol was used, and
* gives the offset of the trailer information.
* We copy the trailer information and then all the normal
* data into mbufs. When full cluster sized units are present
* on the interface on cluster boundaries we can get them more
* easily by remapping, and take advantage of this here.
if_rubaget(ifu
, totlen
, off0
)
register struct ifuba
*ifu
;
struct mbuf
*top
, **mp
, *m
;
register caddr_t cp
= ifu
->ifu_r
.ifrw_addr
+ ifu
->ifu_hlen
;
cp
= ifu
->ifu_r
.ifrw_addr
+ ifu
->ifu_hlen
+ off
;
len
= m
->m_len
= CLBYTES
;
m
->m_off
= (int)p
- (int)m
;
* Switch pages mapped to UNIBUS with new page p,
* as quick form of copy. Remap UNIBUS and invalidate.
cpte
= &Mbmap
[mtocl(cp
)*CLSIZE
];
ppte
= &Mbmap
[mtocl(p
)*CLSIZE
];
x
= btop(cp
- ifu
->ifu_r
.ifrw_addr
);
ip
= (int *)&ifu
->ifu_r
.ifrw_mr
[x
];
for (i
= 0; i
< CLSIZE
; i
++) {
t
= *ppte
; *ppte
++ = *cpte
; *cpte
= t
;
cpte
++->pg_pfnum
|ifu
->ifu_r
.ifrw_proto
;
m
->m_len
= MIN(MLEN
, len
);
bcopy(cp
, mtod(m
, caddr_t
), (unsigned)m
->m_len
);
/* sort of an ALGOL-W style for statement... */
cp
= ifu
->ifu_r
.ifrw_addr
+ ifu
->ifu_hlen
;
* Map a chain of mbufs onto a network interface
* in preparation for an i/o operation.
* The argument chain of mbufs includes the local network
* header which is copied to be in the mapped, aligned
register struct ifuba
*ifu
;
register struct mbuf
*mp
;
cp
= ifu
->ifu_w
.ifrw_addr
;
if (claligned(cp
) && claligned(dp
) && m
->m_len
== CLBYTES
) {
struct pte
*pte
; int *ip
;
pte
= &Mbmap
[mtocl(dp
)*CLSIZE
];
x
= btop(cp
- ifu
->ifu_w
.ifrw_addr
);
ip
= (int *)&ifu
->ifu_w
.ifrw_mr
[x
];
for (i
= 0; i
< CLSIZE
; i
++)
ifu
->ifu_w
.ifrw_proto
| pte
++->pg_pfnum
;
xswapd
|= 1 << (x
>>(CLSHIFT
-PGSHIFT
));
m
->m_next
= ifu
->ifu_xtofree
;
bcopy(mtod(m
, caddr_t
), cp
, (unsigned)m
->m_len
);
* Xswapd is the set of clusters we just mapped out. Ifu->ifu_xswapd
* is the set of clusters mapped out from before. We compute
* the number of clusters involved in this operation in x.
* Clusters mapped out before and involved in this operation
* should be unmapped so original pages will be accessed by the device.
cc
= cp
- ifu
->ifu_w
.ifrw_addr
;
x
= ((cc
- ifu
->ifu_hlen
) + CLBYTES
- 1) >> CLSHIFT
;
ifu
->ifu_xswapd
&= ~xswapd
;
xswapd
&= ~ifu
->ifu_xswapd
;
while (i
= ffs(ifu
->ifu_xswapd
)) {
ifu
->ifu_xswapd
&= ~(1<<i
);
for (x
= 0; x
< CLSIZE
; x
++) {
ifu
->ifu_w
.ifrw_mr
[i
] = ifu
->ifu_wmap
[i
];
ifu
->ifu_xswapd
|= xswapd
;