Date: Tue, 27 Sep 2005 17:46:41 GMT From: Peter Wemm <peter@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 84363 for review Message-ID: <200509271746.j8RHkfuR018378@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=84363 Change 84363 by peter@peter_daintree on 2005/09/27 17:45:52 IFC @84362 Affected files ... .. //depot/projects/hammer/etc/rc.d/localpkg#4 integrate .. //depot/projects/hammer/release/pc98/boot_crunch.conf#7 integrate .. //depot/projects/hammer/sys/alpha/include/atomic.h#11 integrate .. //depot/projects/hammer/sys/amd64/include/atomic.h#23 integrate .. //depot/projects/hammer/sys/arm/include/atomic.h#11 integrate .. //depot/projects/hammer/sys/dev/cardbus/cardbus.c#20 integrate .. //depot/projects/hammer/sys/dev/cp/if_cp.c#21 integrate .. //depot/projects/hammer/sys/dev/ctau/if_ct.c#22 integrate .. //depot/projects/hammer/sys/dev/cx/if_cx.c#28 integrate .. //depot/projects/hammer/sys/dev/fxp/if_fxp.c#51 integrate .. //depot/projects/hammer/sys/dev/fxp/if_fxpvar.h#15 integrate .. //depot/projects/hammer/sys/dev/ips/ips_commands.c#14 integrate .. //depot/projects/hammer/sys/fs/fifofs/fifo_vnops.c#32 integrate .. //depot/projects/hammer/sys/i386/include/atomic.h#11 integrate .. //depot/projects/hammer/sys/ia64/include/atomic.h#4 integrate .. //depot/projects/hammer/sys/kern/init_sysent.c#47 integrate .. //depot/projects/hammer/sys/kern/syscalls.c#45 integrate .. //depot/projects/hammer/sys/kern/syscalls.master#45 integrate .. //depot/projects/hammer/sys/modules/Makefile#86 integrate .. //depot/projects/hammer/sys/pc98/conf/GENERIC#35 integrate .. //depot/projects/hammer/sys/pc98/conf/GENERIC.hints#12 integrate .. //depot/projects/hammer/sys/pc98/conf/NOTES#49 integrate .. //depot/projects/hammer/sys/powerpc/include/atomic.h#8 integrate .. //depot/projects/hammer/sys/sparc64/include/atomic.h#5 integrate .. //depot/projects/hammer/sys/sys/syscall.h#44 integrate .. //depot/projects/hammer/sys/sys/syscall.mk#44 integrate .. //depot/projects/hammer/sys/sys/sysproto.h#44 integrate .. //depot/projects/hammer/usr.bin/make/make.1#25 integrate .. //depot/projects/hammer/usr.bin/netstat/if.c#10 integrate .. //depot/projects/hammer/usr.sbin/sysinstall/Makefile#10 integrate .. //depot/projects/hammer/usr.sbin/sysinstall/sysinstall.h#20 integrate Differences ... ==== //depot/projects/hammer/etc/rc.d/localpkg#4 (text+ko) ==== @@ -1,6 +1,6 @@ #!/bin/sh # -# $FreeBSD: src/etc/rc.d/localpkg,v 1.5 2004/10/07 13:55:26 mtm Exp $ +# $FreeBSD: src/etc/rc.d/localpkg,v 1.6 2005/09/27 02:05:55 brooks Exp $ # # PROVIDE: localpkg @@ -53,13 +53,12 @@ pkg_stop() { - echo -n 'Shutting down daemon processes:' - # For each dir in $local_startup, search for init scripts matching *.sh case ${local_startup} in [Nn][Oo] | '') ;; *) + echo -n 'Shutting down daemon processes:' slist="" if [ -z "${script_name_sep}" ]; then script_name_sep=" " ==== //depot/projects/hammer/release/pc98/boot_crunch.conf#7 (text+ko) ==== @@ -1,4 +1,4 @@ -# $FreeBSD: src/release/pc98/boot_crunch.conf,v 1.59 2004/10/01 07:54:37 ru Exp $ +# $FreeBSD: src/release/pc98/boot_crunch.conf,v 1.60 2005/09/27 13:10:23 nyan Exp $ buildopts -DRELEASE_CRUNCH -Dlint @@ -34,10 +34,8 @@ ln minigzip gunzip ln minigzip zcat -srcdirs /usr/src/usr.sbin /usr/src/usr.sbin/pccard +srcdirs /usr/src/usr.sbin progs arp -progs pccardc -progs pccardd progs ppp progs sysinstall ==== //depot/projects/hammer/sys/alpha/include/atomic.h#11 (text+ko) ==== @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/alpha/include/atomic.h,v 1.23 2005/09/15 19:31:22 jhb Exp $ + * $FreeBSD: src/sys/alpha/include/atomic.h,v 1.24 2005/09/27 17:39:09 jhb Exp $ */ #ifndef _MACHINE_ATOMIC_H_ @@ -365,6 +365,27 @@ return (atomic_cmpset_64(p, cmpval, newval)); } +/* + * Atomically add the value of v to the integer pointed to by p and return + * the previous value of *p. + */ +static __inline u_int +atomic_fetchadd_32(volatile u_int32_t *p, u_int32_t v) +{ + u_int32_t value, temp; + +#ifdef __GNUCLIKE_ASM + __asm __volatile ( + "1:\tldl_l %0, %1\n\t" /* load old value */ + "addl %0, %3, %2\n\t" /* calculate new value */ + "stl_c %2, %1\n\t" /* attempt to store */ + "beq %2, 1b\n" /* spin if failed */ + : "=&r" (value), "=m" (*p), "=r" (temp) + : "r" (v), "m" (*p)); +#endif + return (value); +} + /* Operations on chars. */ #define atomic_set_char atomic_set_8 #define atomic_set_acq_char atomic_set_acq_8 @@ -412,6 +433,7 @@ #define atomic_load_acq_int atomic_load_acq_32 #define atomic_store_rel_int atomic_store_rel_32 #define atomic_readandclear_int atomic_readandclear_32 +#define atomic_fetchadd_int atomic_fetchadd_32 /* Operations on longs. */ #define atomic_set_long atomic_set_64 ==== //depot/projects/hammer/sys/amd64/include/atomic.h#23 (text+ko) ==== @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/amd64/include/atomic.h,v 1.38 2005/09/15 19:31:22 jhb Exp $ + * $FreeBSD: src/sys/amd64/include/atomic.h,v 1.39 2005/09/27 17:39:10 jhb Exp $ */ #ifndef _MACHINE_ATOMIC_H_ #define _MACHINE_ATOMIC_H_ @@ -73,6 +73,7 @@ int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src); int atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src); +u_int atomic_fetchadd_int(volatile u_int *p, u_int v); #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ @@ -154,6 +155,25 @@ return (res); } +/* + * Atomically add the value of v to the integer pointed to by p and return + * the previous value of *p. + */ +static __inline u_int +atomic_fetchadd_int(volatile u_int *p, u_int v) +{ + + __asm __volatile ( + " " __XSTRING(MPLOCKED) " " + " xaddl %0, %1 ; " + "# atomic_fetchadd_int" + : "+r" (v), /* 0 (result) */ + "=m" (*p) /* 1 */ + : "m" (*p)); /* 2 */ + + return (v); +} + #if defined(_KERNEL) && !defined(SMP) /* @@ -375,6 +395,7 @@ #define atomic_cmpset_acq_32 atomic_cmpset_acq_int #define atomic_cmpset_rel_32 atomic_cmpset_rel_int #define atomic_readandclear_32 atomic_readandclear_int +#define atomic_fetchadd_32 atomic_fetchadd_int /* Operations on 64-bit quad words. */ #define atomic_set_64 atomic_set_long ==== //depot/projects/hammer/sys/arm/include/atomic.h#11 (text+ko) ==== @@ -33,7 +33,7 @@ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/arm/include/atomic.h,v 1.10 2005/07/27 20:01:44 jhb Exp $ + * $FreeBSD: src/sys/arm/include/atomic.h,v 1.11 2005/09/27 17:39:10 jhb Exp $ */ #ifndef _MACHINE_ATOMIC_H_ @@ -127,6 +127,19 @@ __with_interrupts_disabled(*p -= val); } +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t value; + + __with_interrupts_disabled( + { + value = *p; + *p += v; + }); + return (value); +} + #else /* !_KERNEL */ static __inline u_int32_t @@ -240,6 +253,30 @@ : "=r" (ras_start), "=r" (start), "+r" (address), "+r" (clearmask)); } + +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t ras_start, start; + + __asm __volatile("1:\n" + "mov %0, #0xe0000008\n" + "adr %1, 2f\n" + "str %1, [%0]\n" + "adr %1, 1b\n" + "mov %0, #0xe0000004\n" + "str %1, [%0]\n" + "ldr %1, %2\n" + "add %3, %1, %3\n" + "str %3, %2\n" + "2:\n" + "mov %3, #0\n" + "str %3, [%0]\n" + : "=r" (ras_start), "=r" (start), "=m" (*p), "+r" (v)); + return (start); +} + + #endif /* _KERNEL */ static __inline int @@ -291,5 +328,6 @@ #define atomic_store_ptr atomic_store_32 #define atomic_cmpset_ptr atomic_cmpset_32 #define atomic_set_ptr atomic_set_32 +#define atomic_fetchadd_int atomic_fetchadd_32 #endif /* _MACHINE_ATOMIC_H_ */ ==== //depot/projects/hammer/sys/dev/cardbus/cardbus.c#20 (text+ko) ==== @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/dev/cardbus/cardbus.c,v 1.52 2005/03/18 05:19:49 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/cardbus/cardbus.c,v 1.53 2005/09/27 13:33:46 ru Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -360,8 +360,8 @@ bus_release_resource(cbdev, SYS_RES_IRQ, rid, res); resource_list_add(&dinfo->pci.resources, SYS_RES_IRQ, rid, start, end, 1); - dinfo->pci.cfg.intline = rman_get_start(res); - pci_write_config(child, PCIR_INTLINE, rman_get_start(res), 1); + dinfo->pci.cfg.intline = start; + pci_write_config(child, PCIR_INTLINE, start, 1); free(barlist, M_DEVBUF); return (0); ==== //depot/projects/hammer/sys/dev/cp/if_cp.c#21 (text+ko) ==== @@ -22,7 +22,7 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD: src/sys/dev/cp/if_cp.c,v 1.27 2005/09/19 03:10:16 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/cp/if_cp.c,v 1.29 2005/09/27 16:57:44 rik Exp $"); #include <sys/param.h> #include <sys/ucred.h> @@ -184,6 +184,817 @@ static int cp_destroy = 0; +static int cp_open (struct cdev *dev, int oflags, int devtype, struct thread *td); +static int cp_close (struct cdev *dev, int fflag, int devtype, struct thread *td); +static int cp_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td); +static struct cdevsw cp_cdevsw = { + .d_version = D_VERSION, + .d_open = cp_open, + .d_close = cp_close, + .d_ioctl = cp_ioctl, + .d_name = "cp", + .d_flags = D_NEEDGIANT, +}; + +/* + * Print the mbuf chain, for debug purposes only. + */ +static void printmbuf (struct mbuf *m) +{ + printf ("mbuf:"); + for (; m; m=m->m_next) { + if (m->m_flags & M_PKTHDR) + printf (" HDR %d:", m->m_pkthdr.len); + if (m->m_flags & M_EXT) + printf (" EXT:"); + printf (" %d", m->m_len); + } + printf ("\n"); +} + +/* + * Make an mbuf from data. + */ +static struct mbuf *makembuf (void *buf, unsigned len) +{ + struct mbuf *m; + + MGETHDR (m, M_DONTWAIT, MT_DATA); + if (! m) + return 0; + MCLGET (m, M_DONTWAIT); + if (! (m->m_flags & M_EXT)) { + m_freem (m); + return 0; + } + m->m_pkthdr.len = m->m_len = len; + bcopy (buf, mtod (m, caddr_t), len); + return m; +} + +static int cp_probe (device_t dev) +{ + if ((pci_get_vendor (dev) == cp_vendor_id) && + (pci_get_device (dev) == cp_device_id)) { + device_set_desc (dev, "Cronyx-Tau-PCI serial adapter"); + return BUS_PROBE_DEFAULT; + } + return ENXIO; +} + +static void cp_timeout (void *arg) +{ + drv_t *d; + int s, i, k; + + for (i = 0; i < NBRD; ++i) { + if (adapter[i] == NULL) + continue; + for (k = 0; k < NCHAN; ++k) { + s = splimp (); + if (cp_destroy) { + splx (s); + return; + } + d = channel[i * NCHAN + k]; + if (!d) { + splx (s); + continue; + } + CP_LOCK ((bdrv_t *)d->board->sys); + switch (d->chan->type) { + case T_G703: + cp_g703_timer (d->chan); + break; + case T_E1: + cp_e1_timer (d->chan); + break; + case T_E3: + case T_T3: + case T_STS1: + cp_e3_timer (d->chan); + break; + default: + break; + } + CP_UNLOCK ((bdrv_t *)d->board->sys); + splx (s); + } + } + s = splimp (); + if (!cp_destroy) + callout_reset (&timeout_handle, hz, cp_timeout, 0); + splx (s); +} + +static void cp_led_off (void *arg) +{ + cp_board_t *b = arg; + bdrv_t *bd = (bdrv_t *) b->sys; + int s; + s = splimp (); + if (cp_destroy) { + splx (s); + return; + } + CP_LOCK (bd); + cp_led (b, 0); + CP_UNLOCK (bd); + splx (s); +} + +static void cp_intr (void *arg) +{ + bdrv_t *bd = arg; + cp_board_t *b = bd->board; +#ifndef NETGRAPH + int i; +#endif + int s = splimp (); + if (cp_destroy) { + splx (s); + return; + } + CP_LOCK (bd); + /* Check if we are ready */ + if (b->sys == NULL) { + /* Not we are not, just cleanup. */ + cp_interrupt_poll (b, 1); + CP_UNLOCK (bd); + return; + } + /* Turn LED on. */ + cp_led (b, 1); + + cp_interrupt (b); + + /* Turn LED off 50 msec later. */ + callout_reset (&led_timo[b->num], hz/20, cp_led_off, b); + CP_UNLOCK (bd); + splx (s); + +#ifndef NETGRAPH + /* Pass packets in a lock-free state */ + for (i = 0; i < NCHAN && b->chan[i].type; i++) { + drv_t *d = b->chan[i].sys; + struct mbuf *m; + if (!d || !d->running) + continue; + while (_IF_QLEN(&d->queue)) { + IF_DEQUEUE (&d->queue,m); + if (!m) + continue; + sppp_input (d->ifp, m); + } + } +#endif +} + +static void +cp_bus_dmamap_addr (void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + unsigned long *addr; + + if (error) + return; + + KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); + addr = arg; + *addr = segs->ds_addr; +} + +static int +cp_bus_dma_mem_alloc (int bnum, int cnum, cp_dma_mem_t *dmem) +{ + int error; + + error = bus_dma_tag_create (NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, NULL, NULL, dmem->size, 1, + dmem->size, 0, NULL, NULL, &dmem->dmat); + if (error) { + if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); + else printf ("cp%d: ", bnum); + printf ("couldn't allocate tag for dma memory\n"); + return 0; + } + error = bus_dmamem_alloc (dmem->dmat, (void **)&dmem->virt, + BUS_DMA_NOWAIT | BUS_DMA_ZERO, &dmem->mapp); + if (error) { + if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); + else printf ("cp%d: ", bnum); + printf ("couldn't allocate mem for dma memory\n"); + bus_dma_tag_destroy (dmem->dmat); + return 0; + } + error = bus_dmamap_load (dmem->dmat, dmem->mapp, dmem->virt, + dmem->size, cp_bus_dmamap_addr, &dmem->phys, 0); + if (error) { + if (cnum >= 0) printf ("cp%d-%d: ", bnum, cnum); + else printf ("cp%d: ", bnum); + printf ("couldn't load mem map for dma memory\n"); + bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); + bus_dma_tag_destroy (dmem->dmat); + return 0; + } + return 1; +} + +static void +cp_bus_dma_mem_free (cp_dma_mem_t *dmem) +{ + bus_dmamap_unload (dmem->dmat, dmem->mapp); + bus_dmamem_free (dmem->dmat, dmem->virt, dmem->mapp); + bus_dma_tag_destroy (dmem->dmat); +} + +/* + * Called if the probe succeeded. + */ +static int cp_attach (device_t dev) +{ + bdrv_t *bd = device_get_softc (dev); + int unit = device_get_unit (dev); + char *cp_ln = CP_LOCK_NAME; + unsigned short res; + vm_offset_t vbase; + int rid, error; + cp_board_t *b; + cp_chan_t *c; + drv_t *d; + int s = splimp (); + + b = malloc (sizeof(cp_board_t), M_DEVBUF, M_WAITOK); + if (!b) { + printf ("cp%d: couldn't allocate memory\n", unit); + splx (s); + return (ENXIO); + } + bzero (b, sizeof(cp_board_t)); + + bd->board = b; + rid = PCIR_BAR(0); + bd->cp_res = bus_alloc_resource (dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE); + if (! bd->cp_res) { + printf ("cp%d: cannot map memory\n", unit); + free (b, M_DEVBUF); + splx (s); + return (ENXIO); + } + vbase = (vm_offset_t) rman_get_virtual (bd->cp_res); + + cp_ln[2] = '0' + unit; + mtx_init (&bd->cp_mtx, cp_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE); + res = cp_init (b, unit, (u_char*) vbase); + if (res) { + printf ("cp%d: can't init, error code:%x\n", unit, res); + bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); + free (b, M_DEVBUF); + splx (s); + return (ENXIO); + } + + bd->dmamem.size = sizeof(cp_qbuf_t); + if (! cp_bus_dma_mem_alloc (unit, -1, &bd->dmamem)) { + free (b, M_DEVBUF); + splx (s); + return (ENXIO); + } + CP_LOCK (bd); + cp_reset (b, bd->dmamem.virt, bd->dmamem.phys); + CP_UNLOCK (bd); + + rid = 0; + bd->cp_irq = bus_alloc_resource (dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (! bd->cp_irq) { + cp_destroy = 1; + printf ("cp%d: cannot map interrupt\n", unit); + bus_release_resource (dev, SYS_RES_MEMORY, + PCIR_BAR(0), bd->cp_res); + mtx_destroy (&bd->cp_mtx); + free (b, M_DEVBUF); + splx (s); + return (ENXIO); + } + callout_init (&led_timo[unit], cp_mpsafenet ? CALLOUT_MPSAFE : 0); + error = bus_setup_intr (dev, bd->cp_irq, + INTR_TYPE_NET|(cp_mpsafenet?INTR_MPSAFE:0), + cp_intr, bd, &bd->cp_intrhand); + if (error) { + cp_destroy = 1; + printf ("cp%d: cannot set up irq\n", unit); + bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); + bus_release_resource (dev, SYS_RES_MEMORY, + PCIR_BAR(0), bd->cp_res); + mtx_destroy (&bd->cp_mtx); + free (b, M_DEVBUF); + splx (s); + return (ENXIO); + } + printf ("cp%d: %s, clock %ld MHz\n", unit, b->name, b->osc / 1000000); + + for (c = b->chan; c < b->chan + NCHAN; ++c) { + if (! c->type) + continue; + d = &bd->channel[c->num]; + d->dmamem.size = sizeof(cp_buf_t); + if (! cp_bus_dma_mem_alloc (unit, c->num, &d->dmamem)) + continue; + channel [b->num*NCHAN + c->num] = d; + sprintf (d->name, "cp%d.%d", b->num, c->num); + d->board = b; + d->chan = c; + c->sys = d; +#ifdef NETGRAPH + if (ng_make_node_common (&typestruct, &d->node) != 0) { + printf ("%s: cannot make common node\n", d->name); + d->node = NULL; + continue; + } + NG_NODE_SET_PRIVATE (d->node, d); + sprintf (d->nodename, "%s%d", NG_CP_NODE_TYPE, + c->board->num*NCHAN + c->num); + if (ng_name_node (d->node, d->nodename)) { + printf ("%s: cannot name node\n", d->nodename); + NG_NODE_UNREF (d->node); + continue; + } + d->queue.ifq_maxlen = IFQ_MAXLEN; + d->hi_queue.ifq_maxlen = IFQ_MAXLEN; + mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); + mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); + callout_init (&d->timeout_handle, + cp_mpsafenet ? CALLOUT_MPSAFE : 0); +#else /*NETGRAPH*/ + d->ifp = if_alloc(IFT_PPP); + if (d->ifp == NULL) { + printf ("%s: cannot if_alloc() interface\n", d->name); + continue; + } + d->ifp->if_softc = d; + if_initname (d->ifp, "cp", b->num * NCHAN + c->num); + d->ifp->if_mtu = PP_MTU; + d->ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; + if (!cp_mpsafenet) + d->ifp->if_flags |= IFF_NEEDSGIANT; + d->ifp->if_ioctl = cp_sioctl; + d->ifp->if_start = cp_ifstart; + d->ifp->if_watchdog = cp_ifwatchdog; + d->ifp->if_init = cp_initialize; + d->queue.ifq_maxlen = NRBUF; + mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); + sppp_attach (d->ifp); + if_attach (d->ifp); + IFP2SP(d->ifp)->pp_tlf = cp_tlf; + IFP2SP(d->ifp)->pp_tls = cp_tls; + /* If BPF is in the kernel, call the attach for it. + * The header size of PPP or Cisco/HDLC is 4 bytes. */ + bpfattach (d->ifp, DLT_PPP, 4); +#endif /*NETGRAPH*/ + cp_start_e1 (c); + cp_start_chan (c, 1, 1, d->dmamem.virt, d->dmamem.phys); + + /* Register callback functions. */ + cp_register_transmit (c, &cp_transmit); + cp_register_receive (c, &cp_receive); + cp_register_error (c, &cp_error); + d->devt = make_dev (&cp_cdevsw, b->num*NCHAN+c->num, UID_ROOT, + GID_WHEEL, 0600, "cp%d", b->num*NCHAN+c->num); + } + CP_LOCK (bd); + b->sys = bd; + adapter[unit] = b; + CP_UNLOCK (bd); + splx (s); + return 0; +} + +static int cp_detach (device_t dev) +{ + bdrv_t *bd = device_get_softc (dev); + cp_board_t *b = bd->board; + cp_chan_t *c; + int s; + + KASSERT (mtx_initialized (&bd->cp_mtx), ("cp mutex not initialized")); + s = splimp (); + CP_LOCK (bd); + /* Check if the device is busy (open). */ + for (c = b->chan; c < b->chan + NCHAN; ++c) { + drv_t *d = (drv_t*) c->sys; + + if (! d || ! d->chan->type) + continue; + if (d->running) { + CP_UNLOCK (bd); + splx (s); + return EBUSY; + } + } + + /* Ok, we can unload driver */ + /* At first we should stop all channels */ + for (c = b->chan; c < b->chan + NCHAN; ++c) { + drv_t *d = (drv_t*) c->sys; + + if (! d || ! d->chan->type) + continue; + + cp_stop_chan (c); + cp_stop_e1 (c); + cp_set_dtr (d->chan, 0); + cp_set_rts (d->chan, 0); + } + + /* Reset the adapter. */ + cp_destroy = 1; + cp_interrupt_poll (b, 1); + cp_led_off (b); + cp_reset (b, 0 ,0); + callout_stop (&led_timo[b->num]); + + /* Disable the interrupt request. */ + bus_teardown_intr (dev, bd->cp_irq, bd->cp_intrhand); + + for (c=b->chan; c<b->chan+NCHAN; ++c) { + drv_t *d = (drv_t*) c->sys; + + if (! d || ! d->chan->type) + continue; +#ifndef NETGRAPH + /* Detach from the packet filter list of interfaces. */ + bpfdetach (d->ifp); + + /* Detach from the sync PPP list. */ + sppp_detach (d->ifp); + + /* Detach from the system list of interfaces. */ + if_detach (d->ifp); + if_free (d->ifp); + IF_DRAIN (&d->queue); + mtx_destroy (&d->queue.ifq_mtx); +#else + if (d->node) { + ng_rmnode_self (d->node); + NG_NODE_UNREF (d->node); + d->node = NULL; + } + mtx_destroy (&d->queue.ifq_mtx); + mtx_destroy (&d->hi_queue.ifq_mtx); +#endif + destroy_dev (d->devt); + } + + b->sys = NULL; + CP_UNLOCK (bd); + + bus_deactivate_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); + bus_release_resource (dev, SYS_RES_IRQ, 0, bd->cp_irq); + bus_release_resource (dev, SYS_RES_MEMORY, PCIR_BAR(0), bd->cp_res); + + CP_LOCK (bd); + cp_led_off (b); + CP_UNLOCK (bd); + callout_drain (&led_timo[b->num]); + splx (s); + + s = splimp (); + for (c = b->chan; c < b->chan + NCHAN; ++c) { + drv_t *d = (drv_t*) c->sys; + + if (! d || ! d->chan->type) + continue; + channel [b->num*NCHAN + c->num] = 0; + /* Deallocate buffers. */ + cp_bus_dma_mem_free (&d->dmamem); + } + adapter [b->num] = 0; + cp_bus_dma_mem_free (&bd->dmamem); + free (b, M_DEVBUF); + splx (s); + mtx_destroy (&bd->cp_mtx); + return 0; +} + +#ifndef NETGRAPH +static void cp_ifstart (struct ifnet *ifp) +{ + drv_t *d = ifp->if_softc; + bdrv_t *bd = d->board->sys; + + CP_LOCK (bd); + cp_start (d); + CP_UNLOCK (bd); +} + +static void cp_ifwatchdog (struct ifnet *ifp) +{ + drv_t *d = ifp->if_softc; + + cp_watchdog (d); +} + +static void cp_tlf (struct sppp *sp) +{ + drv_t *d = SP2IFP(sp)->if_softc; + + CP_DEBUG2 (d, ("cp_tlf\n")); + /* XXXRIK: Don't forget to protect them by LOCK, or kill them. */ +/* cp_set_dtr (d->chan, 0);*/ +/* cp_set_rts (d->chan, 0);*/ + if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) + sp->pp_down (sp); +} + +static void cp_tls (struct sppp *sp) +{ + drv_t *d = SP2IFP(sp)->if_softc; + + CP_DEBUG2 (d, ("cp_tls\n")); + if (!(sp->pp_flags & PP_FR) && !(d->ifp->if_flags & PP_CISCO)) + sp->pp_up (sp); +} + +/* + * Process an ioctl request. + */ +static int cp_sioctl (struct ifnet *ifp, u_long cmd, caddr_t data) +{ + drv_t *d = ifp->if_softc; + bdrv_t *bd = d->board->sys; + int error, s, was_up, should_be_up; + + was_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; + error = sppp_ioctl (ifp, cmd, data); + + if (error) + return error; + + if (! (ifp->if_flags & IFF_DEBUG)) + d->chan->debug = 0; + else if (! d->chan->debug) + d->chan->debug = 1; + + switch (cmd) { + default: CP_DEBUG2 (d, ("ioctl 0x%lx\n", cmd)); return 0; + case SIOCADDMULTI: CP_DEBUG2 (d, ("ioctl SIOCADDMULTI\n")); return 0; + case SIOCDELMULTI: CP_DEBUG2 (d, ("ioctl SIOCDELMULTI\n")); return 0; + case SIOCSIFFLAGS: CP_DEBUG2 (d, ("ioctl SIOCSIFFLAGS\n")); break; + case SIOCSIFADDR: CP_DEBUG2 (d, ("ioctl SIOCSIFADDR\n")); break; + } + + /* We get here only in case of SIFFLAGS or SIFADDR. */ + s = splimp (); + CP_LOCK (bd); + should_be_up = (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0; + if (! was_up && should_be_up) { + /* Interface goes up -- start it. */ + cp_up (d); + cp_start (d); + } else if (was_up && ! should_be_up) { + /* Interface is going down -- stop it. */ +/* if ((IFP2SP(ifp)->pp_flags & PP_FR) || (ifp->if_flags & PP_CISCO))*/ + cp_down (d); + } + CP_DEBUG (d, ("ioctl 0x%lx p4\n", cmd)); + CP_UNLOCK (bd); + splx (s); + return 0; +} + +/* + * Initialization of interface. + * It seems to be never called by upper level? + */ +static void cp_initialize (void *softc) +{ + drv_t *d = softc; + + CP_DEBUG (d, ("cp_initialize\n")); +} +#endif /*NETGRAPH*/ + +/* + * Stop the interface. Called on splimp(). + */ +static void cp_down (drv_t *d) +{ + CP_DEBUG (d, ("cp_down\n")); + /* Interface is going down -- stop it. */ + cp_set_dtr (d->chan, 0); + cp_set_rts (d->chan, 0); + + d->running = 0; +} + +/* + * Start the interface. Called on splimp(). + */ +static void cp_up (drv_t *d) +{ + CP_DEBUG (d, ("cp_up\n")); + cp_set_dtr (d->chan, 1); + cp_set_rts (d->chan, 1); + d->running = 1; +} + +/* + * Start output on the interface. Get another datagram to send + * off of the interface queue, and copy it to the interface + * before starting the output. + */ +static void cp_send (drv_t *d) +{ + struct mbuf *m; + u_short len; + + CP_DEBUG2 (d, ("cp_send, tn=%d te=%d\n", d->chan->tn, d->chan->te)); + + /* No output if the interface is down. */ + if (! d->running) + return; + + /* No output if the modem is off. */ + if (! (d->chan->lloop || d->chan->type != T_SERIAL || + cp_get_dsr (d->chan))) + return; + + while (cp_transmit_space (d->chan)) { + /* Get the packet to send. */ +#ifdef NETGRAPH + IF_DEQUEUE (&d->hi_queue, m); + if (! m) + IF_DEQUEUE (&d->queue, m); +#else + m = sppp_dequeue (d->ifp); +#endif + if (! m) + return; +#ifndef NETGRAPH + if (d->ifp->if_bpf) + BPF_MTAP (d->ifp, m); +#endif + len = m_length (m, NULL); + if (len >= BUFSZ) + printf ("%s: too long packet: %d bytes: ", + d->name, len); + else if (! m->m_next) + cp_send_packet (d->chan, (u_char*) mtod (m, caddr_t), len, 0); + else { + u_char *buf = d->chan->tbuf[d->chan->te]; + m_copydata (m, 0, len, buf); + cp_send_packet (d->chan, buf, len, 0); + } + m_freem (m); + /* Set up transmit timeout, if the transmit ring is not empty.*/ +#ifdef NETGRAPH + d->timeout = 10; +#else + d->ifp->if_timer = 10; +#endif + } +#ifndef NETGRAPH + d->ifp->if_drv_flags |= IFF_DRV_OACTIVE; +#endif +} + +/* + * Start output on the interface. + * Always called on splimp(). + */ +static void cp_start (drv_t *d) +{ + if (d->running) { + if (! d->chan->dtr) + cp_set_dtr (d->chan, 1); + if (! d->chan->rts) + cp_set_rts (d->chan, 1); + cp_send (d); + } +} + +/* + * Handle transmit timeouts. + * Recover after lost transmit interrupts. + * Always called on splimp(). + */ +static void cp_watchdog (drv_t *d) +{ + bdrv_t *bd = d->board->sys; + CP_DEBUG (d, ("device timeout\n")); + if (d->running) { + int s = splimp (); + + CP_LOCK (bd); >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200509271746.j8RHkfuR018378>