Deleted Added
sdiff udiff text old ( 118168 ) new ( 118208 )
full compact
1/*
2 * Copyright (c) 2001-2003
3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 15 unchanged lines hidden (view full) ---

24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * Author: Hartmut Brandt <harti@freebsd.org>
28 *
29 * Fore PCA200E driver for NATM
30 */
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/dev/fatm/if_fatm.c 118168 2003-07-29 14:00:59Z harti $");
33
34#include "opt_inet.h"
35#include "opt_natm.h"
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/malloc.h>
41#include <sys/kernel.h>
42#include <sys/bus.h>
43#include <sys/errno.h>
44#include <sys/conf.h>
45#include <sys/module.h>
46#include <sys/queue.h>
47#include <sys/syslog.h>
48#include <sys/endian.h>
49#include <sys/sysctl.h>
50#include <sys/condvar.h>
51
52#include <sys/sockio.h>
53#include <sys/mbuf.h>
54#include <sys/socket.h>
55
56#include <net/if.h>
57#include <net/if_media.h>
58#include <net/if_atm.h>

--- 456 unchanged lines hidden (view full) ---

515 wakeup(q);
516 }
517 }
518 utopia_reset_media(&sc->utopia);
519 }
520 sc->small_cnt = sc->large_cnt = 0;
521
522 /* Reset vcc info */
523 if (sc->vccs != NULL)
524 for (i = 0; i <= FORE_MAX_VCC; i++)
525 sc->vccs[i].flags = 0;
526
527 sc->open_vccs = 0;
528}
529
530/*
531 * Load the firmware into the board and save the entry point.
532 */
533static uint32_t

--- 907 unchanged lines hidden (view full) ---

