1 /* uipc_mbuf.c 1.6 81/10/30 */ 2 3 #include "../h/param.h" 4 #include "../h/dir.h" 5 #include "../h/user.h" 6 #include "../h/proc.h" 7 #include "../h/pte.h" 8 #include "../h/cmap.h" 9 #include "../h/map.h" 10 #include "../h/mbuf.h" 11 #include "../inet/inet.h" 12 #include "../inet/inet_systm.h" 13 #include "../inet/ip.h" 14 #include "../inet/tcp.h" 15 #include "../h/vm.h" 16 17 struct mbuf * 18 m_get(canwait) 19 int canwait; 20 { 21 register struct mbuf *m; 22 23 COUNT(M_GET); 24 MGET(m, canwait); 25 return (m); 26 } 27 28 struct mbuf * 29 m_free(m) 30 struct mbuf *m; 31 { 32 register struct mbuf *n; 33 34 COUNT(M_FREE); 35 MFREE(m, n); 36 return (n); 37 } 38 39 struct mbuf * 40 m_more(type) 41 int type; 42 { 43 int s; 44 register struct mbuf *m; 45 46 COUNT(M_MORE); 47 if (!m_expand()) { 48 netstat.m_drops++; 49 return (NULL); 50 } 51 #define m_more(x) ((struct mbuf *)panic("m_more")) 52 MGET(m, 0); 53 return (m); 54 } 55 56 m_freem(m) 57 register struct mbuf *m; 58 { 59 register struct mbuf *n; 60 register int s, cnt; 61 62 COUNT(M_FREEM); 63 if (m == NULL) 64 return (0); 65 cnt = 0; 66 s = splimp(); 67 do { 68 if (m->m_off > MMAXOFF) 69 cnt += NMBPG; 70 cnt++; 71 MFREE(m, n); 72 } while (m = n); 73 splx(s); 74 return (cnt); 75 } 76 77 mbufinit() 78 { 79 register struct mbuf *m; 80 register i; 81 82 COUNT(MBUFINIT); 83 m = (struct mbuf *)&netutl[0]; /* ->start of buffer virt mem */ 84 vmemall(&Netmap[0], 2, proc, CSYS); 85 vmaccess(&Netmap[0], m, 2); 86 for (i=0; i < NMBPG; i++) { 87 m->m_off = 0; 88 m_free(m); 89 m++; 90 } 91 pg_alloc(3); 92 mbstat.m_pages = 4; 93 mbstat.m_bufs = 32; 94 mbstat.m_lowat = 16; 95 mbstat.m_hiwat = 32; 96 { int i,j,k,n; 97 n = 32; 98 k = n << 1; 99 if ((i = rmalloc(netmap, n)) == 0) 100 return (0); 101 j = i<<1; 102 m = pftom(i); 103 /* should use vmemall sometimes */ 104 if (memall(&Netmap[j], k, proc, CSYS) == 0) { 105 printf("botch\n"); 106 return; 107 } 108 vmaccess(&Netmap[j], (caddr_t)m, k); 109 for (j=0; j < n; j++) { 110 m->m_off = 0; 111 m->m_next = mpfree; 112 mpfree = m; 113 m += NMBPG; 114 nmpfree++; 115 } 116 } 117 } 118 119 pg_alloc(n) 120 register int n; 121 { 122 register i, j, k; 123 register struct mbuf *m; 124 int bufs, s; 125 126 COUNT(PG_ALLOC); 127 k = n << 1; 128 if ((i = rmalloc(netmap, n)) == 0) 129 return (0); 130 j = i<<1; 131 m = pftom(i); 132 /* should use vmemall sometimes */ 133 if (memall(&Netmap[j], k, proc, CSYS) == 0) 134 return (0); 135 vmaccess(&Netmap[j], (caddr_t)m, k); 136 bufs = n << 3; 137 s = splimp(); 138 for (j=0; j < bufs; j++) { 139 m->m_off = 0; 140 m_free(m); 141 m++; 142 } 143 splx(s); 144 mbstat.m_pages += n; 145 return (1); 146 } 147 148 m_expand() 149 { 150 register i; 151 register struct mbuf *m, *n; 152 int need, needp, needs; 153 154 COUNT(M_EXPAND); 155 needs = need = mbstat.m_hiwat - mbstat.m_bufs; 156 needp = need >> 3; 157 if (pg_alloc(needp)) 158 return (1); 159 for (i=0; i < needp; i++, need -= NMBPG) 160 if (pg_alloc(1) == 0) 161 goto steal; 162 return (need < needs); 163 steal: 164 /* while (not enough) ask protocols to free code */ 165 ; 166 } 167 168 #ifdef notdef 169 m_relse() 170 { 171 172 COUNT(M_RELSE); 173 } 174 #endif 175 176 m_cat(m, n) 177 register struct mbuf *m, *n; 178 { 179 180 while (m->m_next) 181 m = m->m_next; 182 while (n) 183 if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { 184 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len); 185 m->m_len += n->m_len; 186 n = m_free(n); 187 } else { 188 m->m_next = n; 189 m = n; 190 n = m->m_next; 191 } 192 } 193 194 m_adj(mp, len) 195 struct mbuf *mp; 196 register len; 197 { 198 register struct mbuf *m, *n; 199 200 /* 201 for (m = mp; m; m = m->m_next) { 202 printf("a %x %d\n", m, m->m_len); 203 } 204 */ 205 COUNT(M_ADJ); 206 if ((m = mp) == NULL) 207 return; 208 if (len >= 0) { /* adjust from top of msg chain */ 209 while (m != NULL && len > 0) { 210 if (m->m_len <= len) { /* free this mbuf */ 211 len -= m->m_len; 212 m->m_len = 0; 213 m = m->m_next; 214 } else { /* adjust mbuf */ 215 m->m_len -= len; 216 m->m_off += len; 217 break; 218 } 219 } 220 221 } else { /* adjust from bottom of msg chain */ 222 len = -len; 223 while (len > 0 && m->m_len != 0) { 224 /* find end of chain */ 225 while (m != NULL && m->m_len != 0) { 226 n = m; 227 m = m->m_next; 228 } 229 if (n->m_len <= len) { /* last mbuf */ 230 len -= n->m_len; 231 n->m_len = 0; 232 m = mp; 233 } else { /* adjust length */ 234 n->m_len -= len; 235 break; 236 } 237 } 238 } 239 } 240 241 /* 242 * convert mbuf virtual to physical addr for uballoc 243 */ 244 mtophys(m) 245 register struct mbuf *m; 246 { 247 register i; 248 register unsigned long addr; 249 register struct pte *pte; 250 251 COUNT(MTOPHYS); 252 i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT; 253 pte = &Netmap[i]; 254 addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET); 255 return (addr); 256 } 257