1: /*
2: * Copyright (c) 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)if_uba.c 1.2 (2.11BSD GTE) 4/3/93
7: *
8: * 2.11BSD - uballoc and ubmalloc calling conventions changed.
9: * ubmalloc now only performs address computation, the
10: * necessary UMRs are allocated at network startup.
11: * sms@wlv.imsd.contel.com - 9/8/90
12: */
13:
14: #include "param.h"
15: #include "../machine/seg.h"
16:
17: #include "systm.h"
18: #include "domain.h"
19: #include "protosw.h"
20: #include "mbuf.h"
21: #include "buf.h"
22: #include "pdpuba/ubavar.h"
23: #include "map.h"
24: #include "uba.h"
25: #include "socket.h"
26: #include "netinet/in.h"
27: #include "netinet/in_systm.h"
28: #include "net/if.h"
29: #include "pdpif/if_uba.h"
30:
31: /*
32: * Routines supporting UNIBUS network interfaces.
33: */
34:
35: if_ubainit(ifu, uban, hlen, nmr)
36: register struct ifuba *ifu;
37: int uban, hlen, nmr; /* nmr in 64 byte clicks */
38: {
39: if (ifu->ifu_r.ifrw_click)
40: return(1);
41: nmr = ctob(nmr); /* convert clicks back to bytes */
42: ifu->ifu_r.ifrw_click = m_ioget(nmr+hlen);
43: ifu->ifu_w.ifrw_click = m_ioget(nmr+hlen);
44: if (ifu->ifu_r.ifrw_click == 0 || ifu->ifu_w.ifrw_click == 0) {
45: ifu->ifu_r.ifrw_click = ifu->ifu_w.ifrw_click = 0;
46: return(0);
47: }
48: ifu->ifu_r.ifrw_info = ubmalloc(ifu->ifu_r.ifrw_click);
49: ifu->ifu_w.ifrw_info = ubmalloc(ifu->ifu_w.ifrw_click);
50: ifu->ifu_hlen = hlen;
51: return(1);
52: }
53:
54: /*
55: * Pull read data off a interface.
56: * Len is length of data, with local net header stripped.
57: * Off is non-zero if a trailer protocol was used, and
58: * gives the offset of the trailer information.
59: * We copy the trailer information and then all the normal
60: * data into mbufs.
61: */
62: struct mbuf *
63: if_rubaget(ifu, totlen, off0, ifp)
64: register struct ifuba *ifu;
65: int totlen, off0;
66: struct ifnet *ifp;
67: {
68: register caddr_t cp = (caddr_t)ifu->ifu_hlen;
69: register struct mbuf *m;
70: struct mbuf *top, **mp;
71: int click = ifu->ifu_r.ifrw_click;
72: int off = off0, len;
73:
74: top = 0;
75: mp = ⊤
76: while (totlen > 0) {
77: MGET(m, M_DONTWAIT, MT_DATA);
78: if (m == 0) {
79: m_freem(top);
80: top = 0;
81: goto out;
82: }
83: if (off) {
84: len = totlen - off;
85: cp = (caddr_t) (ifu->ifu_hlen + off);
86: } else
87: len = totlen;
88: if (len >= NBPG) {
89: if (ifp)
90: goto nopage;
91: MCLGET(m);
92: if (m->m_len != CLBYTES)
93: goto nopage;
94: m->m_len = MIN(len, CLBYTES);
95: goto copy;
96: }
97: nopage:
98: m->m_off = MMINOFF;
99: if (ifp) {
100: /*
101: * Leave room for ifp.
102: */
103: m->m_len = MIN(MLEN - sizeof(ifp), len);
104: m->m_off += sizeof(ifp);
105: } else
106: m->m_len = MIN(MLEN, len);
107: copy:
108: mbcopyin(click, cp, mtod(m, char *), (u_int)m->m_len);
109: cp += m->m_len;
110: nocopy:
111: *mp = m;
112: mp = &m->m_next;
113: if (off) {
114: /* sort of an ALGOL-W style for statement... */
115: off += m->m_len;
116: if (off == totlen) {
117: cp = (caddr_t) ifu->ifu_hlen;
118: off = 0;
119: totlen = off0;
120: }
121: } else
122: totlen -= m->m_len;
123: if (ifp) {
124: /*
125: * Prepend interface pointer to first mbuf.
126: */
127: m->m_len += sizeof(ifp);
128: m->m_off -= sizeof(ifp);
129: *(mtod(m, struct ifnet **)) = ifp;
130: ifp = NULL;
131: }
132: }
133: out:
134: return(top);
135: }
136:
137: /*
138: * Map a chain of mbufs onto a network interface
139: * in preparation for an i/o operation.
140: * The argument chain of mbufs includes the local network
141: * header.
142: */
143: if_wubaput(ifu, m)
144: struct ifuba *ifu;
145: register struct mbuf *m;
146: {
147: register struct mbuf *mp;
148: register u_short off = 0;
149: u_short click = ifu->ifu_w.ifrw_click;
150:
151: while (m) {
152: mbcopyout(mtod(m, char *), click, off, (u_int)m->m_len);
153: off += m->m_len;
154: MFREE(m, mp);
155: m = mp;
156: }
157: return(off);
158: }
159:
160: #define KDSA ((u_short *)0172260) /* supervisor - was 172360.KERNEL */
161:
162: /*
163: * Map UNIBUS virtual memory over some address in supervisor data
164: * space. We're similar to the "mapalloc" routine used for
165: * raw I/O, but for different objects. The kernel's 'ubmap' is
166: * tested since the network's "fake" 'ubmap' has gone away (this
167: * routine was the only one to use it).
168: */
169: ubadr_t
170: uballoc(addr, size)
171: caddr_t addr;
172: u_int size;
173: {
174: register int nregs;
175: register struct ubmap *ubp;
176: ubadr_t paddr, vaddr;
177: u_int click, first;
178: int page, offset;
179:
180: page = (((int)addr >> 13) & 07);
181: offset = ((int)addr & 017777);
182: click = KDSA[page];
183: paddr = (ubadr_t)click << 6;
184: paddr += offset;
185: if (!mfkd(&ubmap))
186: return(paddr);
187: nregs = (int)btoub(size);
188: first = MALLOC(ub_map, nregs);
189: #ifdef DIAGNOSTIC
190: /*
191: * Should never happen since this is only called by initialization routines
192: * in the network drivers.
193: */
194: if (!first)
195: panic("uballoc");
196: #endif
197: ubp = &UBMAP[first];
198: vaddr = (ubadr_t)first << 13;
199: while (nregs--) {
200: ubp->ub_lo = loint(paddr);
201: ubp->ub_hi = hiint(paddr);
202: ubp++;
203: paddr += (ubadr_t) UBPAGE;
204: }
205: return(vaddr);
206: }
207:
208: /*
209: * Computes a physical address within the mapped I/O area managed by
210: * m_ioget. For a UNIBUS machine, the m_ioget arena is
211: * already mapped by UMRs and mioumr and miostart have the base
212: * virtual and click addresses of the mapped arena. For Q22 machines
213: * mioumr and miostart are 0, turning the calculation into a ctob
214: * of the input click address.
215: */
216: ubadr_t
217: ubmalloc(addr)
218: memaddr addr; /* pdp11 "clicks" */
219: {
220: extern ubadr_t mioumr;
221: extern memaddr miostart;
222:
223: return(((ubadr_t)(addr - miostart) << 6) + mioumr);
224: }
Defined functions
Defined macros
KDSA
defined in line
160; used 1 times