- Merge the pdq driver (if_fpa and if_fea) from NetBSD.

Among other things this gets us ifmedia support.
- Update fddi_ifattach() to take an additional argument.
This commit is contained in:
Matthew N. Dodd 2002-03-29 11:22:22 +00:00
parent c772c98600
commit 0e93a9b535
9 changed files with 1712 additions and 527 deletions

View file

@ -35,25 +35,32 @@
#include <sys/kernel.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <net/fddi.h>
#include <dev/eisa/eisaconf.h>
#include <dev/pdq/pdqvar.h>
#include <dev/pdq/pdq_freebsd.h>
#include <dev/pdq/pdqreg.h>
static void pdq_eisa_subprobe (pdq_bus_t, u_int32_t, u_int32_t *, u_int32_t *, u_int32_t *);
static void pdq_eisa_devinit (pdq_softc_t *);
static const char * pdq_eisa_match (eisa_id_t);
static int pdq_eisa_probe (device_t);
static int pdq_eisa_attach (device_t);
void pdq_eisa_intr (void *);
static int pdq_eisa_detach (device_t);
static int pdq_eisa_shutdown (device_t);
static void pdq_eisa_ifintr (void *);
#define DEFEA_IRQS 0x0000FBA9U
@ -91,18 +98,18 @@ pdq_eisa_devinit (sc)
/*
* Do the standard initialization for the DEFEA registers.
*/
PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_FUNCTION_CTRL, 0x23);
PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CMP_1_1, (sc->sc_iobase >> 8) & 0xF0);
PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CMP_0_1, (sc->sc_iobase >> 8) & 0xF0);
PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_SLOT_CTRL, 0x01);
data = PDQ_OS_IORD_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF);
PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_FUNCTION_CTRL, 0x23);
PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_IO_CMP_1_1, (sc->io_bsh >> 8) & 0xF0);
PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_IO_CMP_0_1, (sc->io_bsh >> 8) & 0xF0);
PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_SLOT_CTRL, 0x01);
data = PDQ_OS_IORD_8(sc->io_bst, sc->io_bsh, PDQ_EISA_BURST_HOLDOFF);
#if defined(PDQ_IOMAPPED)
PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF, data & ~1);
PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_BURST_HOLDOFF, data & ~1);
#else
PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF, data | 1);
PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_BURST_HOLDOFF, data | 1);
#endif
data = PDQ_OS_IORD_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CONFIG_STAT_0);
PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CONFIG_STAT_0, data | DEFEA_INTRENABLE);
data = PDQ_OS_IORD_8(sc->io_bst, sc->io_bsh, PDQ_EISA_IO_CONFIG_STAT_0);
PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_IO_CONFIG_STAT_0, data | DEFEA_INTRENABLE);
return;
}
@ -144,7 +151,7 @@ pdq_eisa_probe (dev)
device_set_desc(dev, desc);
iobase = eisa_get_slot(dev) * EISA_SLOT_SIZE;
pdq_eisa_subprobe(PDQ_BUS_EISA, iobase, &maddr, &msize, &irq);
pdq_eisa_subprobe(SYS_RES_IOPORT, iobase, &maddr, &msize, &irq);
eisa_add_iospace(dev, iobase, 0x200, RESVADDR_NONE);
eisa_add_mspace(dev, maddr, msize, RESVADDR_NONE);
@ -153,99 +160,119 @@ pdq_eisa_probe (dev)
return (0);
}
void
pdq_eisa_intr(xdev)
void *xdev;
static void
pdq_eisa_ifintr(arg)
void * arg;
{
device_t dev = (device_t) xdev;
pdq_softc_t *sc = device_get_softc(dev);
device_t dev;
pdq_softc_t * sc;
dev = (device_t)arg;
sc = device_get_softc(dev);
PDQ_LOCK(sc);
(void) pdq_interrupt(sc->sc_pdq);
PDQ_LOCK(sc);
return;
}
static int
pdq_eisa_attach (dev)
device_t dev;
device_t dev;
{
pdq_softc_t *sc = device_get_softc(dev);
struct resource *io = 0;
struct resource *irq = 0;
struct resource *mspace = 0;
int rid;
void *ih;
u_int32_t m_addr, m_size;
pdq_softc_t * sc;
struct ifnet * ifp;
int error;
rid = 0;
io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
0, ~0, 1, RF_ACTIVE);
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
if (!io) {
device_printf(dev, "No I/O space?!\n");
goto bad;
}
sc->dev = dev;
rid = 0;
mspace = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
sc->io_rid = 0;
sc->io_type = SYS_RES_IOPORT;
sc->io = bus_alloc_resource(dev, sc->io_type, &sc->io_rid,
0, ~0, 1, RF_ACTIVE);
if (!sc->io) {
device_printf(dev, "Unable to allocate I/O space resource.\n");
error = ENXIO;
goto bad;
}
sc->io_bsh = rman_get_bushandle(sc->io);
sc->io_bst = rman_get_bustag(sc->io);
if (!mspace) {
device_printf(dev, "No memory space?!\n");
sc->mem_rid = 0;
sc->mem_type = SYS_RES_MEMORY;
sc->mem = bus_alloc_resource(dev, sc->mem_type, &sc->mem_rid,
0, ~0, 1, RF_ACTIVE);
if (!sc->mem) {
device_printf(dev, "Unable to allocate memory resource.\n");
error = ENXIO;
goto bad;
}
sc->mem_bsh = rman_get_bushandle(sc->mem);
sc->mem_bst = rman_get_bustag(sc->mem);
sc->irq_rid = 0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
if (!sc->irq) {
device_printf(dev, "Unable to allocate interrupt resource.\n");
error = ENXIO;
goto bad;
}
rid = 0;
irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
0, ~0, 1, RF_ACTIVE);
if (!irq) {
device_printf(dev, "No, irq?!\n");
goto bad;
}
m_addr = rman_get_start(mspace);
m_size = rman_get_size(mspace);
sc->sc_iobase = (pdq_bus_ioport_t) rman_get_start(io);
sc->sc_membase = (pdq_bus_memaddr_t) pmap_mapdev(m_addr, m_size);
sc->sc_if.if_name = "fea";
sc->sc_if.if_unit = device_get_unit(dev);
ifp->if_name = "fea";
ifp->if_unit = device_get_unit(dev);
pdq_eisa_devinit(sc);
sc->sc_pdq = pdq_initialize(PDQ_BUS_EISA, sc->sc_membase,
sc->sc_if.if_name, sc->sc_if.if_unit,
(void *) sc, PDQ_DEFEA);
sc->sc_pdq = pdq_initialize(sc->mem_bst, sc->mem_bsh,
ifp->if_name, ifp->if_unit,
(void *)sc, PDQ_DEFEA);
if (sc->sc_pdq == NULL) {
device_printf(dev, "initialization failed\n");
device_printf(dev, "Initialization failed.\n");
error = ENXIO;
goto bad;
}
if (bus_setup_intr(dev, irq, INTR_TYPE_NET, pdq_eisa_intr, dev, &ih)) {
error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
pdq_eisa_ifintr, dev, &sc->irq_ih);
if (error) {
device_printf(dev, "Failed to setup interrupt handler.\n");
error = ENXIO;
goto bad;
}
bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6);
pdq_ifattach(sc, NULL);
bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes,
(caddr_t) sc->arpcom.ac_enaddr, FDDI_ADDR_LEN);
pdq_ifattach(sc);
return (0);
bad:
if (io)
bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
if (irq)
bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
if (mspace)
bus_release_resource(dev, SYS_RES_MEMORY, 0, mspace);
pdq_free(dev);
return (error);
}
return (-1);
static int
pdq_eisa_detach (dev)
device_t dev;
{
pdq_softc_t * sc;
sc = device_get_softc(dev);
pdq_ifdetach(sc);
return (0);
}
static int
pdq_eisa_shutdown(dev)
device_t dev;
{
pdq_softc_t *sc = device_get_softc(dev);
pdq_softc_t * sc;
sc = device_get_softc(dev);
pdq_hwreset(sc->sc_pdq);
return (0);
@ -254,6 +281,7 @@ pdq_eisa_shutdown(dev)
static device_method_t pdq_eisa_methods[] = {
DEVMETHOD(device_probe, pdq_eisa_probe),
DEVMETHOD(device_attach, pdq_eisa_attach),
DEVMETHOD(device_attach, pdq_eisa_detach),
DEVMETHOD(device_shutdown, pdq_eisa_shutdown),
{ 0, 0 }
@ -265,6 +293,6 @@ static driver_t pdq_eisa_driver = {
sizeof(pdq_softc_t),
};
static devclass_t pdq_devclass;
DRIVER_MODULE(pdq, eisa, pdq_eisa_driver, pdq_devclass, 0, 0);
DRIVER_MODULE(if_fea, eisa, pdq_eisa_driver, pdq_devclass, 0, 0);
/* MODULE_DEPEND(if_fea, eisa, 1, 1, 1); */
MODULE_DEPEND(if_fea, fddi, 1, 1, 1);

View file

@ -32,22 +32,29 @@
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <net/if.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include <dev/pdq/pdqvar.h>
#include <dev/pdq/pdqreg.h>
#include <machine/bus_memio.h>
#include <machine/bus_pio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <net/fddi.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pdq/pdq_freebsd.h>
#include <dev/pdq/pdqreg.h>
#define DEC_VENDORID 0x1011
#define DEFPA_CHIPID 0x000F
@ -58,13 +65,26 @@
#define PCI_CBMA 0x10 /* Configuration Base Memory Address */
#define PCI_CBIO 0x14 /* Configuration Base I/O Address */
static int pdq_pci_probe (device_t);
static int pdq_pci_attach (device_t);
static int pdq_pci_detach (device_t);
static void pdq_pci_shutdown (device_t);
static void pdq_pci_ifintr (void *);
static void
pdq_pci_ifintr(void *arg)
{
device_t dev;
pdq_softc_t *sc;
sc = device_get_softc(arg);
dev = (device_t)arg;
sc = device_get_softc(dev);
PDQ_LOCK(sc);
(void) pdq_interrupt(sc->sc_pdq);
PDQ_UNLOCK(sc);
return;
}
/*
@ -76,61 +96,112 @@ pdq_pci_probe(device_t dev)
if (pci_get_vendor(dev) == DEC_VENDORID &&
pci_get_device(dev) == DEFPA_CHIPID) {
device_set_desc(dev, "Digital DEFPA PCI FDDI Controller");
return 0;
return (0);
}
return ENXIO;
return (ENXIO);
}
static int
pdq_pci_attach(device_t dev)
{
pdq_softc_t *sc;
int data;
struct resource *memres, *irqres;
int rid;
void *ih;
struct ifnet *ifp;
u_int32_t command;
int error;
memres = NULL;
irqres = NULL;
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
data = pci_read_config(dev, PCIR_LATTIMER, 1);
if (data < DEFPA_LATENCY) {
data = DEFPA_LATENCY;
pci_write_config(dev, PCIR_LATTIMER, data, 1);
sc->dev = dev;
/*
* Map control/status registers.
*/
pci_enable_busmaster(dev);
pci_enable_io(dev, SYS_RES_IOPORT);
pci_enable_io(dev, SYS_RES_MEMORY);
command = pci_read_config(dev, PCIR_COMMAND, 4);
if (!(command & PCIM_CMD_PORTEN)) {
device_printf(dev, "Failed to enable PCI I/O ports.\n");
error = ENXIO;
goto bad;
}
rid = PCI_CBMA;
memres = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE);
if (!memres)
if (!(command & PCIM_CMD_MEMEN)) {
device_printf(dev, "Failed to enable PCI memory mapping.\n");
error = ENXIO;
goto bad;
}
sc->sc_if.if_name = "fpa";
sc->sc_if.if_unit = device_get_unit(dev);
sc->sc_membase = (pdq_bus_memaddr_t) rman_get_virtual(memres);
sc->sc_pdq = pdq_initialize(PDQ_BUS_PCI, sc->sc_membase,
sc->sc_if.if_name, sc->sc_if.if_unit,
(void *) sc, PDQ_DEFPA);
if (sc->sc_pdq == NULL)
goto bad;
bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6);
pdq_ifattach(sc, NULL);
rid = 0;
irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
RF_SHAREABLE | RF_ACTIVE);
if (!irqres)
goto bad;
if (bus_setup_intr(dev, irqres, INTR_TYPE_NET, pdq_pci_ifintr,
(void *)dev, &ih))
goto bad;
return 0;
command = pci_read_config(dev, PCIR_LATTIMER, 1);
if (command < DEFPA_LATENCY) {
command = DEFPA_LATENCY;
pci_write_config(dev, PCIR_LATTIMER, command, 1);
}
sc->mem_rid = PCI_CBMA;
sc->mem_type = SYS_RES_MEMORY;
sc->mem = bus_alloc_resource(dev, sc->mem_type, &sc->mem_rid,
0, ~0, 1, RF_ACTIVE);
if (!sc->mem) {
device_printf(dev, "Unable to allocate I/O space resource.\n");
error = ENXIO;
goto bad;
}
sc->mem_bsh = rman_get_bushandle(sc->mem);
sc->mem_bst = rman_get_bustag(sc->mem);
sc->irq_rid = 0;
sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
if (!sc->irq) {
device_printf(dev, "Unable to allocate interrupt resource.\n");
error = ENXIO;
goto bad;
}
ifp->if_name = "fpa";
ifp->if_unit = device_get_unit(dev);
sc->sc_pdq = pdq_initialize(sc->mem_bst, sc->mem_bsh,
ifp->if_name, ifp->if_unit,
(void *)sc, PDQ_DEFPA);
if (sc->sc_pdq == NULL) {
device_printf(dev, "Initialization failed.\n");
error = ENXIO;
goto bad;
}
error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
pdq_pci_ifintr, dev, &sc->irq_ih);
if (error) {
device_printf(dev, "Failed to setup interrupt handler.\n");
error = ENXIO;
goto bad;
}
bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes,
(caddr_t) sc->arpcom.ac_enaddr, FDDI_ADDR_LEN);
pdq_ifattach(sc);
return (0);
bad:
if (memres)
bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, memres);
if (irqres)
bus_release_resource(dev, SYS_RES_IRQ, 0, irqres);
return ENXIO;
pdq_free(dev);
return (error);
}
static int
pdq_pci_detach (dev)
device_t dev;
{
pdq_softc_t *sc;
sc = device_get_softc(dev);
pdq_ifdetach(sc);
return (0);
}
static void
@ -140,19 +211,26 @@ pdq_pci_shutdown(device_t dev)
sc = device_get_softc(dev);
pdq_hwreset(sc->sc_pdq);
return;
}
static device_method_t pdq_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pdq_pci_probe),
DEVMETHOD(device_attach, pdq_pci_attach),
DEVMETHOD(device_detach, pdq_pci_detach),
DEVMETHOD(device_shutdown, pdq_pci_shutdown),
{ 0, 0 }
};
static driver_t pdq_pci_driver = {
"fpa",
pdq_pci_methods,
sizeof(pdq_softc_t),
};
static devclass_t pdq_devclass;
DRIVER_MODULE(if_fpa, pci, pdq_pci_driver, pdq_devclass, 0, 0);
/* MODULE_DEPEND(if_fpa, pci, 1, 1, 1); */
MODULE_DEPEND(if_fpa, fddi, 1, 1, 1);

View file