1441 * Check the receive queue. Send any received PDU up the protocol stack
1442 * (except when there was an error or the VCI appears to be closed. In this
1443 * case discard the PDU).
1444 */
1445static void
1446fatm_intr_drain_rx(struct fatm_softc *sc)
1447{
1448 struct rxqueue *q;
1449 int stat, mlen, drop;
1450 u_int i;
1451 uint32_t h;
1452 struct mbuf *last, *m0;
1453 struct rpd *rpd;
1454 struct rbuf *rb;
1455 u_int vci, vpi, pt;
1456 struct atm_pseudohdr aph;
1457 struct ifnet *ifp;
1458
1459 for (;;) {
1460 q = GET_QUEUE(sc->rxqueue, struct rxqueue, sc->rxqueue.tail);
1461
1462 H_SYNCSTAT_POSTREAD(sc, q->q.statp);
1463 stat = H_GETSTAT(q->q.statp);
1464
1465 if ((stat & FATM_STAT_COMPLETE) == 0)
1466 break;
1467
1468 rpd = (struct rpd *)q->q.ioblk;
1469 H_SYNCQ_POSTREAD(&sc->rxq_mem, rpd, RPD_SIZE);
1470
1471 rpd->nseg = le32toh(rpd->nseg);
1472 drop = 0;
1473 mlen = 0;
1474 m0 = last = 0;
1475 for (i = 0; i < rpd->nseg; i++) {
1476 rb = sc->rbufs + rpd->segment[i].handle;
1477 if (m0 == NULL) {
1478 m0 = last = rb->m;
1479 } else {
1480 last->m_next = rb->m;

--- 23 unchanged lines hidden (view full) ---

1504 vpi = (h >> 20) & 0xff;
1505 vci = (h >> 4 ) & 0xffff;
1506 pt = (h >> 1 ) & 0x7;
1507
1508 /*
1509 * Locate the VCC this packet belongs to
1510 */
1511 if (!VC_OK(sc, vpi, vci))
1512 drop = 1;
1513 else if ((sc->vccs[vci].flags & FATM_VCC_OPEN) == 0) {
1514 sc->istats.rx_closed++;
1515 drop = 1;
1516 }
1517
1518 DBG(sc, RCV, ("RCV: vc=%u.%u pt=%u mlen=%d %s", vpi, vci,
1519 pt, mlen, drop ? "dropped" : ""));
1520
1521 if (drop) {
1522 m_freem(m0);
1523 } else {
1524 ATM_PH_FLAGS(&aph) = sc->vccs[vci].flags & 0xff;
1525 ATM_PH_VPI(&aph) = vpi;
1526 ATM_PH_SETVCI(&aph, vci);
1527
1528 ifp = &sc->ifatm.ifnet;
1529 ifp->if_ipackets++;
1530
1531 atm_input(ifp, &aph, m0, sc->vccs[vci].rxhand);
1532 }
1533
1534 H_SETSTAT(q->q.statp, FATM_STAT_FREE);
1535 H_SYNCSTAT_PREWRITE(sc, q->q.statp);
1536
1537 WRITE4(sc, q->q.card, q->q.card_ioblk);
1538 BARRIER_W(sc);
1539

--- 350 unchanged lines hidden (view full) ---

1890}
1891
1892/*
1893 * Start output.
1894 *
1895 * Note, that we update the internal statistics without the lock here.
1896 */
1897static int
1898fatm_tx(struct fatm_softc *sc, struct mbuf *m, u_int vpi, u_int vci, u_int mlen)
1899{
1900 struct txqueue *q;
1901 u_int nblks;
1902 int error, aal, nsegs;
1903 struct tpd *tpd;
1904
1905 /*
1906 * Get a queue element.

--- 36 unchanged lines hidden (view full) ---

1943 }
1944 nsegs = tpd->spec;
1945
1946 bus_dmamap_sync(sc->tx_tag, q->map, BUS_DMASYNC_PREWRITE);
1947
1948 /*
1949 * OK. Now go and do it.
1950 */
1951 aal = (sc->vccs[vci].aal == ATMIO_AAL_5) ? 5 : 0;
1952
1953 H_SETSTAT(q->q.statp, FATM_STAT_PENDING);
1954 H_SYNCSTAT_PREWRITE(sc, q->q.statp);
1955 q->m = m;
1956
1957 /*
1958 * If the transmit queue is almost full, schedule a
1959 * transmit interrupt so that transmit descriptors can
1960 * be recycled.
1961 */
1962 H_SETDESC(tpd->spec, TDX_MKSPEC((sc->txcnt >=
1963 (4 * FATM_TX_QLEN) / 5), aal, nsegs, mlen));
1964 H_SETDESC(tpd->atm_header, TDX_MKHDR(vpi, vci, 0, 0));
1965
1966 if (sc->vccs[vci].traffic == ATMIO_TRAFFIC_UBR)
1967 H_SETDESC(tpd->stream, 0);
1968 else {
1969 u_int i;
1970
1971 for (i = 0; i < RATE_TABLE_SIZE; i++)
1972 if (rate_table[i].cell_rate < sc->vccs[vci].pcr)
1973 break;
1974 if (i > 0)
1975 i--;
1976 H_SETDESC(tpd->stream, rate_table[i].ratio);
1977 }
1978 H_SYNCQ_PREWRITE(&sc->txq_mem, tpd, TPD_SIZE);
1979
1980 nblks = TDX_SEGS2BLKS(nsegs);
1981
1982 DBG(sc, XMIT, ("XMIT: mlen=%d spec=0x%x nsegs=%d blocks=%d",
1983 mlen, le32toh(tpd->spec), nsegs, nblks));
1984
1985 WRITE4(sc, q->q.card + 0, q->q.card_ioblk | nblks);
1986 BARRIER_W(sc);
1987
1988 sc->txcnt++;
1989 sc->ifatm.ifnet.if_opackets++;
1990
1991 NEXT_QUEUE_ENTRY(sc->txqueue.head, FATM_TX_QLEN);
1992
1993 return (0);
1994}
1995
1996static void
1997fatm_start(struct ifnet *ifp)
1998{
1999 struct atm_pseudohdr aph;
2000 struct fatm_softc *sc;
2001 struct mbuf *m;
2002 u_int mlen, vpi, vci;
2003
2004 sc = (struct fatm_softc *)ifp->if_softc;
2005
2006 while (1) {
2007 IF_DEQUEUE(&ifp->if_snd, m);
2008 if (m == NULL)
2009 break;
2010

--- 32 unchanged lines hidden (view full) ---

2043 * From here on we need the softc
2044 */
2045 FATM_LOCK(sc);
2046 if (!(ifp->if_flags & IFF_RUNNING)) {
2047 FATM_UNLOCK(sc);
2048 m_freem(m);
2049 break;
2050 }
2051 if (!VC_OK(sc, vpi, vci) ||
2052 !(sc->vccs[vci].flags & FATM_VCC_OPEN)) {
2053 FATM_UNLOCK(sc);
2054 m_freem(m);
2055 continue;
2056 }
2057 if (fatm_tx(sc, m, vpi, vci, mlen)) {
2058 FATM_UNLOCK(sc);
2059 break;
2060 }
2061 FATM_UNLOCK(sc);
2062 }
2063}
2064
2065/*
2066 * Return a table of all currently open VCCs.
2067 */
2068static struct atmio_vcctable *
2069get_vccs(struct fatm_softc *sc, int flags)
2070{
2071 struct atmio_vcctable *vccs;
2072 struct atmio_vcc *v;
2073 u_int i, alloc;
2074
2075 alloc = 10;
2076 vccs = NULL;
2077 for (;;) {
2078 vccs = reallocf(vccs,
2079 sizeof(*vccs) + alloc * sizeof(vccs->vccs[0]),
2080 M_DEVBUF, flags);
2081 if (vccs == NULL)
2082 return (NULL);
2083
2084 vccs->count = 0;
2085 FATM_LOCK(sc);
2086 v = vccs->vccs;
2087 for (i = 0; i < (1U << sc->ifatm.mib.vci_bits); i++) {
2088 if (sc->vccs[i].flags & FATM_VCC_OPEN) {
2089 if (vccs->count++ == alloc) {
2090 alloc *= 2;
2091 break;
2092 }
2093 v->vpi = 0;
2094 v->vci = i;
2095 v->flags = sc->vccs[i].flags;
2096 v->aal = sc->vccs[i].aal;
2097 v->traffic = sc->vccs[i].traffic;
2098 bzero(&v->tparam, sizeof(v->tparam));
2099 v->tparam.pcr = sc->vccs[i].pcr;
2100 v++;
2101 }
2102 }
2103 if (i == (1U << sc->ifatm.mib.vci_bits))
2104 break;
2105 FATM_UNLOCK(sc);
2106 }
2107 FATM_UNLOCK(sc);
2108 return (vccs);
2109}
2110
2111/*
2112 * VCC managment
2113 *
2114 * This may seem complicated. The reason for this is, that we need an
2115 * asynchronuous open/close for the NATM VCCs because our ioctl handler
2116 * is called with the radix node head of the routing table locked. Therefor
2117 * we cannot sleep there and wait for the open/close to succeed. For this
2118 * reason we just initiate the operation from the ioctl.
2119 */

--- 28 unchanged lines hidden (view full) ---

2148 BARRIER_W(sc);
2149 WRITE4(sc, q->q.card + FATMOC_OP, cmd);
2150 BARRIER_W(sc);
2151
2152 return (q);
2153}
2154
2155/*
2156 * Start to open a VCC. This just initiates the operation.
2157 */
2158static int
2159fatm_start_open_vcc(struct fatm_softc *sc, u_int vpi, u_int vci, u_int aal,
2160 u_int traffic, u_int pcr, u_int flags, void *rxhand,
2161 void (*func)(struct fatm_softc *, struct cmdqueue *), struct cmdqueue **qp)
2162{
2163 int error;
2164 uint32_t cmd;
2165 struct cmdqueue *q;
2166
2167 error = 0;
2168
2169 if (!(sc->ifatm.ifnet.if_flags & IFF_RUNNING))
2170 return (EIO);
2171 if (!VC_OK(sc, vpi, vci) ||
2172 (aal != ATMIO_AAL_0 && aal != ATMIO_AAL_5) ||
2173 (traffic != ATMIO_TRAFFIC_UBR && traffic != ATMIO_TRAFFIC_CBR))
2174 return (EINVAL);
2175 if (sc->vccs[vci].flags & FATM_VCC_BUSY)
2176 return (EBUSY);
2177
2178 /* Command and buffer strategy */
2179 cmd = FATM_OP_ACTIVATE_VCIN | FATM_OP_INTERRUPT_SEL | (0 << 16);
2180 if (aal == ATMIO_AAL_0)
2181 cmd |= (0 << 8);
2182 else
2183 cmd |= (5 << 8);
2184
2185 if ((q = fatm_start_vcc(sc, vpi, vci, cmd, 1, func)) == NULL)
2186 return (EIO);
2187 if (qp != NULL)
2188 *qp = q;
2189
2190 sc->vccs[vci].aal = aal;
2191 sc->vccs[vci].flags = flags | FATM_VCC_TRY_OPEN;
2192 sc->vccs[vci].rxhand = rxhand;
2193 sc->vccs[vci].pcr = pcr;
2194 sc->vccs[vci].traffic = traffic;
2195
2196 return (0);
2197}
2198
2199/*
2200 * Initiate closing a VCC
2201 */
2202static int
2203fatm_start_close_vcc(struct fatm_softc *sc, u_int vpi, u_int vci,
2204 void (*func)(struct fatm_softc *, struct cmdqueue *), struct cmdqueue **qp)
2205{
2206 int error;
2207 struct cmdqueue *q;
2208
2209 error = 0;
2210
2211 if (!(sc->ifatm.ifnet.if_flags & IFF_RUNNING))
2212 return (EIO);
2213 if (!VC_OK(sc, vpi, vci))
2214 return (EINVAL);
2215 if (!(sc->vccs[vci].flags & (FATM_VCC_OPEN | FATM_VCC_TRY_OPEN)))
2216 return (ENOENT);
2217
2218 if ((q = fatm_start_vcc(sc, vpi, vci,
2219 FATM_OP_DEACTIVATE_VCIN | FATM_OP_INTERRUPT_SEL, 1, func)) == NULL)
2220 return (EIO);
2221
2222 if (qp != NULL)
2223 *qp = q;
2224
2225 sc->vccs[vci].flags &= ~(FATM_VCC_OPEN | FATM_VCC_TRY_OPEN);
2226 sc->vccs[vci].flags |= FATM_VCC_TRY_CLOSE;
2227
2228 return (0);
2229}
2230
2231/*
2232 * Wait on the queue entry until the VCC is opened/closed.
2233 */
2234static int
2235fatm_waitvcc(struct fatm_softc *sc, struct cmdqueue *q)
2236{

--- 5 unchanged lines hidden (view full) ---

2242 error = msleep(q, &sc->mtx, PZERO | PCATCH, "fatm_vci", hz);
2243
2244 if (error != 0)
2245 return (error);
2246 return (q->error);
2247}
2248
2249/*
2250 * The VC has been opened/closed and somebody has been waiting for this.
2251 * Wake him up.
2252 */
2253static void
2254fatm_cmd_complete(struct fatm_softc *sc, struct cmdqueue *q)
2255{
2256
2257 H_SYNCSTAT_POSTREAD(sc, q->q.statp);
2258 if (H_GETSTAT(q->q.statp) & FATM_STAT_ERROR) {
2259 sc->istats.get_stat_errors++;
2260 q->error = EIO;
2261 }
2262 wakeup(q);
2263}
2264
2265/*
2266 * Open a vcc and wait for completion
2267 */
2268static int
2269fatm_open_vcc(struct fatm_softc *sc, u_int vpi, u_int vci, u_int flags,
2270 u_int aal, u_int traffic, u_int pcr, void *rxhand)
2271{
2272 int error;
2273 struct cmdqueue *q;
2274
2275 error = 0;
2276
2277 FATM_LOCK(sc);
2278 error = fatm_start_open_vcc(sc, vpi, vci, aal, traffic, pcr,
2279 flags, rxhand, fatm_cmd_complete, &q);
2280 if (error != 0) {
2281 FATM_UNLOCK(sc);
2282 return (error);
2283 }
2284 error = fatm_waitvcc(sc, q);
2285
2286 if (error == 0) {
2287 sc->vccs[vci].flags &= ~FATM_VCC_TRY_OPEN;
2288 sc->vccs[vci].flags |= FATM_VCC_OPEN;
2289 sc->open_vccs++;
2290
2291 /* inform management if this is not an NG
2292 * VCC or it's an NG PVC. */
2293 if (!(sc->vccs[vci].flags & ATMIO_FLAG_NG) ||
2294 (sc->vccs[vci].flags & ATMIO_FLAG_PVC))
2295 ATMEV_SEND_VCC_CHANGED(&sc->ifatm, 0, vci, 1);
2296 } else
2297 bzero(&sc->vccs[vci], sizeof(sc->vccs[vci]));
2298
2299 FATM_UNLOCK(sc);
2300 return (error);
2301}
2302
2303/*
2304 * Close a VCC synchronuosly
2305 */
2306static int
2307fatm_close_vcc(struct fatm_softc *sc, u_int vpi, u_int vci)
2308{
2309 int error;
2310 struct cmdqueue *q;
2311
2312 error = 0;
2313
2314 FATM_LOCK(sc);
2315 error = fatm_start_close_vcc(sc, vpi, vci, fatm_cmd_complete, &q);
2316 if (error != 0) {
2317 FATM_UNLOCK(sc);
2318 return (error);
2319 }
2320 error = fatm_waitvcc(sc, q);
2321
2322 if (error == 0) {
2323 /* inform management of this is not an NG
2324 * VCC or it's an NG PVC. */
2325 if (!(sc->vccs[vci].flags & ATMIO_FLAG_NG) ||
2326 (sc->vccs[vci].flags & ATMIO_FLAG_PVC))
2327 ATMEV_SEND_VCC_CHANGED(&sc->ifatm, 0, vci, 0);
2328
2329 bzero(&sc->vccs[vci], sizeof(sc->vccs[vci]));
2330 sc->open_vccs--;
2331 }
2332
2333 FATM_UNLOCK(sc);
2334 return (error);
2335}
2336
2337/*
2338 * The VC has been opened.
2339 */
2340static void
2341fatm_open_complete(struct fatm_softc *sc, struct cmdqueue *q)
2342{
2343 u_int vci;
2344
2345 vci = GETVCI(READ4(sc, q->q.card + FATMOC_ACTIN_VPVC));
2346 H_SYNCSTAT_POSTREAD(sc, q->q.statp);
2347 if (H_GETSTAT(q->q.statp) & FATM_STAT_ERROR) {
2348 sc->istats.get_stat_errors++;
2349 bzero(&sc->vccs[vci], sizeof(sc->vccs[vci]));
2350 if_printf(&sc->ifatm.ifnet, "opening VCI %u failed\n", vci);
2351 return;
2352 }
2353
2354 sc->vccs[vci].flags &= ~FATM_VCC_TRY_OPEN;
2355 sc->vccs[vci].flags |= FATM_VCC_OPEN;
2356 sc->open_vccs++;
2357
2358 /* inform management if this is not an NG
2359 * VCC or it's an NG PVC. */
2360 if (!(sc->vccs[vci].flags & ATMIO_FLAG_NG) ||
2361 (sc->vccs[vci].flags & ATMIO_FLAG_PVC))
2362 ATMEV_SEND_VCC_CHANGED(&sc->ifatm, 0, vci, 1);
2363}
2364
2365/*
2366 * The VC has been closed.
2367 */
2368static void
2369fatm_close_complete(struct fatm_softc *sc, struct cmdqueue *q)
2370{
2371 u_int vci;
2372
2373 vci = GETVCI(READ4(sc, q->q.card + FATMOC_ACTIN_VPVC));
2374 H_SYNCSTAT_POSTREAD(sc, q->q.statp);
2375 if (H_GETSTAT(q->q.statp) & FATM_STAT_ERROR) {
2376 sc->istats.get_stat_errors++;
2377 /* keep the VCC in that state */
2378 if_printf(&sc->ifatm.ifnet, "closing VCI %u failed\n", vci);
2379 return;
2380 }
2381
2382 /* inform management of this is not an NG
2383 * VCC or it's an NG PVC. */
2384 if (!(sc->vccs[vci].flags & ATMIO_FLAG_NG) ||
2385 (sc->vccs[vci].flags & ATMIO_FLAG_PVC))
2386 ATMEV_SEND_VCC_CHANGED(&sc->ifatm, 0, vci, 0);
2387
2388 bzero(&sc->vccs[vci], sizeof(sc->vccs[vci]));
2389 sc->open_vccs--;
2390}
2391
2392/*
2393 * Open a vcc but don't wait.
2394 */
2395static int
2396fatm_open_vcc_nowait(struct fatm_softc *sc, u_int vpi, u_int vci, u_int flags,
2397 u_int aal, void *rxhand)
2398{
2399 int error;
2400
2401 FATM_LOCK(sc);
2402 error = fatm_start_open_vcc(sc, vpi, vci, aal, ATMIO_TRAFFIC_UBR, 0,
2403 flags, rxhand, fatm_open_complete, NULL);
2404 FATM_UNLOCK(sc);
2405 return (error);
2406}
2407
2408/*
2409 * Close a VCC but don't wait
2410 */
2411static int
2412fatm_close_vcc_nowait(struct fatm_softc *sc, u_int vpi, u_int vci)
2413{
2414 int error;
2415
2416 FATM_LOCK(sc);
2417 error = fatm_start_close_vcc(sc, vpi, vci, fatm_close_complete, NULL);
2418 FATM_UNLOCK(sc);
2419 return (error);
2420}
2421
2422/*
2423 * IOCTL handler
2424 */
2425static int
2426fatm_ioctl(struct ifnet *ifp, u_long cmd, caddr_t arg)
2427{
2428 int error;
2429 struct fatm_softc *sc = ifp->if_softc;
2430 struct ifaddr *ifa = (struct ifaddr *)arg;
2431 struct ifreq *ifr = (struct ifreq *)arg;
2432 struct atmio_closevcc *cl = (struct atmio_closevcc *)arg;
2433 struct atmio_openvcc *op = (struct atmio_openvcc *)arg;
2434 struct atm_pseudoioctl *pa = (struct atm_pseudoioctl *)arg;
2435 struct atmio_vcctable *vtab;
2436
2437 error = 0;
2438 switch (cmd) {
2439
2440 case SIOCATMENA: /* internal NATM use */
2441 error = fatm_open_vcc_nowait(sc, ATM_PH_VPI(&pa->aph),
2442 ATM_PH_VCI(&pa->aph), ATM_PH_FLAGS(&pa->aph),
2443 (ATM_PH_FLAGS(&pa->aph) & ATM_PH_AAL5) ? ATMIO_AAL_5 :
2444 ATMIO_AAL_0, pa->rxhand);
2445 break;
2446
2447 case SIOCATMDIS: /* internal NATM use */
2448 error = fatm_close_vcc_nowait(sc, ATM_PH_VPI(&pa->aph),
2449 ATM_PH_VCI(&pa->aph));
2450 break;
2451
2452 case SIOCATMOPENVCC:
2453 error = fatm_open_vcc(sc, op->param.vpi, op->param.vci,
2454 op->param.flags, op->param.aal, op->param.traffic,
2455 op->param.tparam.pcr, op->rxhand);
2456 break;
2457
2458 case SIOCATMCLOSEVCC:
2459 error = fatm_close_vcc(sc, cl->vpi, cl->vci);
2460 break;
2461
2462 case SIOCSIFADDR:
2463 FATM_LOCK(sc);
2464 ifp->if_flags |= IFF_UP;
2465 if (!(ifp->if_flags & IFF_RUNNING))
2466 fatm_init_locked(sc);
2467 switch (ifa->ifa_addr->sa_family) {

--- 28 unchanged lines hidden (view full) ---

2496 if (ifp->if_flags & IFF_RUNNING)
2497 error = ifmedia_ioctl(ifp, ifr, &sc->media, cmd);
2498 else
2499 error = EINVAL;
2500 break;
2501
2502 case SIOCATMGVCCS:
2503 /* return vcc table */
2504 vtab = get_vccs(sc, M_WAITOK);
2505 if (vtab == NULL) {
2506 error = ENOMEM;
2507 break;
2508 }
2509 error = copyout(vtab, ifr->ifr_data, sizeof(*vtab) +
2510 vtab->count * sizeof(vtab->vccs[0]));
2511 free(vtab, M_DEVBUF);
2512 break;
2513
2514 case SIOCATMGETVCCS: /* internal netgraph use */
2515 vtab = get_vccs(sc, M_NOWAIT);
2516 if (vtab == NULL) {
2517 error = ENOMEM;
2518 break;
2519 }
2520 *(void **)arg = vtab;
2521 break;
2522
2523 default:

--- 45 unchanged lines hidden (view full) ---

2569 }
2570 }
2571
2572 while ((rb = LIST_FIRST(&sc->rbuf_free)) != NULL) {
2573 bus_dmamap_destroy(sc->rbuf_tag, rb->map);
2574 LIST_REMOVE(rb, link);
2575 }
2576
2577 free(sc->rbufs, M_DEVBUF);
2578 free(sc->vccs, M_DEVBUF);
2579
2580 free(sc->l1queue.chunk, M_DEVBUF);
2581 free(sc->s1queue.chunk, M_DEVBUF);
2582 free(sc->rxqueue.chunk, M_DEVBUF);
2583 free(sc->txqueue.chunk, M_DEVBUF);
2584 free(sc->cmdqueue.chunk, M_DEVBUF);
2585
2586 destroy_dma_memory(&sc->reg_mem);
2587 destroy_dma_memory(&sc->sadi_mem);
2588 destroy_dma_memory(&sc->prom_mem);
2589#ifdef TEST_DMA_SYNC
2590 destroy_dma_memoryX(&sc->s1q_mem);
2591 destroy_dma_memoryX(&sc->l1q_mem);
2592 destroy_dma_memoryX(&sc->rxq_mem);

--- 371 unchanged lines hidden (view full) ---

2964 M_DEVBUF, M_ZERO | M_WAITOK);
2965 sc->rxqueue.chunk = malloc(FATM_RX_QLEN * sizeof(struct rxqueue),
2966 M_DEVBUF, M_ZERO | M_WAITOK);
2967 sc->s1queue.chunk = malloc(SMALL_SUPPLY_QLEN * sizeof(struct supqueue),
2968 M_DEVBUF, M_ZERO | M_WAITOK);
2969 sc->l1queue.chunk = malloc(LARGE_SUPPLY_QLEN * sizeof(struct supqueue),
2970 M_DEVBUF, M_ZERO | M_WAITOK);
2971
2972 sc->vccs = malloc((FORE_MAX_VCC + 1) * sizeof(struct card_vcc),
2973 M_DEVBUF, M_ZERO | M_WAITOK);
2974
2975 /*
2976 * Allocate memory for the receive buffer headers. The total number
2977 * of headers should probably also include the maximum number of
2978 * buffers on the receive queue.
2979 */
2980 sc->rbuf_total = SMALL_POOL_SIZE + LARGE_POOL_SIZE;
2981 sc->rbufs = malloc(sc->rbuf_total * sizeof(struct rbuf),

--- 94 unchanged lines hidden ---