@ -1,3 +1,5 @@
/* $NetBSD: pdq.c,v 1.33 2001/11/13 13:14:43 lukem Exp $ */
/*-
* Copyright (c) 1995,1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
@ -8,7 +10,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -21,6 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Id: pdq.c,v 1.32 1997/06/05 01:56:35 thomas Exp
* $FreeBSD$
*
*/
@ -28,7 +31,7 @@
/*
* DEC PDQ FDDI Controller O/S independent code
*
* This module should work any PDQ based board. Note that changes for
* This module should work any on PDQ based board. Note that changes for
* MIPS and Alpha architectures (or any other architecture which requires
* a flushing of memory or write buffers and/or has incoherent caches)
* have yet to be made.
@ -37,10 +40,18 @@
* flushing of the write buffers.
*/
#ifdef __NetBSD__
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pdq.c,v 1.33 2001/11/13 13:14:43 lukem Exp $");
#endif
#define PDQ_HWSUPPORT /* for pdq.h */
#if defined(__FreeBSD__)
#include <dev/pdq/pdqvar.h>
/*
* What a botch having to specific includes for FreeBSD!
*/
#include <dev/pdq/pdq_freebsd.h>
#include <dev/pdq/pdqreg.h>
#else
#include "pdqvar.h"
@ -76,6 +87,7 @@ static const char * const pdq_entities[] = {
};
static const char * const pdq_station_events[] = {
"Unknown Event #0",
"Trace Received"
};
@ -218,6 +230,8 @@ pdq_print_fddi_chars(
pdq_pmd_types[rsp->status_chars_get.pmd_type[1] / 100][rsp->status_chars_get.pmd_type[1] % 100]);
printf("\n");
pdq_os_update_status(pdq, rsp);
}
static void
@ -261,6 +275,7 @@ pdq_init_pci_csrs(
static void
pdq_flush_databuf_queue(
pdq_t *pdq,
pdq_databuf_queue_t *q)
{
PDQ_OS_DATABUF_T *pdu;
@ -268,7 +283,7 @@ pdq_flush_databuf_queue(
PDQ_OS_DATABUF_DEQUEUE(q, pdu);
if (pdu == NULL)
return;
PDQ_OS_DATABUF_FREE(pdu);
PDQ_OS_DATABUF_FREE(pdq, pdu);
}
}
@ -409,7 +424,6 @@ static const struct {
sizeof(pdq_response_addr_filter_get_t),
"Addr Filter Get"
},
#if 0
{ sizeof(pdq_cmd_generic_t), /* 9 - PDQC_ERROR_LOG_CLEAR */
sizeof(pdq_response_generic_t),
"Error Log Clear"
@ -443,7 +457,7 @@ static const struct {
sizeof(pdq_response_generic_t),
"SMT MIB Set",
},
#endif
{ 0, 0, "Bogus CMD" },
};
static void
@ -453,6 +467,7 @@ pdq_queue_commands(
const pdq_csrs_t * const csrs = &pdq->pdq_csrs;
pdq_command_info_t * const ci = &pdq->pdq_command_info;
pdq_descriptor_block_t * const dbp = pdq->pdq_dbp;
pdq_txdesc_t * const txd = &dbp->pdqdb_command_requests[ci->ci_request_producer];
pdq_cmd_code_t op;
pdq_uint32_t cmdlen, rsplen, mask;
@ -487,23 +502,19 @@ pdq_queue_commands(
* Obtain and fill in the descriptor for the command (descriptor is
* pre-initialized)
*/
dbp->pdqdb_command_requests[ci->ci_request_producer].txd_seg_len = cmdlen;
PDQ_ADVANCE(ci->ci_request_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests));
/*
* Obtain and fill in the descriptor for the response (descriptor is
* pre-initialized)
*/
dbp->pdqdb_command_responses[ci->ci_response_producer].rxd_seg_len_hi = cmdlen / 16;
PDQ_ADVANCE(ci->ci_response_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_responses));
txd->txd_seg_len = cmdlen;
/*
* Clear the command area, set the opcode, and the command from the pending
* mask.
*/
PDQ_OS_MEMZERO(ci->ci_bufstart, cmdlen);
*(pdq_cmd_code_t *) ci->ci_bufstart = op;
ci->ci_queued_commands[ci->ci_request_producer] = op;
#if defined(PDQVERBOSE)
((pdq_response_generic_t *) ci->ci_response_bufstart)->generic_op = PDQC_BOGUS_CMD;
#endif
PDQ_OS_MEMZERO(ci->ci_request_bufstart, cmdlen);
*(pdq_cmd_code_t *) ci->ci_request_bufstart = op;
ci->ci_pending_commands &= ~mask;
/*
@ -511,7 +522,7 @@ pdq_queue_commands(
*/
switch (op) {
case PDQC_FILTER_SET: {
pdq_cmd_filter_set_t *filter_set = (pdq_cmd_filter_set_t *) ci->ci_bufstart;
pdq_cmd_filter_set_t *filter_set = (pdq_cmd_filter_set_t *) ci->ci_request_bufstart;
unsigned idx = 0;
filter_set->filter_set_items[idx].item_code = PDQI_IND_GROUP_PROM;
filter_set->filter_set_items[idx].filter_state = (pdq->pdq_flags & PDQ_PROMISC ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK);
@ -529,7 +540,7 @@ pdq_queue_commands(
break;
}
case PDQC_ADDR_FILTER_SET: {
pdq_cmd_addr_filter_set_t *addr_filter_set = (pdq_cmd_addr_filter_set_t *) ci->ci_bufstart;
pdq_cmd_addr_filter_set_t *addr_filter_set = (pdq_cmd_addr_filter_set_t *) ci->ci_request_bufstart;
pdq_lanaddr_t *addr = addr_filter_set->addr_filter_set_addresses;
addr->lanaddr_bytes[0] = 0xFF;
addr->lanaddr_bytes[1] = 0xFF;
@ -541,10 +552,36 @@ pdq_queue_commands(
pdq_os_addr_fill(pdq, addr, 61);
break;
}
case PDQC_SNMP_SET: {
pdq_cmd_snmp_set_t *snmp_set = (pdq_cmd_snmp_set_t *) ci->ci_request_bufstart;
unsigned idx = 0;
snmp_set->snmp_set_items[idx].item_code = PDQSNMP_FULL_DUPLEX_ENABLE;
snmp_set->snmp_set_items[idx].item_value = (pdq->pdq_flags & PDQ_WANT_FDX ? 1 : 2);
snmp_set->snmp_set_items[idx].item_port = 0;
idx++;
snmp_set->snmp_set_items[idx].item_code = PDQSNMP_EOL;
break;
}
default: { /* to make gcc happy */
break;
}
}
/*
* Sync the command request buffer and descriptor, then advance
* the request producer index.
*/
PDQ_OS_CMDRQST_PRESYNC(pdq, txd->txd_seg_len);
PDQ_OS_DESC_PRESYNC(pdq, txd, sizeof(pdq_txdesc_t));
PDQ_ADVANCE(ci->ci_request_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests));
/*
* Sync the command response buffer and advance the response
* producer index (descriptor is already pre-initialized)
*/
PDQ_OS_CMDRSP_PRESYNC(pdq, PDQ_SIZE_COMMAND_RESPONSE);
PDQ_ADVANCE(ci->ci_response_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_responses));
/*
* At this point the command is done. All that needs to be done is to
* produce it to the PDQ.
@ -578,15 +615,21 @@ pdq_process_command_responses(
PDQ_ASSERT(cbp->pdqcb_command_request != ci->ci_request_completion);
rspgen = (const pdq_response_generic_t *) ci->ci_bufstart;
PDQ_OS_CMDRSP_POSTSYNC(pdq, PDQ_SIZE_COMMAND_RESPONSE);
rspgen = (const pdq_response_generic_t *) ci->ci_response_bufstart;
PDQ_ASSERT(rspgen->generic_op == ci->ci_queued_commands[ci->ci_request_completion]);
PDQ_ASSERT(rspgen->generic_status == PDQR_SUCCESS);
PDQ_PRINTF(("PDQ Process Command Response: %s completed (status=%d)\n",
PDQ_PRINTF(("PDQ Process Command Response: %s completed (status=%d [0x%x])\n",
pdq_cmd_info[rspgen->generic_op].cmd_name,
rspgen->generic_status));
rspgen->generic_status, rspgen->generic_status));
if (rspgen->generic_op == PDQC_STATUS_CHARS_GET && (pdq->pdq_flags & PDQ_PRINTCHARS)) {
pdq->pdq_flags &= ~PDQ_PRINTCHARS;
pdq_print_fddi_chars(pdq, (const pdq_response_status_chars_get_t *) rspgen);
} else if (rspgen->generic_op == PDQC_DEC_EXT_MIB_GET) {
pdq->pdq_flags &= ~PDQ_IS_FDX;
if (((const pdq_response_dec_ext_mib_get_t *)rspgen)->dec_ext_mib_get.fdx_operational)
pdq->pdq_flags |= PDQ_IS_FDX;
}
PDQ_ADVANCE(ci->ci_request_completion, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests));
@ -617,19 +660,40 @@ pdq_process_unsolicited_events(
pdq_unsolicited_info_t *ui = &pdq->pdq_unsolicited_info;
volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp;
pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
const pdq_unsolicited_event_t *event;
pdq_rxdesc_t *rxd;
/*
* Process each unsolicited event (if any).
*/
while (cbp->pdqcb_unsolicited_event != ui->ui_completion) {
rxd = &dbp->pdqdb_unsolicited_events[ui->ui_completion];
const pdq_unsolicited_event_t *event;
event = &ui->ui_events[ui->ui_completion & (PDQ_NUM_UNSOLICITED_EVENTS-1)];
PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq, event);
switch (event->event_type) {
case PDQ_UNSOLICITED_EVENT: {
int bad_event = 0;
switch (event->event_entity) {
case PDQ_ENTITY_STATION: {
bad_event = event->event_code.value >= PDQ_STATION_EVENT_MAX;
break;
}
case PDQ_ENTITY_LINK: {
bad_event = event->event_code.value >= PDQ_LINK_EVENT_MAX;
break;
}
case PDQ_ENTITY_PHY_PORT: {
bad_event = event->event_code.value >= PDQ_PHY_EVENT_MAX;
break;
}
default: {
bad_event = 1;
break;
}
}
if (bad_event) {
break;
}
printf(PDQ_OS_PREFIX "Unsolicited Event: %s: %s",
PDQ_OS_PREFIX_ARGS,
pdq_entities[event->event_entity],
@ -643,6 +707,7 @@ pdq_process_unsolicited_events(
break;
}
}
PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, event);
PDQ_ADVANCE(ui->ui_completion, 1, PDQ_RING_MASK(dbp->pdqdb_unsolicited_events));
ui->ui_free++;
}
@ -679,11 +744,13 @@ pdq_process_received_data(
fpdu = lpdu = buffers[completion];
PDQ_ASSERT(fpdu != NULL);
PDQ_OS_RXPDU_POSTSYNC(pdq, fpdu, 0, sizeof(u_int32_t));
dataptr = PDQ_OS_DATABUF_PTR(fpdu);
status = *(pdq_rxstatus_t *) dataptr;
if ((status.rxs_status & 0x200000) == 0) {
datalen = status.rxs_status & 0x1FFF;
if (status.rxs_rcc_badpdu == 0) {
datalen = status.rxs_len;
PDQ_OS_RXPDU_POSTSYNC(pdq, fpdu, sizeof(u_int32_t),
PDQ_RX_FC_OFFSET + 1 - sizeof(u_int32_t));
fc = dataptr[PDQ_RX_FC_OFFSET];
switch (fc & (PDQ_FDDIFC_C|PDQ_FDDIFC_L|PDQ_FDDIFC_F)) {
case PDQ_FDDI_LLC_ASYNC:
@ -710,19 +777,19 @@ pdq_process_received_data(
* Update the lengths of the data buffers now that we know
* the real length.
*/
pdulen = datalen - 4 /* CRC */;
segcnt = (pdulen + PDQ_RX_FC_OFFSET + PDQ_OS_DATABUF_SIZE - 1) / PDQ_OS_DATABUF_SIZE;
PDQ_OS_DATABUF_ALLOC(npdu);
pdulen = datalen + (PDQ_RX_FC_OFFSET - PDQ_OS_HDR_OFFSET) - 4 /* CRC */;
segcnt = (pdulen + PDQ_OS_HDR_OFFSET + PDQ_OS_DATABUF_SIZE - 1) / PDQ_OS_DATABUF_SIZE;
PDQ_OS_DATABUF_ALLOC(pdq, npdu);
if (npdu == NULL) {
PDQ_PRINTF(("discard: no databuf #0\n"));
goto discard_frame;
}
buffers[completion] = npdu;
for (idx = 1; idx < segcnt; idx++) {
PDQ_OS_DATABUF_ALLOC(npdu);
PDQ_OS_DATABUF_ALLOC(pdq, npdu);
if (npdu == NULL) {
PDQ_OS_DATABUF_NEXT_SET(lpdu, NULL);
PDQ_OS_DATABUF_FREE(fpdu);
PDQ_OS_DATABUF_FREE(pdq, fpdu);
goto discard_frame;
}
PDQ_OS_DATABUF_NEXT_SET(lpdu, buffers[(completion + idx) & ring_mask]);
@ -735,13 +802,17 @@ pdq_process_received_data(
buffers[(completion + idx) & ring_mask];
buffers[(completion + idx) & ring_mask] = NULL;
}
PDQ_OS_DATABUF_ADJ(fpdu, PDQ_RX_FC_OFFSET);
PDQ_OS_DATABUF_ADJ(fpdu, PDQ_OS_HDR_OFFSET);
if (segcnt == 1) {
PDQ_OS_DATABUF_LEN_SET(fpdu, pdulen);
} else {
PDQ_OS_DATABUF_LEN_SET(lpdu, pdulen + PDQ_RX_FC_OFFSET - (segcnt - 1) * PDQ_OS_DATABUF_SIZE);
PDQ_OS_DATABUF_LEN_SET(lpdu, pdulen + PDQ_OS_HDR_OFFSET - (segcnt - 1) * PDQ_OS_DATABUF_SIZE);
}
pdq_os_receive_pdu(pdq, fpdu, pdulen);
/*
* Do not pass to protocol if packet was received promiscuously
*/
pdq_os_receive_pdu(pdq, fpdu, pdulen,
status.rxs_rcc_dd < PDQ_RXS_RCC_DD_CAM_MATCH);
rx->rx_free += PDQ_RX_SEGCNT;
PDQ_ADVANCE(producer, PDQ_RX_SEGCNT, ring_mask);
PDQ_ADVANCE(completion, PDQ_RX_SEGCNT, ring_mask);
@ -754,21 +825,21 @@ pdq_process_received_data(
goto discard_frame;
if (status.rxs_rcc_reason != 0) {
/* hardware fault */
}
if (status.rxs_rcc_badcrc) {
printf(PDQ_OS_PREFIX " MAC CRC error (source=%x-%x-%x-%x-%x-%x)\n",
PDQ_OS_PREFIX_ARGS,
dataptr[PDQ_RX_FC_OFFSET+1],
dataptr[PDQ_RX_FC_OFFSET+2],
dataptr[PDQ_RX_FC_OFFSET+3],
dataptr[PDQ_RX_FC_OFFSET+4],
dataptr[PDQ_RX_FC_OFFSET+5],
dataptr[PDQ_RX_FC_OFFSET+6]);
/* rx->rx_badcrc++; */
} else if (status.rxs_fsc == 0 || status.rxs_fsb_e == 1) {
/* rx->rx_frame_status_errors++; */
} else {
/* hardware fault */
if (status.rxs_rcc_badcrc) {
printf(PDQ_OS_PREFIX " MAC CRC error (source=%x-%x-%x-%x-%x-%x)\n",
PDQ_OS_PREFIX_ARGS,
dataptr[PDQ_RX_FC_OFFSET+1],
dataptr[PDQ_RX_FC_OFFSET+2],
dataptr[PDQ_RX_FC_OFFSET+3],
dataptr[PDQ_RX_FC_OFFSET+4],
dataptr[PDQ_RX_FC_OFFSET+5],
dataptr[PDQ_RX_FC_OFFSET+6]);
/* rx->rx_badcrc++; */
} else if (status.rxs_fsc == 0 || status.rxs_fsb_e == 1) {
/* rx->rx_frame_status_errors++; */
} else {
/* hardware fault */
}
}
}
discard_frame:
@ -787,7 +858,9 @@ pdq_process_received_data(
}
rxd->rxd_pa_hi = 0;
rxd->rxd_seg_len_hi = PDQ_OS_DATABUF_SIZE / 16;
rxd->rxd_pa_lo = PDQ_OS_VA_TO_PA(pdq, PDQ_OS_DATABUF_PTR(buffers[rx->rx_producer]));
rxd->rxd_pa_lo = PDQ_OS_DATABUF_BUSPA(pdq, buffers[rx->rx_producer]);
PDQ_OS_RXPDU_PRESYNC(pdq, buffers[rx->rx_producer], 0, PDQ_OS_DATABUF_SIZE);
PDQ_OS_DESC_PRESYNC(pdq, rxd, sizeof(*rxd));
PDQ_ADVANCE(rx->rx_producer, 1, ring_mask);
PDQ_ADVANCE(producer, 1, ring_mask);
PDQ_ADVANCE(completion, 1, ring_mask);
@ -804,7 +877,7 @@ pdq_process_received_data(
*/
for (idx = 0; idx < PDQ_RX_SEGCNT; idx++) {
if ((pdu = buffers[(rx->rx_producer + idx) & ring_mask]) == NULL) {
PDQ_OS_DATABUF_ALLOC(pdu);
PDQ_OS_DATABUF_ALLOC(pdq, pdu);
if (pdu == NULL)
break;
buffers[(rx->rx_producer + idx) & ring_mask] = pdu;
@ -817,7 +890,9 @@ pdq_process_received_data(
}
rxd->rxd_pa_hi = 0;
rxd->rxd_seg_len_hi = PDQ_OS_DATABUF_SIZE / 16;
rxd->rxd_pa_lo = PDQ_OS_VA_TO_PA(pdq, PDQ_OS_DATABUF_PTR(pdu));
rxd->rxd_pa_lo = PDQ_OS_DATABUF_BUSPA(pdq, pdu);
PDQ_OS_RXPDU_PRESYNC(pdq, pdu, 0, PDQ_OS_DATABUF_SIZE);
PDQ_OS_DESC_PRESYNC(pdq, rxd, sizeof(*rxd));
}
if (idx < PDQ_RX_SEGCNT) {
/*
@ -832,24 +907,65 @@ pdq_process_received_data(
}
}
static void pdq_process_transmitted_data(pdq_t *pdq);
pdq_boolean_t
pdq_queue_transmit_data(
pdq_t *pdq,
PDQ_OS_DATABUF_T *pdu)
{
pdq_tx_info_t *tx = &pdq->pdq_tx_info;
pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
pdq_tx_info_t * const tx = &pdq->pdq_tx_info;
pdq_descriptor_block_t * const dbp = pdq->pdq_dbp;
pdq_uint32_t producer = tx->tx_producer;
pdq_txdesc_t *eop = NULL;
PDQ_OS_DATABUF_T *pdu0;
pdq_uint32_t freecnt;
#if defined(PDQ_BUS_DMA)
bus_dmamap_t map;
#endif
if (tx->tx_free < 1)
again:
if (PDQ_RX_FC_OFFSET == PDQ_OS_HDR_OFFSET) {
freecnt = tx->tx_free - 1;
} else {
freecnt = tx->tx_free;
}
/*
* Need 2 or more descriptors to be able to send.
*/
if (freecnt == 0) {
pdq->pdq_intrmask |= PDQ_HOST_INT_TX_ENABLE;
PDQ_CSR_WRITE(&pdq->pdq_csrs, csr_host_int_enable, pdq->pdq_intrmask);
return PDQ_FALSE;
}
dbp->pdqdb_transmits[producer] = tx->tx_hdrdesc;
PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits));
if (PDQ_RX_FC_OFFSET == PDQ_OS_HDR_OFFSET) {
dbp->pdqdb_transmits[producer] = tx->tx_hdrdesc;
PDQ_OS_DESC_PRESYNC(pdq, &dbp->pdqdb_transmits[producer], sizeof(pdq_txdesc_t));
PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits));
}
#if defined(PDQ_BUS_DMA)
map = M_GETCTX(pdu, bus_dmamap_t);
if (freecnt >= map->dm_nsegs) {
int idx;
for (idx = 0; idx < map->dm_nsegs; idx++) {
/*
* Initialize the transmit descriptor
*/
eop = &dbp->pdqdb_transmits[producer];
eop->txd_seg_len = map->dm_segs[idx].ds_len;
eop->txd_pa_lo = map->dm_segs[idx].ds_addr;
eop->txd_sop = eop->txd_eop = eop->txd_pa_hi = 0;
PDQ_OS_DESC_PRESYNC(pdq, eop, sizeof(pdq_txdesc_t));
freecnt--;
PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits));
}
pdu0 = NULL;
} else {
pdu0 = pdu;
}
#else
for (freecnt = tx->tx_free - 1, pdu0 = pdu; pdu0 != NULL && freecnt > 0;) {
pdq_uint32_t fraglen, datalen = PDQ_OS_DATABUF_LEN(pdu0);
const pdq_uint8_t *dataptr = PDQ_OS_DATABUF_PTR(pdu0);
@ -868,9 +984,9 @@ pdq_queue_transmit_data(
*/
eop = &dbp->pdqdb_transmits[producer];
eop->txd_seg_len = seglen;
eop->txd_pa_lo = PDQ_OS_VA_TO_PA(pdq, dataptr);
eop->txd_pa_lo = PDQ_OS_VA_TO_BUSPA(pdq, dataptr);
eop->txd_sop = eop->txd_eop = eop->txd_pa_hi = 0;
PDQ_OS_DESC_PRESYNC(pdq, eop, sizeof(pdq_txdesc_t));
datalen -= seglen;
dataptr += seglen;
fraglen = PDQ_OS_PAGESIZE;
@ -879,20 +995,37 @@ pdq_queue_transmit_data(
}
pdu0 = PDQ_OS_DATABUF_NEXT(pdu0);
}
#endif /* defined(PDQ_BUS_DMA) */
if (pdu0 != NULL) {
unsigned completion = tx->tx_completion;
PDQ_ASSERT(freecnt == 0);
PDQ_OS_CONSUMER_POSTSYNC(pdq);
pdq_process_transmitted_data(pdq);
if (completion != tx->tx_completion) {
producer = tx->tx_producer;
eop = NULL;
goto again;
}
/*
* If we still have data to process then the ring was too full
* to store the PDU. Return FALSE so the caller will requeue
* the PDU for later.
*/
pdq->pdq_intrmask |= PDQ_HOST_INT_TX_ENABLE;
PDQ_CSR_WRITE(&pdq->pdq_csrs, csr_host_int_enable, pdq->pdq_intrmask);
return PDQ_FALSE;
}
/*
* Everything went fine. Finish it up.
*/
tx->tx_descriptor_count[tx->tx_producer] = tx->tx_free - freecnt;
if (PDQ_RX_FC_OFFSET != PDQ_OS_HDR_OFFSET) {
dbp->pdqdb_transmits[tx->tx_producer].txd_sop = 1;
PDQ_OS_DESC_PRESYNC(pdq, &dbp->pdqdb_transmits[tx->tx_producer],
sizeof(pdq_txdesc_t));
}
eop->txd_eop = 1;
PDQ_OS_DESC_PRESYNC(pdq, eop, sizeof(pdq_txdesc_t));
PDQ_OS_DATABUF_ENQUEUE(&tx->tx_txq, pdu);
tx->tx_producer = producer;
tx->tx_free = freecnt;
@ -908,6 +1041,7 @@ pdq_process_transmitted_data(
volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp;
pdq_descriptor_block_t *dbp = pdq->pdq_dbp;
pdq_uint32_t completion = tx->tx_completion;
int reclaimed = 0;
while (completion != cbp->pdqcb_transmits) {
PDQ_OS_DATABUF_T *pdu;
@ -917,14 +1051,17 @@ pdq_process_transmitted_data(
PDQ_OS_DATABUF_DEQUEUE(&tx->tx_txq, pdu);
pdq_os_transmit_done(pdq, pdu);
tx->tx_free += descriptor_count;
reclaimed = 1;
PDQ_ADVANCE(completion, descriptor_count, PDQ_RING_MASK(dbp->pdqdb_transmits));
}
if (tx->tx_completion != completion) {
tx->tx_completion = completion;
pdq->pdq_intrmask &= ~PDQ_HOST_INT_TX_ENABLE;
PDQ_CSR_WRITE(&pdq->pdq_csrs, csr_host_int_enable, pdq->pdq_intrmask);
pdq_os_restart_transmitter(pdq);
}
PDQ_DO_TYPE2_PRODUCER(pdq);
if (reclaimed)
PDQ_DO_TYPE2_PRODUCER(pdq);
}
void
@ -943,11 +1080,12 @@ pdq_flush_transmitter(
* Don't call transmit done since the packet never made it
* out on the wire.
*/
PDQ_OS_DATABUF_FREE(pdu);
PDQ_OS_DATABUF_FREE(pdq, pdu);
}
tx->tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits);
tx->tx_completion = cbp->pdqcb_transmits = tx->tx_producer;
cbp->pdqcb_transmits = tx->tx_completion = tx->tx_producer;
PDQ_OS_CONSUMER_PRESYNC(pdq);
PDQ_DO_TYPE2_PRODUCER(pdq);
}
@ -964,17 +1102,17 @@ pdq_hwreset(
if (state == PDQS_DMA_UNAVAILABLE)
return;
PDQ_CSR_WRITE(csrs, csr_port_data_a,
(state == PDQS_HALTED) ? 0 : PDQ_PRESET_SKIP_SELFTEST);
(state == PDQS_HALTED && pdq->pdq_type != PDQ_DEFTA) ? 0 : PDQ_PRESET_SKIP_SELFTEST);
PDQ_CSR_WRITE(csrs, csr_port_reset, 1);
PDQ_OS_USEC_DELAY(100);
PDQ_CSR_WRITE(csrs, csr_port_reset, 0);
for (cnt = 45000;;cnt--) {
for (cnt = 100000;;cnt--) {
PDQ_OS_USEC_DELAY(1000);
state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
if (state == PDQS_DMA_UNAVAILABLE || cnt == 0)
break;
}
PDQ_PRINTF(("PDQ Reset spun %d cycles\n", 45000 - cnt));
PDQ_PRINTF(("PDQ Reset spun %d cycles\n", 100000 - cnt));
PDQ_OS_USEC_DELAY(10000);
state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE);
@ -1050,12 +1188,12 @@ pdq_stop(
/*
* Flush all the databuf queues.
*/
pdq_flush_databuf_queue(&pdq->pdq_tx_info.tx_txq);
pdq->pdq_flags &= ~PDQ_TXOK;
pdq_flush_databuf_queue(pdq, &pdq->pdq_tx_info.tx_txq);
pdq->pdq_flags &= ~(PDQ_TXOK|PDQ_IS_ONRING|PDQ_IS_FDX);
buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_rx_info.rx_buffers;
for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_receives); idx++) {
if (buffers[idx] != NULL) {
PDQ_OS_DATABUF_FREE(buffers[idx]);
PDQ_OS_DATABUF_FREE(pdq, buffers[idx]);
buffers[idx] = NULL;
}
}
@ -1063,7 +1201,7 @@ pdq_stop(
buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_host_smt_info.rx_buffers;
for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_host_smt); idx++) {
if (buffers[idx] != NULL) {
PDQ_OS_DATABUF_FREE(buffers[idx]);
PDQ_OS_DATABUF_FREE(pdq, buffers[idx]);
buffers[idx] = NULL;
}
}
@ -1078,6 +1216,7 @@ pdq_stop(
pdq->pdq_cbp->pdqcb_unsolicited_event = 0;
pdq->pdq_cbp->pdqcb_command_response = 0;
pdq->pdq_cbp->pdqcb_command_request = 0;
PDQ_OS_CONSUMER_PRESYNC(pdq);
/*
* Reset the producer and completion indexes to 0.
@ -1119,20 +1258,30 @@ pdq_stop(
*/
pdq_process_unsolicited_events(pdq);
if (pdq->pdq_type == PDQ_DEFEA && pdq->pdq_chip_rev == PDQ_CHIP_REV_E)
if ((pdq->pdq_type == PDQ_DEFEA && pdq->pdq_chip_rev == PDQ_CHIP_REV_E)
|| pdq->pdq_type == PDQ_DEFTA)
PDQ_CSR_WRITE(csrs, csr_port_data_b, PDQ_DMA_BURST_16LW);
else
PDQ_CSR_WRITE(csrs, csr_port_data_b, PDQ_DMA_BURST_8LW);
PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_DMA_BURST_SIZE_SET);
pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD);
/*
* Make sure there isn't stale information in the caches before
* tell the adapter about the blocks it's going to use.
*/
PDQ_OS_CONSUMER_PRESYNC(pdq);
PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_OS_VA_TO_PA(pdq, pdq->pdq_cbp));
PDQ_CSR_WRITE(csrs, csr_port_data_a, pdq->pdq_pa_consumer_block);
pdq_do_port_control(csrs, PDQ_PCTL_CONSUMER_BLOCK);
PDQ_CSR_WRITE(csrs, csr_port_data_b, 0);
PDQ_CSR_WRITE(csrs, csr_port_data_a,
PDQ_OS_VA_TO_PA(pdq, pdq->pdq_dbp) | PDQ_DMA_INIT_LW_BSWAP_DATA);
#if !defined(BYTE_ORDER) || BYTE_ORDER == LITTLE_ENDIAN
PDQ_CSR_WRITE(csrs, csr_port_data_a, pdq->pdq_pa_descriptor_block | PDQ_DMA_INIT_LW_BSWAP_DATA);
#else
PDQ_CSR_WRITE(csrs, csr_port_data_a, pdq->pdq_pa_descriptor_block | PDQ_DMA_INIT_LW_BSWAP_DATA | PDQ_DMA_INIT_LW_BSWAP_LITERAL);
#endif
pdq_do_port_control(csrs, PDQ_PCTL_DMA_INIT);
for (cnt = 0; cnt < 1000; cnt++) {
@ -1152,9 +1301,11 @@ pdq_stop(
PDQ_ASSERT(state == PDQS_DMA_AVAILABLE);
PDQ_CSR_WRITE(csrs, csr_host_int_type_0, 0xFF);
PDQ_CSR_WRITE(csrs, csr_host_int_enable, 0) /* PDQ_HOST_INT_STATE_CHANGE
pdq->pdq_intrmask = 0;
/* PDQ_HOST_INT_STATE_CHANGE
|PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE
|PDQ_HOST_INT_UNSOL_ENABLE */;
PDQ_CSR_WRITE(csrs, csr_host_int_enable, pdq->pdq_intrmask);
/*
* Any other command but START should be valid.
@ -1169,6 +1320,7 @@ pdq_stop(
* Now wait (up to 100ms) for the command(s) to finish.
*/
for (cnt = 0; cnt < 1000; cnt++) {
PDQ_OS_CONSUMER_POSTSYNC(pdq);
pdq_process_command_responses(pdq);
if (pdq->pdq_command_info.ci_response_producer == pdq->pdq_command_info.ci_response_completion)
break;
@ -1201,9 +1353,11 @@ pdq_run(
* ones will get through.
*/
PDQ_CSR_WRITE(csrs, csr_host_int_type_0, 0xFF);
PDQ_CSR_WRITE(csrs, csr_host_int_enable, PDQ_HOST_INT_STATE_CHANGE|PDQ_HOST_INT_XMT_DATA_FLUSH
|PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE|PDQ_HOST_INT_UNSOL_ENABLE
|PDQ_HOST_INT_RX_ENABLE|PDQ_HOST_INT_TX_ENABLE|PDQ_HOST_INT_HOST_SMT_ENABLE);
pdq->pdq_intrmask = PDQ_HOST_INT_STATE_CHANGE
|PDQ_HOST_INT_XMT_DATA_FLUSH|PDQ_HOST_INT_FATAL_ERROR
|PDQ_HOST_INT_CMD_RSP_ENABLE|PDQ_HOST_INT_UNSOL_ENABLE
|PDQ_HOST_INT_RX_ENABLE|PDQ_HOST_INT_HOST_SMT_ENABLE;
PDQ_CSR_WRITE(csrs, csr_host_int_enable, pdq->pdq_intrmask);
/*
* Set the MAC and address filters and start up the PDQ.
*/
@ -1223,7 +1377,9 @@ pdq_run(
| (pdq->pdq_host_smt_info.rx_completion << 8));
}
pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET)
| PDQ_BITMASK(PDQC_ADDR_FILTER_SET) | PDQ_BITMASK(PDQC_START);
| PDQ_BITMASK(PDQC_ADDR_FILTER_SET)
| PDQ_BITMASK(PDQC_SNMP_SET)
| PDQ_BITMASK(PDQC_START);
if (pdq->pdq_flags & PDQ_PRINTCHARS)
pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET);
pdq_queue_commands(pdq);
@ -1232,7 +1388,8 @@ pdq_run(
case PDQS_LINK_UNAVAILABLE:
case PDQS_LINK_AVAILABLE: {
pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET)
| PDQ_BITMASK(PDQC_ADDR_FILTER_SET);
| PDQ_BITMASK(PDQC_ADDR_FILTER_SET)
| PDQ_BITMASK(PDQC_SNMP_SET);
if (pdq->pdq_flags & PDQ_PRINTCHARS)
pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET);
if (pdq->pdq_flags & PDQ_PASS_SMT) {
@ -1270,6 +1427,7 @@ pdq_interrupt(
while ((data = PDQ_CSR_READ(csrs, csr_port_status)) & PDQ_PSTS_INTR_PENDING) {
progress = 1;
PDQ_PRINTF(("PDQ Interrupt: Status = 0x%08x\n", data));
PDQ_OS_CONSUMER_POSTSYNC(pdq);
if (data & PDQ_PSTS_RCV_DATA_PENDING) {
pdq_process_received_data(pdq, &pdq->pdq_rx_info,
pdq->pdq_dbp->pdqdb_receives,
@ -1284,7 +1442,7 @@ pdq_interrupt(
PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt));
PDQ_DO_HOST_SMT_PRODUCER(pdq);
}
if (data & PDQ_PSTS_XMT_DATA_PENDING)
/* if (data & PDQ_PSTS_XMT_DATA_PENDING) */
pdq_process_transmitted_data(pdq);
if (data & PDQ_PSTS_UNSOL_PENDING)
pdq_process_unsolicited_events(pdq);
@ -1296,9 +1454,13 @@ pdq_interrupt(
pdq_state_t state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status));
printf(PDQ_OS_PREFIX "%s", PDQ_OS_PREFIX_ARGS, pdq_adapter_states[state]);
if (state == PDQS_LINK_UNAVAILABLE) {
pdq->pdq_flags &= ~PDQ_TXOK;
pdq->pdq_flags &= ~(PDQ_TXOK|PDQ_IS_ONRING|PDQ_IS_FDX);
} else if (state == PDQS_LINK_AVAILABLE) {
pdq->pdq_flags |= PDQ_TXOK;
if (pdq->pdq_flags & PDQ_WANT_FDX) {
pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_DEC_EXT_MIB_GET);
pdq_queue_commands(pdq);
}
pdq->pdq_flags |= PDQ_TXOK|PDQ_IS_ONRING;
pdq_os_restart_transmitter(pdq);
} else if (state == PDQS_HALTED) {
pdq_response_error_log_get_t log_entry;
@ -1310,7 +1472,28 @@ pdq_interrupt(
PDQ_CSR_READ(&pdq->pdq_pci_csrs, csr_pfi_status),
data & PDQ_HOST_INT_FATAL_ERROR));
}
pdq_read_error_log(pdq, &log_entry);
PDQ_OS_MEMZERO(&log_entry, sizeof(log_entry));
if (pdq_read_error_log(pdq, &log_entry)) {
PDQ_PRINTF((" Error log Entry:\n"));
PDQ_PRINTF((" CMD Status = %d (0x%x)\n",
log_entry.error_log_get_status,
log_entry.error_log_get_status));
PDQ_PRINTF((" Event Status = %d (0x%x)\n",
log_entry.error_log_get_event_status,
log_entry.error_log_get_event_status));
PDQ_PRINTF((" Caller Id = %d (0x%x)\n",
log_entry.error_log_get_caller_id,
log_entry.error_log_get_caller_id));
PDQ_PRINTF((" Write Count = %d (0x%x)\n",
log_entry.error_log_get_write_count,
log_entry.error_log_get_write_count));
PDQ_PRINTF((" FRU Implication Mask = %d (0x%x)\n",
log_entry.error_log_get_fru_implication_mask,
log_entry.error_log_get_fru_implication_mask));
PDQ_PRINTF((" Test ID = %d (0x%x)\n",
log_entry.error_log_get_test_id,
log_entry.error_log_get_test_id));
}
pdq_stop(pdq);
if (pdq->pdq_flags & PDQ_RUNNING)
pdq_run(pdq);
@ -1350,8 +1533,11 @@ pdq_initialize(
{
pdq_t *pdq;
pdq_state_t state;
pdq_descriptor_block_t *dbp;
#if !defined(PDQ_BUS_DMA)
const pdq_uint32_t contig_bytes = (sizeof(pdq_descriptor_block_t) * 2) - PDQ_OS_PAGESIZE;
pdq_uint8_t *p;
#endif
int idx;
PDQ_ASSERT(sizeof(pdq_descriptor_block_t) == 8192);
@ -1387,32 +1573,46 @@ pdq_initialize(
* buffers (though on machines with 8KB pages we will to allocate
* them separately since there will be nothing left overs.)
*/
#if defined(PDQ_OS_MEMALLOC_CONTIG)
p = (pdq_uint8_t *) PDQ_OS_MEMALLOC_CONTIG(contig_bytes);
if (p == NULL)
printf("%s() - PDQ_OS_MEMALLOC_CONTIG() failed!\n", __FUNCTION__);
if (p != NULL) {
pdq_physaddr_t physaddr = PDQ_OS_VA_TO_PA(pdq, p);
pdq_physaddr_t physaddr = PDQ_OS_VA_TO_BUSPA(pdq, p);
/*
* Assert that we really got contiguous memory. This isn't really
* needed on systems that actually have physical contiguous allocation
* routines, but on those systems that don't ...
*/
for (idx = PDQ_OS_PAGESIZE; idx < 0x2000; idx += PDQ_OS_PAGESIZE) {
if (PDQ_OS_VA_TO_PA(pdq, p + idx) - physaddr != idx)
if (PDQ_OS_VA_TO_BUSPA(pdq, p + idx) - physaddr != idx)
goto cleanup_and_return;
}
physaddr &= 0x1FFF;
if (physaddr) {
if (physaddr & 0x1FFF) {
pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) p;
pdq->pdq_dbp = (pdq_descriptor_block_t *) &p[0x2000 - physaddr];
pdq->pdq_unsolicited_info.ui_pa_bufstart = physaddr;
pdq->pdq_dbp = (pdq_descriptor_block_t *) &p[0x2000 - (physaddr & 0x1FFF)];
pdq->pdq_pa_descriptor_block = physaddr & ~0x1FFFUL;
} else {
pdq->pdq_dbp = (pdq_descriptor_block_t *) p;
pdq->pdq_pa_descriptor_block = physaddr;
pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) &p[0x2000];
pdq->pdq_unsolicited_info.ui_pa_bufstart = physaddr + 0x2000;
}
}
pdq->pdq_cbp = (volatile pdq_consumer_block_t *) &pdq->pdq_dbp->pdqdb_consumer;
pdq->pdq_pa_consumer_block = PDQ_DB_BUSPA(pdq, pdq->pdq_cbp);
if (contig_bytes == sizeof(pdq_descriptor_block_t)) {
pdq->pdq_unsolicited_info.ui_events =
(pdq_unsolicited_event_t *) PDQ_OS_MEMALLOC(
PDQ_NUM_UNSOLICITED_EVENTS * sizeof(pdq_unsolicited_event_t));
}
#else
if (pdq_os_memalloc_contig(pdq))
goto cleanup_and_return;
#endif
/*
* Make sure everything got allocated. If not, free what did
@ -1420,27 +1620,24 @@ pdq_initialize(
*/
if (pdq->pdq_dbp == NULL || pdq->pdq_unsolicited_info.ui_events == NULL) {
cleanup_and_return:
#ifdef PDQ_OS_MEMFREE_CONTIG
if (p /* pdq->pdq_dbp */ != NULL)
PDQ_OS_MEMFREE_CONTIG(p /* pdq->pdq_dbp */, contig_bytes);
if (contig_bytes == sizeof(pdq_descriptor_block_t) && pdq->pdq_unsolicited_info.ui_events != NULL)
PDQ_OS_MEMFREE(pdq->pdq_unsolicited_info.ui_events,
PDQ_NUM_UNSOLICITED_EVENTS * sizeof(pdq_unsolicited_event_t));
#endif
PDQ_OS_MEMFREE(pdq, sizeof(pdq_t));
return NULL;
}
dbp = pdq->pdq_dbp;
pdq->pdq_cbp = (volatile pdq_consumer_block_t *) &pdq->pdq_dbp->pdqdb_consumer;
pdq->pdq_command_info.ci_bufstart = (pdq_uint8_t *) pdq->pdq_dbp->pdqdb_command_pool;
pdq->pdq_rx_info.rx_buffers = (void *) pdq->pdq_dbp->pdqdb_receive_buffers;
pdq->pdq_host_smt_info.rx_buffers = (void *) pdq->pdq_dbp->pdqdb_host_smt_buffers;
PDQ_PRINTF(("\nPDQ Descriptor Block = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp));
PDQ_PRINTF((" Recieve Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_receives));
PDQ_PRINTF((" Transmit Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_transmits));
PDQ_PRINTF((" Host SMT Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_host_smt));
PDQ_PRINTF((" Command Response Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_command_responses));
PDQ_PRINTF((" Command Request Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_command_requests));
PDQ_PRINTF(("\nPDQ Descriptor Block = " PDQ_OS_PTR_FMT " (PA = 0x%x)\n", dbp, pdq->pdq_pa_descriptor_block));
PDQ_PRINTF((" Receive Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_receives));
PDQ_PRINTF((" Transmit Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_transmits));
PDQ_PRINTF((" Host SMT Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_host_smt));
PDQ_PRINTF((" Command Response Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_command_responses));
PDQ_PRINTF((" Command Request Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_command_requests));
PDQ_PRINTF(("PDQ Consumer Block = " PDQ_OS_PTR_FMT "\n", pdq->pdq_cbp));
/*
@ -1449,7 +1646,7 @@ pdq_initialize(
* block, command pool, and buffer pointers for the receive
* host_smt rings.
*/
PDQ_OS_MEMZERO(pdq->pdq_dbp, sizeof(*pdq->pdq_dbp));
PDQ_OS_MEMZERO(dbp, sizeof(*dbp));
/*
* Initialize the CSR references.
@ -1459,61 +1656,81 @@ pdq_initialize(
if (pdq->pdq_type == PDQ_DEFPA)
pdq_init_pci_csrs(&pdq->pdq_pci_csrs, bus, csr_base, 1);
PDQ_PRINTF(("PDQ CSRs: BASE = " PDQ_OS_PTR_FMT "\n", pdq->pdq_csrs.csr_base));
PDQ_PRINTF((" Port Reset = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF(("PDQ CSRs: BASE = " PDQ_OS_CSR_FMT "\n", pdq->pdq_csrs.csr_base));
PDQ_PRINTF((" Port Reset = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_port_reset, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_reset)));
PDQ_PRINTF((" Host Data = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Host Data = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_host_data, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_data)));
PDQ_PRINTF((" Port Control = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Port Control = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_port_control, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_control)));
PDQ_PRINTF((" Port Data A = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Port Data A = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_port_data_a, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_data_a)));
PDQ_PRINTF((" Port Data B = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Port Data B = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_port_data_b, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_data_b)));
PDQ_PRINTF((" Port Status = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Port Status = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_port_status, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status)));
PDQ_PRINTF((" Host Int Type 0 = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Host Int Type 0 = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_host_int_type_0, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_type_0)));
PDQ_PRINTF((" Host Int Enable = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Host Int Enable = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_host_int_enable, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_enable)));
PDQ_PRINTF((" Type 2 Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Type 2 Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_type_2_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_type_2_producer)));
PDQ_PRINTF((" Command Response Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Command Response Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_cmd_response_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_cmd_response_producer)));
PDQ_PRINTF((" Command Request Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Command Request Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_cmd_request_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_cmd_request_producer)));
PDQ_PRINTF((" Host SMT Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Host SMT Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_host_smt_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_smt_producer)));
PDQ_PRINTF((" Unsolicited Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n",
PDQ_PRINTF((" Unsolicited Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n",
pdq->pdq_csrs.csr_unsolicited_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_unsolicited_producer)));
/*
* Initialize the command information block
*/
pdq->pdq_command_info.ci_pa_bufstart = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_command_info.ci_bufstart);
for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_command_requests)/sizeof(pdq->pdq_dbp->pdqdb_command_requests[0]); idx++) {
pdq_txdesc_t *txd = &pdq->pdq_dbp->pdqdb_command_requests[idx];
pdq->pdq_command_info.ci_request_bufstart = dbp->pdqdb_cmd_request_buf;
pdq->pdq_command_info.ci_pa_request_bufstart = PDQ_DB_BUSPA(pdq, pdq->pdq_command_info.ci_request_bufstart);
pdq->pdq_command_info.ci_pa_request_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_command_requests);
PDQ_PRINTF(("PDQ Command Request Buffer = " PDQ_OS_PTR_FMT " (PA=0x%x)\n",
pdq->pdq_command_info.ci_request_bufstart,
pdq->pdq_command_info.ci_pa_request_bufstart));
for (idx = 0; idx < sizeof(dbp->pdqdb_command_requests)/sizeof(dbp->pdqdb_command_requests[0]); idx++) {
pdq_txdesc_t *txd = &dbp->pdqdb_command_requests[idx];
txd->txd_pa_lo = pdq->pdq_command_info.ci_pa_bufstart;
txd->txd_pa_lo = pdq->pdq_command_info.ci_pa_request_bufstart;
txd->txd_eop = txd->txd_sop = 1;
txd->txd_pa_hi = 0;
}
for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_command_responses)/sizeof(pdq->pdq_dbp->pdqdb_command_responses[0]); idx++) {
pdq_rxdesc_t *rxd = &pdq->pdq_dbp->pdqdb_command_responses[idx];
PDQ_OS_DESC_PRESYNC(pdq, dbp->pdqdb_command_requests,
sizeof(dbp->pdqdb_command_requests));
rxd->rxd_pa_lo = pdq->pdq_command_info.ci_pa_bufstart;
pdq->pdq_command_info.ci_response_bufstart = dbp->pdqdb_cmd_response_buf;
pdq->pdq_command_info.ci_pa_response_bufstart = PDQ_DB_BUSPA(pdq, pdq->pdq_command_info.ci_response_bufstart);
pdq->pdq_command_info.ci_pa_response_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_command_responses);
PDQ_PRINTF(("PDQ Command Response Buffer = " PDQ_OS_PTR_FMT " (PA=0x%x)\n",
pdq->pdq_command_info.ci_response_bufstart,
pdq->pdq_command_info.ci_pa_response_bufstart));
for (idx = 0; idx < sizeof(dbp->pdqdb_command_responses)/sizeof(dbp->pdqdb_command_responses[0]); idx++) {
pdq_rxdesc_t *rxd = &dbp->pdqdb_command_responses[idx];
rxd->rxd_pa_lo = pdq->pdq_command_info.ci_pa_response_bufstart;
rxd->rxd_sop = 1;
rxd->rxd_seg_cnt = 0;
rxd->rxd_seg_len_lo = 0;
rxd->rxd_seg_len_hi = PDQ_SIZE_COMMAND_RESPONSE / 16;
}
PDQ_OS_DESC_PRESYNC(pdq, dbp->pdqdb_command_responses,
sizeof(dbp->pdqdb_command_responses));
/*
* Initialize the unsolicited event information block
*/
pdq->pdq_unsolicited_info.ui_free = PDQ_NUM_UNSOLICITED_EVENTS;
pdq->pdq_unsolicited_info.ui_pa_bufstart = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_unsolicited_info.ui_events);
for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_unsolicited_events)/sizeof(pdq->pdq_dbp->pdqdb_unsolicited_events[0]); idx++) {
pdq_rxdesc_t *rxd = &pdq->pdq_dbp->pdqdb_unsolicited_events[idx];
pdq->pdq_unsolicited_info.ui_pa_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_unsolicited_events);
PDQ_PRINTF(("PDQ Unsolicit Event Buffer = " PDQ_OS_PTR_FMT " (PA=0x%x)\n",
pdq->pdq_unsolicited_info.ui_events,
pdq->pdq_unsolicited_info.ui_pa_bufstart));
for (idx = 0; idx < sizeof(dbp->pdqdb_unsolicited_events)/sizeof(dbp->pdqdb_unsolicited_events[0]); idx++) {
pdq_rxdesc_t *rxd = &dbp->pdqdb_unsolicited_events[idx];
pdq_unsolicited_event_t *event = &pdq->pdq_unsolicited_info.ui_events[idx & (PDQ_NUM_UNSOLICITED_EVENTS-1)];
rxd->rxd_sop = 1;
@ -1522,26 +1739,35 @@ pdq_initialize(
rxd->rxd_pa_lo = pdq->pdq_unsolicited_info.ui_pa_bufstart + (const pdq_uint8_t *) event
- (const pdq_uint8_t *) pdq->pdq_unsolicited_info.ui_events;
rxd->rxd_pa_hi = 0;
PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, event);
}
PDQ_OS_DESC_PRESYNC(pdq, dbp->pdqdb_unsolicited_events,
sizeof(dbp->pdqdb_unsolicited_events));
/*
* Initialize the receive information blocks (normal and SMT).
*/
pdq->pdq_rx_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives);
pdq->pdq_rx_info.rx_buffers = pdq->pdq_receive_buffers;
pdq->pdq_rx_info.rx_free = PDQ_RING_MASK(dbp->pdqdb_receives);
pdq->pdq_rx_info.rx_target = pdq->pdq_rx_info.rx_free - PDQ_RX_SEGCNT * 8;
pdq->pdq_rx_info.rx_pa_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_receives);
pdq->pdq_host_smt_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt);
pdq->pdq_host_smt_info.rx_buffers = pdq->pdq_host_smt_buffers;
pdq->pdq_host_smt_info.rx_free = PDQ_RING_MASK(dbp->pdqdb_host_smt);
pdq->pdq_host_smt_info.rx_target = pdq->pdq_host_smt_info.rx_free - PDQ_RX_SEGCNT * 3;
pdq->pdq_host_smt_info.rx_pa_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_host_smt);
/*
* Initialize the transmit information block.
*/
pdq->pdq_tx_hdr[0] = PDQ_FDDI_PH0;
pdq->pdq_tx_hdr[1] = PDQ_FDDI_PH1;
pdq->pdq_tx_hdr[2] = PDQ_FDDI_PH2;
pdq->pdq_tx_info.tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits);
pdq->pdq_tx_info.tx_hdrdesc.txd_seg_len = sizeof(pdq->pdq_tx_hdr);
dbp->pdqdb_tx_hdr[0] = PDQ_FDDI_PH0;
dbp->pdqdb_tx_hdr[1] = PDQ_FDDI_PH1;
dbp->pdqdb_tx_hdr[2] = PDQ_FDDI_PH2;
pdq->pdq_tx_info.tx_free = PDQ_RING_MASK(dbp->pdqdb_transmits);
pdq->pdq_tx_info.tx_hdrdesc.txd_seg_len = 3;
pdq->pdq_tx_info.tx_hdrdesc.txd_sop = 1;
pdq->pdq_tx_info.tx_hdrdesc.txd_pa_lo = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_tx_hdr);
pdq->pdq_tx_info.tx_hdrdesc.txd_pa_lo = PDQ_DB_BUSPA(pdq, dbp->pdqdb_tx_hdr);
pdq->pdq_tx_info.tx_pa_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_transmits);
state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status));
PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states[state]));

271
sys/dev/pdq/pdq_freebsd.h Normal file
View file

@ -0,0 +1,271 @@
/* $NetBSD: pdqvar.h,v 1.27 2000/05/03 19:17:54 thorpej Exp $ */
/*-
* Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Id: pdqvar.h,v 1.21 1997/03/21 21:16:04 thomas Exp
* $FreeBSD$
*
*/
/*
* DEC PDQ FDDI Controller; PDQ O/S dependent definitions
*
* Written by Matt Thomas
*
*/
#if defined(PDQ_HWSUPPORT)
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus_memio.h>
#include <machine/bus_pio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/fddi.h>
#include <net/bpf.h>
#include <vm/vm.h> /* for vtophys */
#include <vm/pmap.h> /* for vtophys */
#include <machine/clock.h> /* for DELAY */
#endif /* PDQ_HWSUPPORT */
typedef struct _pdq_t pdq_t;
typedef struct _pdq_csrs_t pdq_csrs_t;
typedef struct _pdq_pci_csrs_t pdq_pci_csrs_t;
typedef struct _pdq_lanaddr_t pdq_lanaddr_t;
typedef unsigned int pdq_uint32_t;
typedef unsigned short pdq_uint16_t;
typedef unsigned char pdq_uint8_t;
typedef enum _pdq_boolean_t pdq_boolean_t;
typedef enum _pdq_type_t pdq_type_t;
typedef enum _pdq_state_t pdq_state_t;
typedef struct mbuf PDQ_OS_DATABUF_T;
typedef bus_space_tag_t pdq_bus_t;
typedef bus_space_handle_t pdq_bus_memaddr_t;
typedef pdq_bus_memaddr_t pdq_bus_memoffset_t;
extern devclass_t pdq_devclass;
enum _pdq_type_t {
PDQ_DEFPA, /* PCI-bus */
PDQ_DEFEA, /* EISA-bus */
PDQ_DEFTA, /* TurboChannel */
PDQ_DEFAA, /* FutureBus+ */
PDQ_DEFQA /* Q-bus */
};
#define sc_ifmedia ifmedia
#define sc_if arpcom.ac_if
#define sc_bpf sc_if.if_bpf
#define IFQ_DEQUEUE IF_DEQUEUE
#define IFQ_IS_EMPTY(q) ((q)->ifq_len == 0)
typedef struct _pdq_os_ctx_t {
struct arpcom arpcom;
struct ifmedia ifmedia;
device_t dev;
int debug;
pdq_t * sc_pdq;
int sc_flags;
#define PDQIF_DOWNCALL 0x0001 /* active calling from if to pdq */
struct resource * io;
int io_rid;
int io_type;
bus_space_handle_t io_bsh;
bus_space_tag_t io_bst;
struct resource * mem;
int mem_rid;
int mem_type;
bus_space_handle_t mem_bsh;
bus_space_tag_t mem_bst;
struct resource * irq;
int irq_rid;
void * irq_ih;
struct mtx mtx;
} pdq_softc_t;
#define PDQ_LOCK(_sc) mtx_lock(&(_sc)->mtx)
#define PDQ_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
#define PDQ_OS_HDR_OFFSET PDQ_RX_FC_OFFSET
#define PDQ_OS_PAGESIZE PAGE_SIZE
#define PDQ_OS_TX_TRANSMIT 5
#define PDQ_OS_IORD_32(bt, bh, off) bus_space_read_4(bt, bh, off)
#define PDQ_OS_IOWR_32(bt, bh, off, data) bus_space_write_4(bt, bh, off, data)
#define PDQ_OS_IORD_8(bt, bh, off) bus_space_read_1(bt, bh, off)
#define PDQ_OS_IOWR_8(bt, bh, off, data) bus_space_write_1(bt, bh, off, data)
#define PDQ_CSR_OFFSET(base, offset) (0 + (offset)*sizeof(pdq_uint32_t))
#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_IOWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data)
#define PDQ_CSR_READ(csr, name) PDQ_OS_IORD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name)
#define PDQ_OS_DATABUF_FREE(pdq, b) (m_freem(b))
#if defined(PDQ_OSSUPPORT)
#define PDQ_OS_TX_TIMEOUT 5 /* seconds */
#define PDQ_OS_IFP_TO_SOFTC(ifp) ((pdq_softc_t *) (ifp)->if_softc)
#define PDQ_BPF_MTAP(sc, m) bpf_mtap(&(sc)->arpcom.ac_if, m)
#endif /* PDQ_OSSUPPORT */
#if defined(PDQ_HWSUPPORT)
#define PDQ_OS_PREFIX "%s%d: "
#define PDQ_OS_PREFIX_ARGS pdq->pdq_os_name, pdq->pdq_unit
#define PDQ_OS_PTR_FMT "%p"
#define PDQ_OS_CSR_FMT "0x%x"
#define PDQ_OS_USEC_DELAY(n) DELAY(n)
#define PDQ_OS_VA_TO_BUSPA(pdq, p) vtophys(p)
#define PDQ_OS_MEMALLOC(n) malloc(n, M_DEVBUF, M_NOWAIT)
#define PDQ_OS_MEMFREE(p, n) free((void *) p, M_DEVBUF)
#define PDQ_OS_MEMZERO(p, n) bzero((caddr_t)(p), (n))
#define PDQ_OS_MEMALLOC_CONTIG(n) contigmalloc(n, M_DEVBUF, M_NOWAIT, 0x800000, ~0, PAGE_SIZE, 0)
#define PDQ_OS_MEMFREE_CONTIG(p, n) contigfree(p, n, M_DEVBUF)
#define PDQ_OS_DATABUF_SIZE (MCLBYTES)
#define PDQ_OS_DATABUF_NEXT(b) ((b)->m_next)
#define PDQ_OS_DATABUF_NEXT_SET(b, b1) ((b)->m_next = (b1))
#define PDQ_OS_DATABUF_NEXTPKT(b) ((b)->m_nextpkt)
#define PDQ_OS_DATABUF_NEXTPKT_SET(b, b1) ((b)->m_nextpkt = (b1))
#define PDQ_OS_DATABUF_LEN(b) ((b)->m_len)
#define PDQ_OS_DATABUF_LEN_SET(b, n) ((b)->m_len = (n))
/* #define PDQ_OS_DATABUF_LEN_ADJ(b, n) ((b)->m_len += (n)) */
#define PDQ_OS_DATABUF_PTR(b) (mtod((b), pdq_uint8_t *))
#define PDQ_OS_DATABUF_ADJ(b, n) ((b)->m_data += (n), (b)->m_len -= (n))
#define PDQ_OS_DATABUF_ALLOC(pdq, b) do { \
PDQ_OS_DATABUF_T *x_m0; \
MGETHDR(x_m0, M_DONTWAIT, MT_DATA); \
if (x_m0 != NULL) { \
MCLGET(x_m0, M_DONTWAIT); \
if ((x_m0->m_flags & M_EXT) == 0) { \
m_free(x_m0); \
(b) = NULL; \
} else { \
(b) = x_m0; \
x_m0->m_len = PDQ_OS_DATABUF_SIZE; \
} \
} else { \
(b) = NULL; \
} \
} while (0)
#define PDQ_OS_DATABUF_RESET(b) ((b)->m_data = (b)->m_ext.ext_buf, (b)->m_len = MCLBYTES)
#define PDQ_OS_DATABUF_ENQUEUE(q, b) do { \
PDQ_OS_DATABUF_NEXTPKT_SET(b, NULL); \
if ((q)->q_tail == NULL) \
(q)->q_head = (b); \
else \
PDQ_OS_DATABUF_NEXTPKT_SET(((PDQ_OS_DATABUF_T *)(q)->q_tail), b); \
(q)->q_tail = (b); \
} while (0)
#define PDQ_OS_DATABUF_DEQUEUE(q, b) do { \
if (((b) = (PDQ_OS_DATABUF_T *) (q)->q_head) != NULL) { \
if (((q)->q_head = PDQ_OS_DATABUF_NEXTPKT(b)) == NULL) \
(q)->q_tail = NULL; \
PDQ_OS_DATABUF_NEXTPKT_SET(b, NULL); \
} \
} while (0)
#define PDQ_OS_DATABUF_BUSPA(pdq, b) PDQ_OS_VA_TO_BUSPA(pdq, PDQ_OS_DATABUF_PTR(b))
#define PDQ_OS_CONSUMER_PRESYNC(pdq) do { } while(0)
#define PDQ_OS_CONSUMER_POSTSYNC(pdq) do { } while(0)
#define PDQ_OS_DESC_PRESYNC(pdq, d, s) do { } while(0)
#define PDQ_OS_DESC_POSTSYNC(pdq, d, s) do { } while(0)
#define PDQ_OS_CMDRQST_PRESYNC(pdq, s) do { } while(0)
#define PDQ_OS_CMDRQST_POSTSYNC(pdq, s) do { } while(0)
#define PDQ_OS_CMDRSP_PRESYNC(pdq, s) do { } while(0)
#define PDQ_OS_CMDRSP_POSTSYNC(pdq, s) do { } while(0)
#define PDQ_OS_RXPDU_PRESYNC(pdq, b, o, l) do { } while(0)
#define PDQ_OS_RXPDU_POSTSYNC(pdq, b, o, l) do { } while(0)
#define PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, e) do { } while(0)
#define PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq, e) do { } while(0)
#endif /* PDQ_HWSUPPORT */
/*
* OS dependent functions provided by pdq_ifsubr.c to pdq.c
*/
void pdq_os_addr_fill (pdq_t *pdq, pdq_lanaddr_t *addrs, size_t numaddrs);
void pdq_os_receive_pdu (pdq_t *, PDQ_OS_DATABUF_T *, size_t, int);
void pdq_os_restart_transmitter (pdq_t *pdq);
void pdq_os_transmit_done (pdq_t *, PDQ_OS_DATABUF_T *);
void pdq_os_update_status (pdq_t *, const void *);
/*
* Driver interfaces functions provided by pdq.c to pdq_ifsubr.c
*/
pdq_boolean_t pdq_queue_transmit_data (pdq_t *pdq, PDQ_OS_DATABUF_T *pdu);
void pdq_run (pdq_t *pdq);
pdq_state_t pdq_stop (pdq_t *pdq);
/*
* OS dependent functions provided by
* pdq_ifsubr.c or pdq.c to the bus front ends
*/
void pdq_ifattach (pdq_softc_t *);
void pdq_ifdetach (pdq_softc_t *);
void pdq_free (device_t);
int pdq_interrupt (pdq_t *pdq);
void pdq_hwreset (pdq_t *pdq);
pdq_t * pdq_initialize (pdq_bus_t bus, pdq_bus_memaddr_t csr_va,
const char *name, int unit,
void *ctx, pdq_type_t type);
/*
* Misc prototypes.
*/
void pdq_flush_transmitter(pdq_t *pdq);

View file

@ -1,3 +1,5 @@
/* $NetBSD: pdq_ifsubr.c,v 1.38 2001/12/21 23:21:47 matt Exp $ */
/*-
* Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
@ -8,7 +10,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -21,8 +23,8 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $NetBSD: pdq_ifsubr.c,v 1.12 1997/06/05 01:56:35 thomas Exp$
* $FreeBSD$
*
*/
/*
@ -32,65 +34,45 @@
* (ie. it provides an ifnet interface to the rest of the system)
*/
#include "opt_inet.h"
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#if defined(__bsdi__) || defined(__NetBSD__)
#include <sys/device.h>
#ifdef __NetBSD__
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pdq_ifsubr.c,v 1.38 2001/12/21 23:21:47 matt Exp $");
#endif
#define PDQ_OSSUPPORT
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus_memio.h>
#include <machine/bus_pio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/fddi.h>
#include <net/bpf.h>
#if defined(__FreeBSD__)
#ifdef INET
#include <netinet/in.h>
#include <netinet/if_ether.h>
#endif
#include <netinet/if_fddi.h>
#else
#include <net/if_fddi.h>
#endif
#if defined(__bsdi__)
#include <i386/isa/isavar.h>
#endif
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
#endif
#if defined(__FreeBSD__)
#include <dev/pdq/pdqvar.h>
#include <dev/pdq/pdq_freebsd.h>
#include <dev/pdq/pdqreg.h>
#else
#include "pdqvar.h"
#include "pdqreg.h"
#endif
#if defined(__bsdi__) && _BSDI_VERSION < 199506 /* XXX */
devclass_t pdq_devclass;
static void
arp_ifinit(
struct arpcom *ac,
struct ifaddr *ifa)
{
sc->sc_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr;
arpwhohas(&sc->sc_ac, &IA_SIN(ifa)->sin_addr);
#if _BSDI_VERSION >= 199401
ifa->ifa_rtrequest = arp_rtrequest;
ifa->ifa_flags |= RTF_CLONING;
#endif
}
#endif
void
pdq_ifinit(
pdq_softc_t *sc)
{
@ -101,11 +83,6 @@ pdq_ifinit(
} else {
sc->sc_pdq->pdq_flags &= ~PDQ_PROMISC;
}
if (sc->sc_if.if_flags & IFF_ALLMULTI) {
sc->sc_pdq->pdq_flags |= PDQ_ALLMULTI;
} else {
sc->sc_pdq->pdq_flags &= ~PDQ_ALLMULTI;
}
if (sc->sc_if.if_flags & IFF_LINK1) {
sc->sc_pdq->pdq_flags |= PDQ_PASS_SMT;
} else {
@ -120,7 +97,7 @@ pdq_ifinit(
}
}
void
static void
pdq_ifwatchdog(
struct ifnet *ifp)
{
@ -131,15 +108,20 @@ pdq_ifwatchdog(
ifp->if_flags &= ~IFF_OACTIVE;
ifp->if_timer = 0;
IF_DRAIN(&ifp->if_snd);
for (;;) {
struct mbuf *m;
IFQ_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
return;
PDQ_OS_DATABUF_FREE(PDQ_OS_IFP_TO_SOFTC(ifp)->sc_pdq, m);
}
}
ifnet_ret_t
static void
pdq_ifstart(
struct ifnet *ifp)
{
pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if));
struct ifqueue *ifq = &ifp->if_snd;
pdq_softc_t * const sc = PDQ_OS_IFP_TO_SOFTC(ifp);
struct mbuf *m;
int tx = 0;
@ -153,41 +135,95 @@ pdq_ifstart(
sc->sc_if.if_flags |= IFF_OACTIVE;
return;
}
sc->sc_flags |= PDQIF_DOWNCALL;
for (;; tx = 1) {
IF_DEQUEUE(ifq, m);
IF_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE) {
ifp->if_flags |= IFF_OACTIVE;
IF_PREPEND(ifq, m);
break;
#if defined(PDQ_BUS_DMA) && !defined(PDQ_BUS_DMA_NOTX)
if ((m->m_flags & M_HASTXDMAMAP) == 0) {
bus_dmamap_t map;
if (PDQ_OS_HDR_OFFSET != PDQ_RX_FC_OFFSET) {
m->m_data[0] = PDQ_FDDI_PH0;
m->m_data[1] = PDQ_FDDI_PH1;
m->m_data[2] = PDQ_FDDI_PH2;
}
if (!bus_dmamap_create(sc->sc_dmatag, m->m_pkthdr.len, 255,
m->m_pkthdr.len, 0, BUS_DMA_NOWAIT, &map)) {
if (!bus_dmamap_load_mbuf(sc->sc_dmatag, map, m,
BUS_DMA_WRITE|BUS_DMA_NOWAIT)) {
bus_dmamap_sync(sc->sc_dmatag, map, 0, m->m_pkthdr.len,
BUS_DMASYNC_PREWRITE);
M_SETCTX(m, map);
m->m_flags |= M_HASTXDMAMAP;
}
}
if ((m->m_flags & M_HASTXDMAMAP) == 0)
break;
}
#else
if (PDQ_OS_HDR_OFFSET != PDQ_RX_FC_OFFSET) {
m->m_data[0] = PDQ_FDDI_PH0;
m->m_data[1] = PDQ_FDDI_PH1;
m->m_data[2] = PDQ_FDDI_PH2;
}
#endif
if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE)
break;
}
if (m != NULL) {
ifp->if_flags |= IFF_OACTIVE;
IF_PREPEND(&ifp->if_snd, m);
}
if (tx)
PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq);
sc->sc_flags &= ~PDQIF_DOWNCALL;
}
void
pdq_os_receive_pdu(
pdq_t *pdq,
struct mbuf *m,
size_t pktlen)
size_t pktlen,
int drop)
{
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
struct fddi_header *fh = mtod(m, struct fddi_header *);
pdq_softc_t *sc = pdq->pdq_os_ctx;
struct fddi_header *fh;
sc->sc_if.if_ipackets++;
#if defined(PDQ_BUS_DMA)
{
/*
* Even though the first mbuf start at the first fddi header octet,
* the dmamap starts PDQ_OS_HDR_OFFSET octets earlier. Any additional
* mbufs will start normally.
*/
int offset = PDQ_OS_HDR_OFFSET;
struct mbuf *m0;
for (m0 = m; m0 != NULL; m0 = m0->m_next, offset = 0) {
pdq_os_databuf_sync(sc, m0, offset, m0->m_len, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->sc_dmatag, M_GETCTX(m0, bus_dmamap_t));
bus_dmamap_destroy(sc->sc_dmatag, M_GETCTX(m0, bus_dmamap_t));
m0->m_flags &= ~M_HASRXDMAMAP;
M_SETCTX(m0, NULL);
}
}
#endif
m->m_pkthdr.len = pktlen;
#if NBPFILTER > 0
if (sc->sc_bpf != NULL)
PDQ_BPF_MTAP(sc, m);
if ((fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
m_freem(m);
#endif
fh = mtod(m, struct fddi_header *);
if (drop || (fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) {
sc->sc_if.if_iqdrops++;
sc->sc_if.if_ierrors++;
PDQ_OS_DATABUF_FREE(pdq, m);
return;
}
m->m_data += sizeof(struct fddi_header);
m->m_len -= sizeof(struct fddi_header);
m->m_pkthdr.len = pktlen - sizeof(struct fddi_header);
m_adj(m, FDDI_HDR_LEN);
m->m_pkthdr.rcvif = &sc->sc_if;
fddi_input(&sc->sc_if, fh, m);
}
@ -196,11 +232,12 @@ void
pdq_os_restart_transmitter(
pdq_t *pdq)
{
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
pdq_softc_t *sc = pdq->pdq_os_ctx;
sc->sc_if.if_flags &= ~IFF_OACTIVE;
if (sc->sc_if.if_snd.ifq_head != NULL) {
if (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0) {
sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT;
pdq_ifstart(&sc->sc_if);
if ((sc->sc_flags & PDQIF_DOWNCALL) == 0)
pdq_ifstart(&sc->sc_if);
} else {
sc->sc_if.if_timer = 0;
}
@ -211,10 +248,12 @@ pdq_os_transmit_done(
pdq_t *pdq,
struct mbuf *m)
{
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
pdq_softc_t *sc = pdq->pdq_os_ctx;
#if NBPFILTER > 0
if (sc->sc_bpf != NULL)
PDQ_BPF_MTAP(sc, m);
m_freem(m);
#endif
PDQ_OS_DATABUF_FREE(pdq, m);
sc->sc_if.if_opackets++;
}
@ -224,9 +263,23 @@ pdq_os_addr_fill(
pdq_lanaddr_t *addr,
size_t num_addrs)
{
pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx;
pdq_softc_t *sc = pdq->pdq_os_ctx;
struct ifnet *ifp;
struct ifmultiaddr *ifma;
ifp = &sc->arpcom.ac_if;
/*
* ADDR_FILTER_SET is always issued before FILTER_SET so
* we can play with PDQ_ALLMULTI and not worry about
* queueing a FILTER_SET ourselves.
*/
pdq->pdq_flags &= ~PDQ_ALLMULTI;
#if defined(IFF_ALLMULTI)
sc->sc_if.if_flags &= ~IFF_ALLMULTI;
#endif
for (ifma = TAILQ_FIRST(&sc->sc_if.if_multiaddrs); ifma && num_addrs > 0;
ifma = TAILQ_NEXT(ifma, ifma_link)) {
char *mcaddr;
@ -239,66 +292,95 @@ pdq_os_addr_fill(
addr++;
num_addrs--;
}
/*
* If not all the address fit into the CAM, turn on all-multicast mode.
*/
if (ifma != NULL) {
pdq->pdq_flags |= PDQ_ALLMULTI;
#if defined(IFF_ALLMULTI)
sc->sc_if.if_flags |= IFF_ALLMULTI;
#endif
}
}
int
#if defined(IFM_FDDI)
static int
pdq_ifmedia_change(
struct ifnet *ifp)
{
pdq_softc_t * const sc = PDQ_OS_IFP_TO_SOFTC(ifp);
if (sc->sc_ifmedia.ifm_media & IFM_FDX) {
if ((sc->sc_pdq->pdq_flags & PDQ_WANT_FDX) == 0) {
sc->sc_pdq->pdq_flags |= PDQ_WANT_FDX;
if (sc->sc_pdq->pdq_flags & PDQ_RUNNING)
pdq_run(sc->sc_pdq);
}
} else if (sc->sc_pdq->pdq_flags & PDQ_WANT_FDX) {
sc->sc_pdq->pdq_flags &= ~PDQ_WANT_FDX;
if (sc->sc_pdq->pdq_flags & PDQ_RUNNING)
pdq_run(sc->sc_pdq);
}
return 0;
}
static void
pdq_ifmedia_status(
struct ifnet *ifp,
struct ifmediareq *ifmr)
{
pdq_softc_t * const sc = PDQ_OS_IFP_TO_SOFTC(ifp);
ifmr->ifm_status = IFM_AVALID;
if (sc->sc_pdq->pdq_flags & PDQ_IS_ONRING)
ifmr->ifm_status |= IFM_ACTIVE;
ifmr->ifm_active = (ifmr->ifm_current & ~IFM_FDX);
if (sc->sc_pdq->pdq_flags & PDQ_IS_FDX)
ifmr->ifm_active |= IFM_FDX;
}
void
pdq_os_update_status(
pdq_t *pdq,
const void *arg)
{
pdq_softc_t * const sc = pdq->pdq_os_ctx;
const pdq_response_status_chars_get_t *rsp = arg;
int media = 0;
switch (rsp->status_chars_get.pmd_type[0]) {
case PDQ_PMD_TYPE_ANSI_MUTLI_MODE: media = IFM_FDDI_MMF; break;
case PDQ_PMD_TYPE_ANSI_SINGLE_MODE_TYPE_1: media = IFM_FDDI_SMF; break;
case PDQ_PMD_TYPE_ANSI_SIGNLE_MODE_TYPE_2: media = IFM_FDDI_SMF; break;
case PDQ_PMD_TYPE_UNSHIELDED_TWISTED_PAIR: media = IFM_FDDI_UTP; break;
default: media |= IFM_MANUAL;
}
if (rsp->status_chars_get.station_type == PDQ_STATION_TYPE_DAS)
media |= IFM_FDDI_DA;
sc->sc_ifmedia.ifm_media = media | IFM_FDDI;
}
#endif /* defined(IFM_FDDI) */
static int
pdq_ifioctl(
struct ifnet *ifp,
ioctl_cmd_t cmd,
u_long cmd,
caddr_t data)
{
pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if));
int s, error = 0;
pdq_softc_t *sc = PDQ_OS_IFP_TO_SOFTC(ifp);
int error = 0;
s = splimp();
PDQ_LOCK(sc);
switch (cmd) {
case SIOCSIFMTU:
case SIOCGIFADDR:
case SIOCSIFADDR: {
struct ifaddr *ifa = (struct ifaddr *)data;
ifp->if_flags |= IFF_UP;
switch(ifa->ifa_addr->sa_family) {
#if defined(INET)
case AF_INET: {
pdq_ifinit(sc);
arp_ifinit(&sc->sc_ac.ac_if, ifa);
break;
}
#endif /* INET */
#if defined(NS)
/* This magic copied from if_is.c; I don't use XNS,
* so I have no way of telling if this actually
* works or not.
*/
case AF_NS: {
struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
if (ns_nullhost(*ina)) {
ina->x_host = *(union ns_host *)(sc->sc_ac.ac_enaddr);
} else {
ifp->if_flags &= ~IFF_RUNNING;
bcopy((caddr_t)ina->x_host.c_host,
(caddr_t)sc->sc_ac.ac_enaddr,
sizeof sc->sc_ac.ac_enaddr);
}
pdq_ifinit(sc);
break;
}
#endif /* NS */
default: {
pdq_ifinit(sc);
break;
}
}
break;
}
case SIOCGIFADDR: {
struct ifreq *ifr = (struct ifreq *)data;
bcopy((caddr_t) sc->sc_ac.ac_enaddr,
(caddr_t) ((struct sockaddr *)&ifr->ifr_data)->sa_data,
6);
error = fddi_ioctl(ifp, cmd, data);
break;
}
@ -308,32 +390,22 @@ pdq_ifioctl(
}
case SIOCADDMULTI:
case SIOCDELMULTI:
/*
* Update multicast listeners
*/
if (sc->sc_if.if_flags & IFF_RUNNING)
pdq_run(sc->sc_pdq);
case SIOCDELMULTI: {
if (sc->sc_if.if_flags & IFF_RUNNING) {
pdq_run(sc->sc_pdq);
error = 0;
break;
#if defined(SIOCSIFMTU)
#if !defined(ifr_mtu)
#define ifr_mtu ifr_metric
#endif
case SIOCSIFMTU: {
struct ifreq *ifr = (struct ifreq *)data;
/*
* Set the interface MTU.
*/
if (ifr->ifr_mtu > FDDIMTU) {
error = EINVAL;
break;
}
ifp->if_mtu = ifr->ifr_mtu;
break;
}
#endif /* SIOCSIFMTU */
#if defined(IFM_FDDI) && defined(SIOCSIFMEDIA)
case SIOCSIFMEDIA:
case SIOCGIFMEDIA: {
struct ifreq *ifr = (struct ifreq *)data;
error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
break;
}
#endif
default: {
error = EINVAL;
@ -341,7 +413,7 @@ pdq_ifioctl(
}
}
splx(s);
PDQ_UNLOCK(sc);
return error;
}
@ -350,12 +422,15 @@ pdq_ifioctl(
#endif
void
pdq_ifattach(
pdq_softc_t *sc,
ifnet_ret_t (*ifwatchdog)(int unit))
pdq_ifattach(pdq_softc_t *sc)
{
struct ifnet *ifp = &sc->sc_if;
mtx_init(&sc->mtx, device_get_nameunit(sc->dev), MTX_DEF | MTX_RECURSE);
ifp->if_softc = sc;
ifp->if_init = (if_init_f_t *)pdq_ifinit;
ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
#if (defined(__FreeBSD__) && BSD >= 199506) || defined(__NetBSD__)
@ -365,13 +440,296 @@ pdq_ifattach(
#endif
ifp->if_ioctl = pdq_ifioctl;
#if !defined(__NetBSD__) && !defined(__FreeBSD__)
ifp->if_output = fddi_output;
#endif
ifp->if_start = pdq_ifstart;
ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
#warning "Implement fddi_resolvemulti!"
/* ifp->if_resolvemulti = ether_resolvemulti; XXX */
#if defined(IFM_FDDI)
{
const int media = sc->sc_ifmedia.ifm_media;
ifmedia_init(&sc->sc_ifmedia, IFM_FDX,
pdq_ifmedia_change, pdq_ifmedia_status);
ifmedia_add(&sc->sc_ifmedia, media, 0, 0);
ifmedia_set(&sc->sc_ifmedia, media);
}
#endif
if_attach(ifp);
fddi_ifattach(ifp);
PDQ_BPFATTACH(sc, DLT_FDDI, sizeof(struct fddi_header));
#if defined(__NetBSD__)
fddi_ifattach(ifp, (caddr_t)&sc->sc_pdq->pdq_hwaddr);
#else
fddi_ifattach(ifp, FDDI_BPF_SUPPORTED);
#endif
}
void
pdq_ifdetach (pdq_softc_t *sc)
{
struct ifnet *ifp;
ifp = &sc->arpcom.ac_if;
fddi_ifdetach(ifp, FDDI_BPF_SUPPORTED);
pdq_stop(sc->sc_pdq);
pdq_free(sc->dev);
return;
}
void
pdq_free (device_t dev)
{
pdq_softc_t *sc;
sc = device_get_softc(dev);
if (sc->io)
bus_release_resource(dev, sc->io_type, sc->io_rid, sc->io);
if (sc->mem)
bus_release_resource(dev, sc->mem_type, sc->mem_rid, sc->mem);
if (sc->irq_ih)
bus_teardown_intr(dev, sc->irq, sc->irq_ih);
if (sc->irq)
bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
/*
* Destroy the mutex.
*/
if (mtx_initialized(&sc->mtx) != 0) {
mtx_destroy(&sc->mtx);
}
return;
}
#if defined(PDQ_BUS_DMA)
int
pdq_os_memalloc_contig(
pdq_t *pdq)
{
pdq_softc_t * const sc = pdq->pdq_os_ctx;
bus_dma_segment_t db_segs[1], ui_segs[1], cb_segs[1];
int db_nsegs = 0, ui_nsegs = 0;
int steps = 0;
int not_ok;
not_ok = bus_dmamem_alloc(sc->sc_dmatag,
sizeof(*pdq->pdq_dbp), sizeof(*pdq->pdq_dbp),
sizeof(*pdq->pdq_dbp), db_segs, 1, &db_nsegs,
BUS_DMA_NOWAIT);
if (!not_ok) {
steps = 1;
not_ok = bus_dmamem_map(sc->sc_dmatag, db_segs, db_nsegs,
sizeof(*pdq->pdq_dbp), (caddr_t *) &pdq->pdq_dbp,
BUS_DMA_NOWAIT);
}
if (!not_ok) {
steps = 2;
not_ok = bus_dmamap_create(sc->sc_dmatag, db_segs[0].ds_len, 1,
0x2000, 0, BUS_DMA_NOWAIT, &sc->sc_dbmap);
}
if (!not_ok) {
steps = 3;
not_ok = bus_dmamap_load(sc->sc_dmatag, sc->sc_dbmap,
pdq->pdq_dbp, sizeof(*pdq->pdq_dbp),
NULL, BUS_DMA_NOWAIT);
}
if (!not_ok) {
steps = 4;
pdq->pdq_pa_descriptor_block = sc->sc_dbmap->dm_segs[0].ds_addr;
not_ok = bus_dmamem_alloc(sc->sc_dmatag,
PDQ_OS_PAGESIZE, PDQ_OS_PAGESIZE, PDQ_OS_PAGESIZE,
ui_segs, 1, &ui_nsegs, BUS_DMA_NOWAIT);
}
if (!not_ok) {
steps = 5;
not_ok = bus_dmamem_map(sc->sc_dmatag, ui_segs, ui_nsegs,
PDQ_OS_PAGESIZE,
(caddr_t *) &pdq->pdq_unsolicited_info.ui_events,
BUS_DMA_NOWAIT);
}
if (!not_ok) {
steps = 6;
not_ok = bus_dmamap_create(sc->sc_dmatag, ui_segs[0].ds_len, 1,
PDQ_OS_PAGESIZE, 0, BUS_DMA_NOWAIT,
&sc->sc_uimap);
}
if (!not_ok) {
steps = 7;
not_ok = bus_dmamap_load(sc->sc_dmatag, sc->sc_uimap,
pdq->pdq_unsolicited_info.ui_events,
PDQ_OS_PAGESIZE, NULL, BUS_DMA_NOWAIT);
}
if (!not_ok) {
steps = 8;
pdq->pdq_unsolicited_info.ui_pa_bufstart = sc->sc_uimap->dm_segs[0].ds_addr;
cb_segs[0] = db_segs[0];
cb_segs[0].ds_addr += offsetof(pdq_descriptor_block_t, pdqdb_consumer);
cb_segs[0].ds_len = sizeof(pdq_consumer_block_t);
not_ok = bus_dmamem_map(sc->sc_dmatag, cb_segs, 1,
sizeof(*pdq->pdq_cbp), (caddr_t *) &pdq->pdq_cbp,
BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
}
if (!not_ok) {
steps = 9;
not_ok = bus_dmamap_create(sc->sc_dmatag, cb_segs[0].ds_len, 1,
0x2000, 0, BUS_DMA_NOWAIT, &sc->sc_cbmap);
}
if (!not_ok) {
steps = 10;
not_ok = bus_dmamap_load(sc->sc_dmatag, sc->sc_cbmap,
(caddr_t) pdq->pdq_cbp, sizeof(*pdq->pdq_cbp),
NULL, BUS_DMA_NOWAIT);
}
if (!not_ok) {
pdq->pdq_pa_consumer_block = sc->sc_cbmap->dm_segs[0].ds_addr;
return not_ok;
}
switch (steps) {
case 11: {
bus_dmamap_unload(sc->sc_dmatag, sc->sc_cbmap);
/* FALL THROUGH */
}
case 10: {
bus_dmamap_destroy(sc->sc_dmatag, sc->sc_cbmap);
/* FALL THROUGH */
}
case 9: {
bus_dmamem_unmap(sc->sc_dmatag,
(caddr_t) pdq->pdq_cbp, sizeof(*pdq->pdq_cbp));
/* FALL THROUGH */
}
case 8: {
bus_dmamap_unload(sc->sc_dmatag, sc->sc_uimap);
/* FALL THROUGH */
}
case 7: {
bus_dmamap_destroy(sc->sc_dmatag, sc->sc_uimap);
/* FALL THROUGH */
}
case 6: {
bus_dmamem_unmap(sc->sc_dmatag,
(caddr_t) pdq->pdq_unsolicited_info.ui_events,
PDQ_OS_PAGESIZE);
/* FALL THROUGH */
}
case 5: {
bus_dmamem_free(sc->sc_dmatag, ui_segs, ui_nsegs);
/* FALL THROUGH */
}
case 4: {
bus_dmamap_unload(sc->sc_dmatag, sc->sc_dbmap);
/* FALL THROUGH */
}
case 3: {
bus_dmamap_destroy(sc->sc_dmatag, sc->sc_dbmap);
/* FALL THROUGH */
}
case 2: {
bus_dmamem_unmap(sc->sc_dmatag,
(caddr_t) pdq->pdq_dbp,
sizeof(*pdq->pdq_dbp));
/* FALL THROUGH */
}
case 1: {
bus_dmamem_free(sc->sc_dmatag, db_segs, db_nsegs);
/* FALL THROUGH */
}
}
return not_ok;
}
extern void
pdq_os_descriptor_block_sync(
pdq_os_ctx_t *sc,
size_t offset,
size_t length,
int ops)
{
bus_dmamap_sync(sc->sc_dmatag, sc->sc_dbmap, offset, length, ops);
}
extern void
pdq_os_consumer_block_sync(
pdq_os_ctx_t *sc,
int ops)
{
bus_dmamap_sync(sc->sc_dmatag, sc->sc_cbmap, 0, sizeof(pdq_consumer_block_t), ops);
}
extern void
pdq_os_unsolicited_event_sync(
pdq_os_ctx_t *sc,
size_t offset,
size_t length,
int ops)
{
bus_dmamap_sync(sc->sc_dmatag, sc->sc_uimap, offset, length, ops);
}
extern void
pdq_os_databuf_sync(
pdq_os_ctx_t *sc,
struct mbuf *m,
size_t offset,
size_t length,
int ops)
{
bus_dmamap_sync(sc->sc_dmatag, M_GETCTX(m, bus_dmamap_t), offset, length, ops);
}
extern void
pdq_os_databuf_free(
pdq_os_ctx_t *sc,
struct mbuf *m)
{
if (m->m_flags & (M_HASRXDMAMAP|M_HASTXDMAMAP)) {
bus_dmamap_t map = M_GETCTX(m, bus_dmamap_t);
bus_dmamap_unload(sc->sc_dmatag, map);
bus_dmamap_destroy(sc->sc_dmatag, map);
m->m_flags &= ~(M_HASRXDMAMAP|M_HASTXDMAMAP);
}
m_freem(m);
}
extern struct mbuf *
pdq_os_databuf_alloc(
pdq_os_ctx_t *sc)
{
struct mbuf *m;
bus_dmamap_t map;
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
printf("%s: can't alloc small buf\n", sc->sc_dev.dv_xname);
return NULL;
}
MCLGET(m, M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
printf("%s: can't alloc cluster\n", sc->sc_dev.dv_xname);
m_free(m);
return NULL;
}
m->m_pkthdr.len = m->m_len = PDQ_OS_DATABUF_SIZE;
if (bus_dmamap_create(sc->sc_dmatag, PDQ_OS_DATABUF_SIZE,
1, PDQ_OS_DATABUF_SIZE, 0, BUS_DMA_NOWAIT, &map)) {
printf("%s: can't create dmamap\n", sc->sc_dev.dv_xname);
m_free(m);
return NULL;
}
if (bus_dmamap_load_mbuf(sc->sc_dmatag, map, m,
BUS_DMA_READ|BUS_DMA_NOWAIT)) {
printf("%s: can't load dmamap\n", sc->sc_dev.dv_xname);
bus_dmamap_destroy(sc->sc_dmatag, map);
m_free(m);
return NULL;
}
m->m_flags |= M_HASRXDMAMAP;
M_SETCTX(m, map);
return m;
}
#endif

View file

@ -1,3 +1,5 @@
/* $NetBSD: pdqreg.h,v 1.14 2001/06/13 10:46:03 wiz Exp $ */
/*-
* Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
@ -8,7 +10,7 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@ -21,6 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Id: pdqreg.h,v 1.11 1997/03/21 21:16:04 thomas Exp
* $FreeBSD$
*
*/
@ -33,6 +36,11 @@
#ifndef _PDQREG_H
#define _PDQREG_H
#if !defined(KERNEL) && !defined(_KERNEL)
#include <stddef.h>
#elif !defined(offsetof)
#define offsetof(t, m) ((char *) (&((t *)0L)->m) - (char *) 0L)
#endif
#if defined(PDQTEST) && !defined(PDQ_NDEBUG)
#include <assert.h>
#define PDQ_ASSERT assert
@ -303,19 +311,36 @@ typedef struct {
typedef union {
pdq_uint32_t rxs_status;
pdq_uint32_t PDQ_BITFIELD12(rxs_len : 13,
rxs_rcc_ss : 2,
rxs_rcc_dd : 2,
rxs_rcc_reason : 3,
rxs_rcc_badcrc : 1,
rxs_rcc_badpdu : 1,
rxs_fsb__reserved : 2,
rxs_fsb_c : 1,
rxs_fsb_a : 1,
rxs_fsb_e : 1,
rxs_fsc : 3,
rxs__reserved : 2);
struct {
pdq_uint32_t PDQ_BITFIELD12(st_len : 13,
st_rcc_ss : 2,
st_rcc_dd : 2,
st_rcc_reason : 3,
st_rcc_badcrc : 1,
st_rcc_badpdu : 1,
st_fsb__reserved : 2,
st_fsb_c : 1,
st_fsb_a : 1,
st_fsb_e : 1,
st_fsc : 3,
st__reserved : 2);
} rxs_st;
} pdq_rxstatus_t;
#define rxs_len rxs_st.st_len
#define rxs_rcc_ss rxs_st.st_rcc_ss
#define rxs_rcc_dd rxs_st.st_rcc_dd
#define rxs_rcc_reason rxs_st.st_rcc_reason
#define rxs_rcc_badcrc rxs_st.st_rcc_badcrc
#define rxs_rcc_badpdu rxs_st.st_rcc_badpdu
#define rxs_fsb_c rxs_st.st_fsb_c
#define rxs_fsb_a rxs_st.st_fsb_a
#define rxs_fsb_e rxs_st.st_fsb_e
#define rxs_fsc rxs_st.st_fsc
#define PDQ_RXS_RCC_DD_NO_MATCH 0x00
#define PDQ_RXS_RCC_DD_PROMISC_MATCH 0x01
#define PDQ_RXS_RCC_DD_CAM_MATCH 0x02
#define PDQ_RXS_RCC_DD_MLA_MATCH 0x03
typedef struct {
pdq_uint32_t PDQ_BITFIELD5(txd_pa_hi : 16,
@ -337,27 +362,52 @@ typedef struct {
* The rest of the descriptor block is unused.
* As such we could use it for other things.
*/
pdq_consumer_block_t pdqdb_consumer; /* 64; 0x1380..0x13BF */
void *pdqdb_receive_buffers[256]; /* 1024/2048; 0x13C0..0x17BF 0x13C0..0x1BBF */
void *pdqdb_host_smt_buffers[64]; /* 256/ 512; 0x17C0..0x18BF 0x1BC0..0x1DBF */
pdq_uint32_t pdqdb__filler1[16]; /* 64; 0x1380..0x13BF */
pdq_consumer_block_t pdqdb_consumer; /* 64; 0x13C0..0x13FF */
/*
* The maximum command size is 512 so as long as thes
* command is at least that long all will be fine.
*/
#if defined(__alpha) || defined(__alpha__)
pdq_uint32_t pdqdb_command_pool[144];
#else
pdq_uint32_t pdqdb_command_pool[464];
#endif
pdq_uint32_t pdqdb__filler2[64]; /* 256; 0x1400..0x14FF */
pdq_uint8_t pdqdb_cmd_request_buf[1024]; /* 1024; 0x1500..0x18FF */
pdq_uint8_t pdqdb_cmd_response_buf[1024]; /* 1024; 0x1900..0x1CFF */
pdq_uint32_t pdqdb__filler3[128]; /* 512; 0x1D00..0x1EFF */
pdq_uint8_t pdqdb_tx_hdr[4]; /* 4; 0x1F00..0x1F03 */
pdq_uint32_t pdqdb__filler4[63]; /* 252; 0x1F04..0x1FFF */
} pdq_descriptor_block_t;
#define PDQ_SIZE_COMMAND_RESPONSE 512
typedef enum {
PDQC_START=0,
PDQC_FILTER_SET=1,
PDQC_FILTER_GET=2,
PDQC_CHARS_SET=3,
PDQC_STATUS_CHARS_GET=4,
PDQC_COUNTERS_GET=5,
PDQC_COUNTERS_SET=6,
PDQC_ADDR_FILTER_SET=7,
PDQC_ADDR_FILTER_GET=8,
PDQC_ERROR_LOG_CLEAR=9,
PDQC_ERROR_LOG_GET=10,
PDQC_FDDI_MIB_GET=11,
PDQC_DEC_EXT_MIB_GET=12,
PDQC_DEV_SPECIFIC_GET=13,
PDQC_SNMP_SET=14,
PDQC_SMT_MIB_GET=16,
PDQC_SMT_MIB_SET=17,
PDQC_BOGUS_CMD=18
} pdq_cmd_code_t;
typedef struct {
/*
* These value manage the available space in command/response
* buffer area.
*/
pdq_physaddr_t ci_pa_bufstart;
pdq_uint8_t *ci_bufstart;
pdq_physaddr_t ci_pa_request_bufstart;
pdq_uint8_t *ci_request_bufstart;
pdq_physaddr_t ci_pa_response_bufstart;
pdq_uint8_t *ci_response_bufstart;
/*
* Bitmask of commands to sent to the PDQ
*/
@ -370,6 +420,13 @@ typedef struct {
pdq_uint32_t ci_response_producer;
pdq_uint32_t ci_request_completion;
pdq_uint32_t ci_response_completion;
/*
*
*/
pdq_physaddr_t ci_pa_request_descriptors;
pdq_physaddr_t ci_pa_response_descriptors;
pdq_cmd_code_t ci_queued_commands[16];
} pdq_command_info_t;
#define PDQ_SIZE_UNSOLICITED_EVENT 512
@ -379,6 +436,7 @@ typedef struct _pdq_unsolicited_event_t pdq_unsolicited_event_t;
typedef struct {
pdq_physaddr_t ui_pa_bufstart;
pdq_physaddr_t ui_pa_descriptors;
pdq_unsolicited_event_t *ui_events;
pdq_uint32_t ui_free;
@ -409,6 +467,7 @@ typedef struct {
typedef struct {
void *rx_buffers;
pdq_physaddr_t rx_pa_descriptors;
pdq_uint32_t rx_target;
pdq_uint32_t rx_free;
@ -420,12 +479,14 @@ typedef struct {
pdq_databuf_queue_t tx_txq;
pdq_txdesc_t tx_hdrdesc;
pdq_uint8_t tx_descriptor_count[256];
pdq_physaddr_t tx_pa_descriptors;
pdq_uint32_t tx_free;
pdq_uint32_t tx_producer;
pdq_uint32_t tx_completion;
} pdq_tx_info_t;
typedef struct _pdq_os_ctx_t pdq_os_ctx_t;
struct _pdq_t {
pdq_csrs_t pdq_csrs;
pdq_pci_csrs_t pdq_pci_csrs;
@ -435,6 +496,7 @@ struct _pdq_t {
pdq_fwrev_t pdq_fwrev;
pdq_descriptor_block_t *pdq_dbp;
volatile pdq_consumer_block_t *pdq_cbp;
pdq_uint32_t pdq_intrmask;
pdq_uint32_t pdq_flags;
#define PDQ_PROMISC 0x0001
#define PDQ_ALLMULTI 0x0002
@ -442,36 +504,27 @@ struct _pdq_t {
#define PDQ_RUNNING 0x0008
#define PDQ_PRINTCHARS 0x0010
#define PDQ_TXOK 0x0020
#define PDQ_WANT_FDX 0x0040
#define PDQ_IS_FDX 0x0080
#define PDQ_IS_ONRING 0x0100
const char *pdq_os_name;
void *pdq_os_ctx;
pdq_os_ctx_t *pdq_os_ctx;
pdq_uint32_t pdq_unit;
pdq_command_info_t pdq_command_info;
pdq_unsolicited_info_t pdq_unsolicited_info;
pdq_tx_info_t pdq_tx_info;
pdq_rx_info_t pdq_rx_info;
pdq_rx_info_t pdq_host_smt_info;
pdq_uint8_t pdq_tx_hdr[3];
void *pdq_receive_buffers[256];
void *pdq_host_smt_buffers[64];
pdq_physaddr_t pdq_pa_consumer_block;
pdq_physaddr_t pdq_pa_descriptor_block;
};
typedef enum {
PDQC_START=0,
PDQC_FILTER_SET=1,
PDQC_FILTER_GET=2,
PDQC_CHARS_SET=3,
PDQC_STATUS_CHARS_GET=4,
PDQC_COUNTERS_GET=5,
PDQC_COUNTERS_SET=6,
PDQC_ADDR_FILTER_SET=7,
PDQC_ADDR_FILTER_GET=8,
PDQC_ERROR_LOG_CLEAR=9,
PDQC_ERROR_LOG_GET=10,
PDQC_FDDI_MIB_GET=11,
PDQC_DEC_EXT_MIB_GET=12,
PDQC_DEV_SPECIFIC_GET=13,
PDQC_SNMP_SET=14,
PDQC_SMT_MIB_GET=16,
PDQC_SMT_MIB_SET=17
} pdq_cmd_code_t;
#define PDQ_DB_BUSPA(pdq, m) \
((pdq)->pdq_pa_descriptor_block + \
((u_int8_t *) (m) - (u_int8_t *) (pdq)->pdq_dbp))
typedef enum {
PDQR_SUCCESS=0,
@ -556,6 +609,11 @@ typedef enum {
PDQI_FULL_DUPLEX_ENABLE=44
} pdq_item_code_t;
typedef enum {
PDQSNMP_EOL=0,
PDQSNMP_FULL_DUPLEX_ENABLE=0x2F11
} pdq_snmp_item_code_t;
enum _pdq_boolean_t {
PDQ_FALSE=0,
PDQ_TRUE=1
@ -956,6 +1014,16 @@ typedef struct {
#define PDQ_SIZE_RESPONSE_DEC_EXT_MIB_GET 0x50
typedef struct {
pdq_cmd_code_t snmp_set_op;
struct {
pdq_item_code_t item_code;
pdq_uint32_t item_value;
pdq_port_type_t item_port;
} snmp_set_items[7];
pdq_item_code_t snmp_set_eol_item_code;
} pdq_cmd_snmp_set_t;
typedef enum {
PDQ_CALLER_ID_NONE=0,
PDQ_CALLER_ID_SELFTEST=1,
@ -994,11 +1062,13 @@ typedef enum {
typedef enum {
PDQ_ENTITY_STATION=0,
PDQ_ENTITY_LINK=1,
PDQ_ENTITY_PHY_PORT=2
PDQ_ENTITY_PHY_PORT=2,
PDQ_ENTITY_MAX=3
} pdq_entity_t;
typedef enum {
PDQ_STATION_EVENT_TRACE_RECEIVED=1
PDQ_STATION_EVENT_TRACE_RECEIVED=1,
PDQ_STATION_EVENT_MAX=2
} pdq_station_event_t;
typedef enum {
@ -1022,7 +1092,8 @@ typedef enum {
PDQ_LINK_EVENT_RING_PURGE_ERROR=15,
PDQ_LINK_EVENT_FCI_STRIP_ERROR=16,
PDQ_LINK_EVENT_TRACE_INITIATED=17,
PDQ_LINK_EVENT_DIRECTED_BEACON_RECEIVED=18
PDQ_LINK_EVENT_DIRECTED_BEACON_RECEIVED=18,
PDQ_LINK_EVENT_MAX=19
} pdq_link_event_t;
typedef enum {
@ -1036,7 +1107,8 @@ typedef enum {
typedef enum {
PDQ_PHY_EVENT_LEM_ERROR_MONITOR_REJECT=0,
PDQ_PHY_EVENT_ELASTICITY_BUFFER_ERROR=1,
PDQ_PHY_EVENT_LINK_CONFIDENCE_TEST_REJECT=2
PDQ_PHY_EVENT_LINK_CONFIDENCE_TEST_REJECT=2,
PDQ_PHY_EVENT_MAX=3
} pdq_phy_event_t;
typedef enum {

View file

@ -1,3 +1,5 @@
/* $NetBSD: pdqvar.h,v 1.27 2000/05/03 19:17:54 thorpej Exp $ */
/*-
* Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com>
* All rights reserved.
@ -21,6 +23,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Id: pdqvar.h,v 1.21 1997/03/21 21:16:04 thomas Exp
* $FreeBSD$
*
*/
@ -62,13 +65,10 @@ enum _pdq_type_t {
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#ifndef M_MCAST
#include <sys/mbuf.h>
#endif /* M_CAST */
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
@ -87,31 +87,31 @@ enum _pdq_type_t {
#endif
#define PDQ_OS_USEC_DELAY(n) DELAY(n)
#define PDQ_OS_MEMZERO(p, n) bzero((caddr_t)(p), (n))
#if defined(__NetBSD__) && defined(__alpha__)
#define PDQ_OS_VA_TO_PA(pdq, p) (vtophys((vm_offset_t)p) | (pdq->pdq_type == PDQ_DEFTA ? 0 : 0x40000000))
#elif defined(__FreeBSD__) && defined(__alpha__)
#define PDQ_OS_VA_TO_PA(pdq, p) (vtophys((vm_offset_t)p) | (pdq->pdq_type == PDQ_DEFTA ? 0 : alpha_XXX_dmamap_or))
#else
#define PDQ_OS_VA_TO_PA(pdq, p) vtophys(p)
#if defined(__NetBSD__) && !defined(PDQ_NO_BUS_DMA)
#define PDQ_BUS_DMA
#endif
#if !defined(PDQ_BUS_DMA)
#define PDQ_OS_VA_TO_BUSPA(pdq, p) vtophys(p)
#endif
#define PDQ_OS_MEMALLOC(n) malloc(n, M_DEVBUF, M_NOWAIT)
#define PDQ_OS_MEMFREE(p, n) free((void *) p, M_DEVBUF)
#ifdef __FreeBSD__
#define PDQ_OS_MEMALLOC_CONTIG(n) vm_page_alloc_contig(n, 0, 0xffffffff, PAGE_SIZE)
#define PDQ_OS_MEMFREE_CONTIG(p, n) kmem_free(kernel_map, (vm_offset_t) p, n)
#define PDQ_OS_MEMFREE_CONTIG(p, n) kmem_free(kernel_map, (vaddr_t) p, n)
#else
#define PDQ_OS_MEMALLOC_CONTIG(n) kmem_alloc(kernel_map, round_page(n))
#define PDQ_OS_MEMFREE_CONTIG(p, n) kmem_free(kernel_map, (vm_offset_t) p, n)
#if !defined(PDQ_BUS_DMA)
#define PDQ_OS_MEMALLOC_CONTIG(n) uvm_km_alloc(kernel_map, round_page(n))
#define PDQ_OS_MEMFREE_CONTIG(p, n) uvm_km_free(kernel_map, (vaddr_t) p, n)
#endif
#endif /* __FreeBSD__ */
#if defined(__FreeBSD__)
#include <vm/pmap.h>
#include <vm/vm_extern.h>
#include <machine/bus.h>
#include <machine/cpufunc.h>
#include <machine/clock.h>
typedef void ifnet_ret_t;
typedef u_long ioctl_cmd_t;
#define ifnet_ret_t void
typedef int ioctl_cmd_t;
typedef enum { PDQ_BUS_EISA, PDQ_BUS_PCI } pdq_bus_t;
typedef u_int16_t pdq_bus_ioport_t;
typedef volatile pdq_uint32_t *pdq_bus_memaddr_t;
@ -121,10 +121,14 @@ typedef pdq_bus_memaddr_t pdq_bus_memoffset_t;
#define PDQ_BPFATTACH(sc, t, s) bpfattach(&(sc)->sc_if, t, s)
#endif
#define pdq_os_update_status(a, b) ((void) 0)
#elif defined(__bsdi__)
#if !defined(PDQ_HWSUPPORT) && (_BSDI_VERSION >= 199701)
#include <net/if_media.h>
#endif
#include <machine/inline.h>
typedef int ifnet_ret_t;
#define ifnet_ret_t int
typedef int ioctl_cmd_t;
typedef enum { PDQ_BUS_EISA, PDQ_BUS_PCI } pdq_bus_t;
typedef u_int16_t pdq_bus_ioport_t;
@ -133,36 +137,100 @@ typedef pdq_bus_memaddr_t pdq_bus_memoffset_t;
#elif defined(__NetBSD__)
#if !defined(PDQ_HWSUPPORT)
#include <net/if_media.h>
#endif
#include <machine/bus.h>
#include <machine/intr.h>
#define PDQ_OS_HDR_OFFSET (PDQ_RX_FC_OFFSET-3)
#define PDQ_OS_PTR_FMT "%p"
typedef void ifnet_ret_t;
#define PDQ_OS_CSR_FMT "0x%lx"
#define ifnet_ret_t void
typedef u_long ioctl_cmd_t;
typedef bus_chipset_tag_t pdq_bus_t;
typedef bus_io_handle_t pdq_bus_ioport_t;
#if defined(PDQ_IOMAPPED)
typedef bus_io_handle_t pdq_bus_memaddr_t;
#else
typedef bus_mem_handle_t pdq_bus_memaddr_t;
#endif
typedef pdq_uint32_t pdq_bus_memoffset_t;
typedef bus_space_tag_t pdq_bus_t;
typedef bus_space_handle_t pdq_bus_ioport_t;
typedef bus_space_handle_t pdq_bus_memaddr_t;
typedef bus_addr_t pdq_bus_memoffset_t;
#define PDQ_OS_SPL_RAISE() splnet()
#define PDQ_OS_IOMEM
#define PDQ_OS_IORD_32(t, base, offset) bus_io_read_4 (t, base, offset)
#define PDQ_OS_IOWR_32(t, base, offset, data) bus_io_write_4 (t, base, offset, data)
#define PDQ_OS_IORD_8(t, base, offset) bus_io_read_1 (t, base, offset)
#define PDQ_OS_IOWR_8(t, base, offset, data) bus_io_write_1 (t, base, offset, data)
#define PDQ_OS_MEMRD_32(t, base, offset) bus_mem_read_4(t, base, offset)
#define PDQ_OS_MEMWR_32(t, base, offset, data) bus_mem_write_4(t, base, offset, data)
#define PDQ_OS_IORD_32(t, base, offset) bus_space_read_4 (t, base, offset)
#define PDQ_OS_IOWR_32(t, base, offset, data) bus_space_write_4 (t, base, offset, data)
#define PDQ_OS_IORD_8(t, base, offset) bus_space_read_1 (t, base, offset)
#define PDQ_OS_IOWR_8(t, base, offset, data) bus_space_write_1 (t, base, offset, data)
#define PDQ_CSR_OFFSET(base, offset) (0 + (offset)*sizeof(pdq_uint32_t))
#if defined(PDQ_IOMAPPED)
#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_IOWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data)
#define PDQ_CSR_READ(csr, name) PDQ_OS_IORD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name)
#else
#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_MEMWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data)
#define PDQ_CSR_READ(csr, name) PDQ_OS_MEMRD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name)
#ifdef PDQ_BUS_DMA
#define PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, event) \
pdq_os_unsolicited_event_sync((pdq)->pdq_os_ctx, \
(u_int8_t *) (event) - \
(u_int8_t *) (pdq)->pdq_unsolicited_info.ui_events, \
sizeof(*event), BUS_DMASYNC_PREREAD)
#define PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq, event) \
pdq_os_unsolicited_event_sync((pdq)->pdq_os_ctx, \
(u_int8_t *) (event) - \
(u_int8_t *) (pdq)->pdq_unsolicited_info.ui_events, \
sizeof(*event), BUS_DMASYNC_POSTREAD)
#define PDQ_OS_DESCBLOCK_SYNC(pdq, what, length, why) \
pdq_os_descriptor_block_sync((pdq)->pdq_os_ctx, \
(u_int8_t *) (what) - (u_int8_t *) (pdq)->pdq_dbp, \
(length), (why))
#define PDQ_OS_CONSUMER_PRESYNC(pdq) \
pdq_os_consumer_block_sync((pdq)->pdq_os_ctx, \
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)
#define PDQ_OS_CONSUMER_POSTSYNC(pdq) \
pdq_os_consumer_block_sync((pdq)->pdq_os_ctx, \
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)
#define PDQ_OS_DESC_PRESYNC(pdq, d, s) \
PDQ_OS_DESCBLOCK_SYNC((pdq), (d), (s), BUS_DMASYNC_PREWRITE)
#define PDQ_OS_DESC_POSTSYNC(pdq, d, s) \
PDQ_OS_DESCBLOCK_SYNC((pdq), (d), (s), BUS_DMASYNC_POSTWRITE)
#define PDQ_OS_CMDRQST_PRESYNC(pdq, s) \
PDQ_OS_DESCBLOCK_SYNC((pdq), \
(pdq)->pdq_command_info.ci_request_bufstart, \
(s), BUS_DMASYNC_PREWRITE)
#define PDQ_OS_CMDRSP_PRESYNC(pdq, s) \
PDQ_OS_DESCBLOCK_SYNC((pdq), \
(pdq)->pdq_command_info.ci_response_bufstart, \
(s), BUS_DMASYNC_PREREAD)
#define PDQ_OS_CMDRQST_POSTSYNC(pdq, s) \
PDQ_OS_DESCBLOCK_SYNC((pdq), \
(pdq)->pdq_command_info.ci_request_bufstart, \
(s), BUS_DMASYNC_POSTWRITE)
#define PDQ_OS_CMDRSP_POSTSYNC(pdq, s) \
PDQ_OS_DESCBLOCK_SYNC((pdq), \
(pdq)->pdq_command_info.ci_response_bufstart, \
(s), BUS_DMASYNC_POSTREAD)
#define PDQ_OS_RXPDU_PRESYNC(pdq, b, o, l) \
pdq_os_databuf_sync((pdq)->pdq_os_ctx, (b), (o), (l), \
BUS_DMASYNC_PREREAD)
#define PDQ_OS_RXPDU_POSTSYNC(pdq, b, o, l) \
pdq_os_databuf_sync((pdq)->pdq_os_ctx, (b), (o), (l), \
BUS_DMASYNC_POSTREAD)
#define PDQ_OS_DATABUF_ALLOC(pdq, b) ((void)((b) = pdq_os_databuf_alloc((pdq)->pdq_os_ctx)))
#define PDQ_OS_DATABUF_FREE(pdq, b) pdq_os_databuf_free((pdq)->pdq_os_ctx, (b))
#define PDQ_OS_DATABUF_BUSPA(pdq, b) (M_GETCTX((b), bus_dmamap_t)->dm_segs[0].ds_addr + 0)
struct _pdq_os_ctx_t;
extern void pdq_os_descriptor_block_sync(struct _pdq_os_ctx_t *osctx, size_t offset,
size_t length, int ops);
extern void pdq_os_consumer_block_sync(struct _pdq_os_ctx_t *osctx, int ops);
extern void pdq_os_unsolicited_event_sync(struct _pdq_os_ctx_t *osctx, size_t offset,
size_t length, int ops);
extern struct mbuf *pdq_os_databuf_alloc(struct _pdq_os_ctx_t *osctx);
extern void pdq_os_databuf_sync(struct _pdq_os_ctx_t *osctx, struct mbuf *b,
size_t offset, size_t length, int ops);
extern void pdq_os_databuf_free(struct _pdq_os_ctx_t *osctx, struct mbuf *m);
#define M_HASTXDMAMAP M_LINK1
#define M_HASRXDMAMAP M_LINK2
#endif
#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_IOWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data)
#define PDQ_CSR_READ(csr, name) PDQ_OS_IORD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name)
#define PDQ_OS_IFP_TO_SOFTC(ifp) ((pdq_softc_t *) (ifp)->if_softc)
#define PDQ_ARP_IFINIT(sc, ifa) arp_ifinit(&(sc)->sc_if, (ifa))
#define PDQ_FDDICOM(sc) (&(sc)->sc_ec)
#define PDQ_LANADDR(sc) LLADDR((sc)->sc_if.if_sadl)
#define PDQ_LANADDR_SIZE(sc) ((sc)->sc_if.if_sadl->sdl_alen)
#endif
#if !defined(PDQ_BPF_MTAP)
@ -173,17 +241,42 @@ typedef pdq_uint32_t pdq_bus_memoffset_t;
#define PDQ_BPFATTACH(sc, t, s) bpfattach(&(sc)->sc_bpf, &(sc)->sc_if, t, s)
#endif
#if !defined(PDQ_OS_SPL_RAISE)
#define PDQ_OS_SPL_RAISE() splimp()
#endif
#if !defined(PDQ_OS_SPL_LOWER)
#define PDQ_OS_SPL_LOWER(s) splx(s)
#endif
#if !defined(PDQ_FDDICOM)
#define PDQ_FDDICOM(sc) (&(sc)->sc_ac)
#endif
#if !defined(PDQ_ARP_IFINIT)
#define PDQ_ARP_IFINIT(sc, ifa) arp_ifinit(&(sc)->sc_ac, (ifa))
#endif
#if !defined(PDQ_OS_PTR_FMT)
#define PDQ_OS_PTR_FMT "0x%x"
#endif
#if !defined(PDQ_OS_CSR_FMT)
#define PDQ_OS_CSR_FMT "0x%x"
#endif
#if !defined(PDQ_LANADDR)
#define PDQ_LANADDR(sc) ((sc)->sc_ac.ac_enaddr)
#define PDQ_LANADDR_SIZE(sc) (sizeof((sc)->sc_ac.ac_enaddr))
#endif
#if !defined(PDQ_OS_IOMEM)
#define PDQ_OS_IORD_32(t, base, offset) inl((base) + (offset))
#define PDQ_OS_IOWR_32(t, base, offset, data) outl((base) + (offset), data)
#define PDQ_OS_IORD_8(t, base, offset) inb((base) + (offset))
#define PDQ_OS_IOWR_8(t, base, offset, data) outb((base) + (offset), data)
#define PDQ_OS_MEMRD_32(t, base, offset) readl((base) + (offset))
#define PDQ_OS_MEMWR_32(t, base, offset, data) writel((base) + (offset), data)
#define PDQ_OS_MEMRD_32(t, base, offset) (0 + *((base) + (offset)))
#define PDQ_OS_MEMWR_32(t, base, offset, data) do *((base) + (offset)) = (data); while (0)
#endif
#ifndef PDQ_CSR_OFFSET
#define PDQ_CSR_OFFSET(base, offset) (0 + (base) + (offset))
@ -194,38 +287,60 @@ typedef pdq_uint32_t pdq_bus_memoffset_t;
#define PDQ_CSR_READ(csr, name) PDQ_OS_MEMRD_32((csr)->csr_bus, (csr)->name, 0)
#endif
#ifndef PDQ_OS_IFP_TO_SOFTC
#define PDQ_OS_IFP_TO_SOFTC(ifp) ((pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if)))
#endif
#if !defined(PDQ_HWSUPPORT)
typedef struct {
typedef struct _pdq_os_ctx_t {
#if defined(__bsdi__)
struct device sc_dev; /* base device */
struct isadev sc_id; /* ISA device */
struct intrhand sc_ih; /* interrupt vectoring */
struct atshutdown sc_ats; /* shutdown routine */
struct arpcom sc_ac;
#define sc_if sc_ac.ac_if
#elif defined(__NetBSD__)
struct device sc_dev; /* base device */
void *sc_ih; /* interrupt vectoring */
void *sc_ats; /* shutdown hook */
struct ethercom sc_ec;
bus_dma_tag_t sc_dmatag;
#define sc_if sc_ec.ec_if
#elif defined(__FreeBSD__)
struct kern_devconf *sc_kdc; /* freebsd cruft */
#endif
struct arpcom sc_ac;
#define sc_if sc_ac.ac_if
#endif
#if defined(IFM_FDDI)
struct ifmedia sc_ifmedia;
#endif
pdq_t *sc_pdq;
#if defined(__alpha__) || defined(__i386__)
pdq_bus_ioport_t sc_iobase;
#endif
#ifdef PDQ_IOMAPPED
#if defined(PDQ_IOMAPPED) && !defined(__NetBSD__)
#define sc_membase sc_iobase
#else
pdq_bus_memaddr_t sc_membase;
#endif
pdq_bus_t sc_bc;
pdq_bus_t sc_iotag;
pdq_bus_t sc_csrtag;
#if !defined(__bsdi__) || _BSDI_VERSION >= 199401
#define sc_bpf sc_if.if_bpf
#else
caddr_t sc_bpf;
#endif
#if defined(PDQ_BUS_DMA)
#if !defined(__NetBSD__)
bus_dma_tag_t sc_dmatag;
#endif
bus_dmamap_t sc_dbmap; /* DMA map for descriptor block */
bus_dmamap_t sc_uimap; /* DMA map for unsolicited events */
bus_dmamap_t sc_cbmap; /* DMA map for consumer block */
#endif
} pdq_softc_t;
@ -251,7 +366,7 @@ extern void pdq_ifattach(pdq_softc_t *sc, ifnet_ret_t (*ifwatchdog)(int unit));
#define PDQ_OS_PAGESIZE PAGESIZE
#define PDQ_OS_USEC_DELAY(n) drv_usecwait(n)
#define PDQ_OS_MEMZERO(p, n) bzero((caddr_t)(p), (n))
#define PDQ_OS_VA_TO_PA(pdq, p) vtop((caddr_t)p, NULL)
#define PDQ_OS_VA_TO_BUSPA(pdq, p) vtop((caddr_t)p, NULL)
#define PDQ_OS_MEMALLOC(n) kmem_zalloc(n, KM_NOSLEEP)
#define PDQ_OS_MEMFREE(p, n) kmem_free((caddr_t) p, n)
#define PDQ_OS_MEMALLOC_CONTIG(n) kmem_zalloc_physreq(n, decfddiphysreq_db, KM_NOSLEEP)
@ -260,7 +375,7 @@ extern void pdq_ifattach(pdq_softc_t *sc, ifnet_ret_t (*ifwatchdog)(int unit));
extern physreq_t *decfddiphysreq_db;
extern physreq_t *decfddiphysreq_mblk;
#define PDQ_OS_DATABUF_ALLOC(b) ((void) (((b) = allocb_physreq(PDQ_OS_DATABUF_SIZE, BPRI_MED, decfddiphysreq_mblk)) && ((b)->b_wptr = (b)->b_rptr + PDQ_OS_DATABUF_SIZE)))
#define PDQ_OS_DATABUF_ALLOC(pdq, b) ((void) (((b) = allocb_physreq(PDQ_OS_DATABUF_SIZE, BPRI_MED, decfddiphysreq_mblk)) && ((b)->b_wptr = (b)->b_rptr + PDQ_OS_DATABUF_SIZE)))
#define PDQ_OS_IORD_8(port) inb(port)
#define PDQ_OS_IOWR_8(port, data) outb(port, data)
@ -269,7 +384,9 @@ extern physreq_t *decfddiphysreq_mblk;
#ifdef PDQ_USE_MBUFS
#define PDQ_OS_DATABUF_SIZE (MCLBYTES)
#define PDQ_OS_DATABUF_FREE(b) (m_freem(b))
#ifndef PDQ_OS_DATABUF_FREE
#define PDQ_OS_DATABUF_FREE(pdq, b) (m_freem(b))
#endif
#define PDQ_OS_DATABUF_NEXT(b) ((b)->m_next)
#define PDQ_OS_DATABUF_NEXT_SET(b, b1) ((b)->m_next = (b1))
#define PDQ_OS_DATABUF_NEXTPKT(b) ((b)->m_nextpkt)
@ -281,7 +398,8 @@ extern physreq_t *decfddiphysreq_mblk;
#define PDQ_OS_DATABUF_ADJ(b, n) ((b)->m_data += (n), (b)->m_len -= (n))
typedef struct mbuf PDQ_OS_DATABUF_T;
#define PDQ_OS_DATABUF_ALLOC(b) do { \
#ifndef PDQ_OS_DATABUF_ALLOC
#define PDQ_OS_DATABUF_ALLOC(pdq, b) do { \
PDQ_OS_DATABUF_T *x_m0; \
MGETHDR(x_m0, M_DONTWAIT, MT_DATA); \
if (x_m0 != NULL) { \
@ -297,12 +415,13 @@ typedef struct mbuf PDQ_OS_DATABUF_T;
(b) = NULL; \
} \
} while (0)
#endif
#define PDQ_OS_DATABUF_RESET(b) ((b)->m_data = (b)->m_ext.ext_buf, (b)->m_len = MCLBYTES)
#endif /* PDQ_USE_MBUFS */
#ifdef PDQ_USE_STREAMS
#define PDQ_OS_DATABUF_SIZE (2048)
#define PDQ_OS_DATABUF_FREE(b) (freemsg(b))
#define PDQ_OS_DATABUF_FREE(pdq, b) (freemsg(b))
#define PDQ_OS_DATABUF_NEXT(b) ((b)->b_cont)
#define PDQ_OS_DATABUF_NEXT_SET(b, b1) ((b)->b_cont = (b1))
#define PDQ_OS_DATABUF_NEXTPKT(b) ((b)->b_next)
@ -315,7 +434,7 @@ typedef struct mbuf PDQ_OS_DATABUF_T;
typedef mblk_t PDQ_OS_DATABUF_T;
#ifndef PDQ_OS_DATABUF_ALLOC
#define PDQ_OS_DATABUF_ALLOC(b) ((void) (((b) = allocb(PDQ_OS_DATABUF_SIZE, BPRI_MED)) && ((b)->b_wptr = (b)->b_rptr + PDQ_OS_DATABUF_SIZE)))
#define PDQ_OS_DATABUF_ALLOC(pdq, b) ((void) (((b) = allocb(PDQ_OS_DATABUF_SIZE, BPRI_MED)) && ((b)->b_wptr = (b)->b_rptr + PDQ_OS_DATABUF_SIZE)))
#endif /* PDQ_OS_DATABUF_ALLOC */
#endif /* PDQ_USE_STREAMS */
@ -338,11 +457,39 @@ typedef mblk_t PDQ_OS_DATABUF_T;
} \
} while (0)
#if !defined(PDQ_OS_CONSUMER_PRESYNC)
#define PDQ_OS_CONSUMER_PRESYNC(pdq) do { } while(0)
#define PDQ_OS_CONSUMER_POSTSYNC(pdq) do { } while(0)
#define PDQ_OS_DESC_PRESYNC(pdq, d, s) do { } while(0)
#define PDQ_OS_DESC_POSTSYNC(pdq, d, s) do { } while(0)
#define PDQ_OS_CMDRQST_PRESYNC(pdq, s) do { } while(0)
#define PDQ_OS_CMDRQST_POSTSYNC(pdq, s) do { } while(0)
#define PDQ_OS_CMDRSP_PRESYNC(pdq, s) do { } while(0)
#define PDQ_OS_CMDRSP_POSTSYNC(pdq, s) do { } while(0)
#define PDQ_OS_RXPDU_PRESYNC(pdq, b, o, l) do { } while(0)
#define PDQ_OS_RXPDU_POSTSYNC(pdq, b, o, l) do { } while(0)
#define PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, e) do { } while(0)
#define PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq, e) do { } while(0)
#endif
#ifndef PDQ_OS_DATABUF_BUSPA
#define PDQ_OS_DATABUF_BUSPA(pdq, b) PDQ_OS_VA_TO_BUSPA(pdq, PDQ_OS_DATABUF_PTR(b))
#endif
#ifndef PDQ_OS_HDR_OFFSET
#define PDQ_OS_HDR_OFFSET PDQ_RX_FC_OFFSET
#endif
extern void pdq_os_addr_fill(pdq_t *pdq, pdq_lanaddr_t *addrs, size_t numaddrs);
extern void pdq_os_receive_pdu(pdq_t *, PDQ_OS_DATABUF_T *pdu, size_t pdulen);
extern void pdq_os_receive_pdu(pdq_t *, PDQ_OS_DATABUF_T *pdu, size_t pdulen, int drop);
extern void pdq_os_restart_transmitter(pdq_t *pdq);
extern void pdq_os_transmit_done(pdq_t *pdq, PDQ_OS_DATABUF_T *pdu);
#if !defined(pdq_os_update_status)
extern void pdq_os_update_status(pdq_t *pdq, const void *rsp);
#endif
#if !defined(PDQ_OS_MEMALLOC_CONTIG)
extern int pdq_os_memalloc_contig(pdq_t *pdq);
#endif
extern pdq_boolean_t pdq_queue_transmit_data(pdq_t *pdq, PDQ_OS_DATABUF_T *pdu);
extern void pdq_flush_transmitter(pdq_t *pdq);

View file

@ -97,11 +97,9 @@ struct fddi_header {
#define FDDI_BPF_UNSUPPORTED 0
#define FDDI_BPF_SUPPORTED 1
void fddi_ifattach(struct ifnet *);
void fddi_ifattach(struct ifnet *, int);
void fddi_ifdetach(struct ifnet *, int);
void fddi_input(struct ifnet *, struct fddi_header *, struct mbuf *);
int fddi_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
int fddi_ioctl(struct ifnet *, int, caddr_t);
#endif /* _KERNEL */

View file

@ -94,8 +94,11 @@ extern u_char aarp_org_code[ 3 ];
static u_char fddibroadcastaddr[FDDI_ADDR_LEN] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static int fddi_resolvemulti(struct ifnet *, struct sockaddr **,
static int fddi_resolvemulti(struct ifnet *, struct sockaddr **,
struct sockaddr *);
static int fddi_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
#define IFP2AC(IFP) ((struct arpcom *)IFP)
#define senderr(e) { error = (e); goto bad; }
@ -107,7 +110,7 @@ static int fddi_resolvemulti(struct ifnet *, struct sockaddr **,
* packet leaves a multiple of 512 bytes of data in remainder.
* Assumes that ifp is actually pointer to arpcom structure.
*/
int
static int
fddi_output(ifp, m, dst, rt0)
struct ifnet *ifp;
struct mbuf *m;
@ -519,8 +522,9 @@ dropanyway:
* Perform common duties while attaching to interface list
*/
void
fddi_ifattach(ifp)
fddi_ifattach(ifp, bpf)
struct ifnet *ifp;
int bpf;
{
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
@ -551,6 +555,9 @@ fddi_ifattach(ifp)
sdl->sdl_alen = ifp->if_addrlen;
bcopy(IFP2AC(ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
if (bpf)
bpfattach(ifp, DLT_FDDI, FDDI_HDR_LEN);
return;
}