diff options
Diffstat (limited to 'sys/dev/patm/if_patmvar.h')
-rw-r--r-- | sys/dev/patm/if_patmvar.h | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/sys/dev/patm/if_patmvar.h b/sys/dev/patm/if_patmvar.h new file mode 100644 index 0000000..c146990 --- /dev/null +++ b/sys/dev/patm/if_patmvar.h @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * 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. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * Author: Hartmut Brandt <harti@freebsd.org> + * + * $FreeBSD$ + * + * Driver for IDT77252 (ABR) based cards like ProSum's. + */ + +/* legal values are 0, 1, 2 and 8 */ +#define PATM_VPI_BITS 2 +#define PATM_CFG_VPI IDT_CFG_VP2 + +/* receive status queue size */ +#define PATM_RSQ_SIZE 512 +#define PATM_CFQ_RSQ_SIZE IDT_CFG_RXQ512 + +/* alignment for SQ memory */ +#define PATM_SQ_ALIGNMENT 8192 + +#define PATM_PROATM_NAME_OFFSET 060 +#define PATM_PROATM_NAME "PROATM" +#define PATM_PROATM_MAC_OFFSET 044 +#define PATM_IDT_MAC_OFFSET 0154 + +/* maximum number of packets on UBR queue */ +#define PATM_DLFT_MAXQ 1000 + +/* maximum number of packets on other queues. This should depend on the + * traffic contract. */ +#define PATM_TX_IFQLEN 100 + +/* + * Maximum number of DMA maps we allocate. This is the minimum that can be + * set larger via a sysctl. + * Starting number of DMA maps. + * Step for growing. + */ +#define PATM_CFG_TXMAPS_MAX 1024 +#define PATM_CFG_TXMAPS_INIT 128 +#define PATM_CFG_TXMAPS_STEP 128 + +/* percents of TST slots to keep for non-CBR traffic */ +#define PATM_TST_RESERVE 2 + +/* + * Structure to hold TX DMA maps + */ +struct patm_txmap { + SLIST_ENTRY(patm_txmap) link; + bus_dmamap_t map; +}; + +/* + * Receive buffers. + * + * We manage our own external mbufs for small receive buffers for two reasons: + * the card may consume a rather large number of buffers. Mapping each buffer + * would consume a lot of iospace on sparc64. Also the card allows us to set + * a 32-bit handle for identification of the buffers. On a 64-bit system this + * requires us to use a mapping between buffers and handles. + * + * For large buffers we use mbuf clusters directly. We track these by using + * an array of pointers (lbufs) to special structs and a free list of these + * structs. + * + * For AAL0 cell we use FBQ2 and make the 1 cell long. + */ +/* + * Define the small buffer chunk so that we have at least 16 byte free + * at the end of the chunk and that there is an integral number of chunks + * in a page. + */ +#define SMBUF_PAGE_SIZE 16384 /* 16k pages */ +#define SMBUF_MAX_PAGES 64 /* maximum number of pages */ +#define SMBUF_CHUNK_SIZE 256 /* 256 bytes per chunk */ +#define SMBUF_CELLS 5 +#define SMBUF_SIZE (SMBUF_CELLS * 48) +#define SMBUF_THRESHOLD 9 /* 9/16 of queue size */ +#define SMBUF_NI_THRESH 3 +#define SMBUF_CI_THRESH 1 + +#define VMBUF_PAGE_SIZE 16384 /* 16k pages */ +#define VMBUF_MAX_PAGES 16 /* maximum number of pages */ +#define VMBUF_CHUNK_SIZE 64 /* 64 bytes per chunk */ +#define VMBUF_CELLS 1 +#define VMBUF_SIZE (VMBUF_CELLS * 48) +#define VMBUF_THRESHOLD 15 /* 15/16 of size */ + +#define SMBUF_OFFSET (SMBUF_CHUNK_SIZE - 8 - SMBUF_SIZE) +#define VMBUF_OFFSET 0 + +#define MBUF_SHANDLE 0x00000000 +#define MBUF_LHANDLE 0x80000000 +#define MBUF_VHANDLE 0x40000000 +#define MBUF_HMASK 0x3fffffff + +/* + * Large buffers + * + * The problem with these is the maximum count. When the card assembles + * a AAL5 pdu it moves a buffer from the FBQ to the VC. This frees space + * in the FBQ, put the buffer may pend on the card for an unlimited amount + * of time (we don't idle connections). This means that the upper limit + * on buffers on the card may be (no-of-open-vcs + FBQ_SIZE). Because + * this is far too much, make this a tuneable. We could also make + * this dynamic by allocating pages of several lbufs at once during run time. + */ +#define LMBUF_MAX (IDT_FBQ_SIZE * 2) +#define LMBUF_CELLS (MCLBYTES / 48) /* 42 cells = 2048 byte */ +#define LMBUF_SIZE (LMBUF_CELLS * 48) +#define LMBUF_THRESHOLD 9 /* 9/16 of queue size */ +#define LMBUF_OFFSET (MCLBYTES - LMBUF_SIZE) +#define LMBUF_NI_THRESH 3 +#define LMBUF_CI_THRESH 1 + +#define LMBUF_HANDLE 0x80000000 + +struct lmbuf { + SLIST_ENTRY(lmbuf) link; /* free list link */ + bus_dmamap_t map; /* DMA map */ + u_int handle; /* this is the handle index */ + struct mbuf *m; /* the current mbuf */ + bus_addr_t phy; /* phy addr */ +}; + +#define PATM_CID(SC, VPI, VCI) \ + (((VPI) << (SC)->ifatm.mib.vci_bits) | (VCI)) + +/* + * Internal driver statistics + */ +struct patm_stats { + uint32_t raw_cells; + uint32_t raw_no_vcc; + uint32_t raw_no_buf; + uint32_t tx_qfull; + uint32_t tx_out_of_tbds; + uint32_t tx_out_of_maps; + uint32_t tx_load_err; +}; + +/* + * These are allocated as DMA able memory + */ +struct patm_scd { + struct idt_tbd scq[IDT_SCQ_SIZE]; + LIST_ENTRY(patm_scd) link; /* all active SCDs */ + uint32_t sram; /* SRAM address */ + bus_addr_t phy; /* physical address */ + bus_dmamap_t map; /* DMA map */ + u_int tail; /* next free entry for host */ + int space; /* number of free entries (minus one) */ + u_int slots; /* CBR slots allocated */ + uint8_t tag; /* next tag for TSI */ + uint8_t last_tag; /* last tag checked in interrupt */ + uint8_t num_on_card; /* number of PDUs on tx queue */ + uint8_t lacr; /* LogACR value */ + uint8_t init_er; /* LogER value */ + struct ifqueue q; /* queue of packets */ + struct mbuf *on_card[IDT_TSQE_TAG_SPACE]; +}; + +/* + * Per-VCC data + */ +struct patm_vcc { + struct atmio_vcc vcc; /* caller's parameters */ + void *rxhand; /* NATM handle */ + u_int vflags; /* open and other flags */ + uint32_t ipackets; /* packets received */ + uint32_t opackets; /* packets sent */ + uint64_t ibytes; /* bytes received */ + uint64_t obytes; /* bytes sent */ + struct mbuf *chain; /* currently received chain */ + struct mbuf *last; /* end of chain */ + u_int cid; /* index */ + u_int cps; /* last ABR cps */ + struct patm_scd *scd; +}; +#define PATM_VCC_TX_OPEN 0x0001 +#define PATM_VCC_RX_OPEN 0x0002 +#define PATM_VCC_TX_CLOSING 0x0004 +#define PATM_VCC_RX_CLOSING 0x0008 +#define PATM_VCC_OPEN 0x000f /* all the above */ +#define PATM_VCC_ASYNC 0x0010 + +#define PATM_RAW_CELL 0x0000 /* 53 byte cells */ +#define PATM_RAW_NOHEC 0x0100 /* 52 byte cells */ +#define PATM_RAW_CS 0x0200 /* 64 byte cell stream */ +#define PATM_RAW_FORMAT 0x0300 /* format mask */ + +/* + * Per adapter data + */ +struct patm_softc { + struct ifatm ifatm; /* common ATM stuff */ + struct mtx mtx; /* lock */ + struct ifmedia media; /* media */ + device_t dev; /* device */ + struct resource * memres; /* memory resource */ + bus_space_handle_t memh; /* handle */ + bus_space_tag_t memt; /* ... and tag */ + int irqid; /* resource id */ + struct resource * irqres; /* resource */ + void * ih; /* interrupt handle */ + struct utopia utopia; /* phy state */ + const struct idt_mmap *mmap; /* SRAM memory map */ + u_int flags; /* see below */ + u_int revision; /* chip revision */ + + /* DMAable status queue memory */ + size_t sq_size; /* size of memory area */ + bus_dma_tag_t sq_tag; /* DMA tag */ + bus_dmamap_t sq_map; /* map */ + + bus_addr_t tsq_phy; /* phys addr. */ + struct idt_tsqe *tsq; /* transmit status queue */ + struct idt_tsqe *tsq_next; /* last processed entry */ + struct idt_rsqe *rsq; /* receive status queue */ + bus_addr_t rsq_phy; /* phys addr. */ + u_int rsq_last; /* last processed entry */ + struct idt_rawhnd *rawhnd; /* raw cell handle */ + bus_addr_t rawhnd_phy; /* phys addr. */ + + /* TST */ + u_int tst_state; /* active TST and others */ + u_int tst_jump[2]; /* address of the jumps */ + u_int tst_base[2]; /* base address of TST */ + u_int *tst_soft; /* soft TST */ + struct mtx tst_lock; + struct callout tst_callout; + u_int tst_free; /* free slots */ + u_int tst_reserve; /* non-CBR reserve */ + u_int bwrem; /* remaining bandwith */ + + /* sysctl support */ + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + + /* EEPROM contents */ + uint8_t eeprom[256]; + + /* large buffer mapping */ + bus_dma_tag_t lbuf_tag; /* DMA tag */ + u_int lbuf_max; /* maximum number */ + struct lmbuf *lbufs; /* array for indexing */ + SLIST_HEAD(,lmbuf) lbuf_free_list; /* free list */ + + /* small buffer handling */ + bus_dma_tag_t sbuf_tag; /* DMA tag */ + struct mbpool *sbuf_pool; /* pool */ + struct mbpool *vbuf_pool; /* pool */ + + /* raw cell queue */ + struct lmbuf *rawh; /* current header buf */ + u_int rawi; /* cell index into buffer */ + + /* statistics */ + struct patm_stats stats; /* statistics */ + + /* Vccs */ + struct patm_vcc **vccs; /* channel pointer array */ + u_int vccs_open; /* number of open channels */ + uma_zone_t vcc_zone; + struct cv vcc_cv; + + /* SCDs */ + uint32_t scd_free; /* SRAM of first free SCD */ + bus_dma_tag_t scd_tag; + struct patm_scd *scd0; + LIST_HEAD(, patm_scd) scd_list; /* list of all active SCDs */ + + /* Tx */ + bus_dma_tag_t tx_tag; /* for transmission */ + SLIST_HEAD(, patm_txmap) tx_maps_free; /* free maps */ + u_int tx_nmaps; /* allocated maps */ + u_int tx_maxmaps; /* maximum number */ + struct uma_zone *tx_mapzone; /* zone for maps */ + +#ifdef PATM_DEBUG + /* debugging */ + u_int debug; +#endif +}; + +/* flags */ +#define PATM_25M 0x0001 /* 25MBit card */ +#define PATM_SBUFW 0x0002 /* warned */ +#define PATM_VBUFW 0x0004 /* warned */ +#define PATM_UNASS 0x0010 /* unassigned cells */ + +#define PATM_CLR 0x0007 /* clear on stop */ + +/* tst - uses unused fields */ +#define TST_BOTH 0x03000000 +#define TST_CH0 0x01000000 +#define TST_CH1 0x02000000 +/* tst_state */ +#define TST_ACT1 0x0001 /* active TST */ +#define TST_PENDING 0x0002 /* need update */ +#define TST_WAIT 0x0004 /* wait fo jump */ + +#define patm_printf(SC, ...) if_printf(&(SC)->ifatm.ifnet, __VA_ARGS__); + +#ifdef PATM_DEBUG +/* + * Debugging + */ +enum { + DBG_ATTACH = 0x0001, /* attaching the card */ + DBG_INTR = 0x0002, /* interrupts */ + DBG_REG = 0x0004, /* register access */ + DBG_SRAM = 0x0008, /* SRAM access */ + DBG_PHY = 0x0010, /* PHY access */ + DBG_IOCTL = 0x0020, /* ioctl */ + DBG_FREEQ = 0x0040, /* free bufq supply */ + DBG_VCC = 0x0080, /* open/close */ + DBG_TX = 0x0100, /* transmission */ + DBG_TST = 0x0200, /* TST */ + + DBG_ALL = 0xffff +}; + +#define patm_debug(SC, FLAG, ...) do { \ + if((SC)->debug & DBG_##FLAG) { \ + if_printf(&(SC)->ifatm.ifnet, "%s: ", __func__); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + } \ + } while (0) +#else + +#define patm_debug(SC, FLAG, ...) do { } while (0) + +#endif + +/* start output */ +void patm_start(struct ifnet *); + +/* ioctl handler */ +int patm_ioctl(struct ifnet *, u_long, caddr_t); + +/* start the interface */ +void patm_init(void *); + +/* start the interface with the lock held */ +void patm_initialize(struct patm_softc *); + +/* stop the interface */ +void patm_stop(struct patm_softc *); + +/* software reset of interface */ +void patm_reset(struct patm_softc *); + +/* interrupt handler */ +void patm_intr(void *); + +/* check RSQ */ +void patm_intr_rsq(struct patm_softc *sc); + +/* close the given vcc for transmission */ +void patm_tx_vcc_close(struct patm_softc *, struct patm_vcc *); + +/* close the given vcc for receive */ +void patm_rx_vcc_close(struct patm_softc *, struct patm_vcc *); + +/* transmission side finally closed */ +void patm_tx_vcc_closed(struct patm_softc *, struct patm_vcc *); + +/* receive side finally closed */ +void patm_rx_vcc_closed(struct patm_softc *, struct patm_vcc *); + +/* vcc closed */ +void patm_vcc_closed(struct patm_softc *, struct patm_vcc *); + +/* check if we can open this one */ +int patm_tx_vcc_can_open(struct patm_softc *, struct patm_vcc *); + +/* check if we can open this one */ +int patm_rx_vcc_can_open(struct patm_softc *, struct patm_vcc *); + +/* open it */ +void patm_tx_vcc_open(struct patm_softc *, struct patm_vcc *); + +/* open it */ +void patm_rx_vcc_open(struct patm_softc *, struct patm_vcc *); + +/* receive packet */ +void patm_rx(struct patm_softc *, struct idt_rsqe *); + +/* packet transmitted */ +void patm_tx(struct patm_softc *, u_int, u_int); + +/* VBR connection went idle */ +void patm_tx_idle(struct patm_softc *, u_int); + +/* allocate an SCQ */ +struct patm_scd *patm_scd_alloc(struct patm_softc *); + +/* free an SCD */ +void patm_scd_free(struct patm_softc *sc, struct patm_scd *scd); + +/* setup SCD in SRAM */ +void patm_scd_setup(struct patm_softc *sc, struct patm_scd *scd); + +/* setup TCT entry in SRAM */ +void patm_tct_setup(struct patm_softc *, struct patm_scd *, struct patm_vcc *); + +/* free a large buffer */ +void patm_lbuf_free(struct patm_softc *sc, struct lmbuf *b); + +/* Process the raw cell at the given address */ +void patm_rx_raw(struct patm_softc *sc, u_char *cell); + +/* load a one segment DMA map */ +void patm_load_callback(void *, bus_dma_segment_t *, int, int); + +/* network operation register access */ +static __inline uint32_t +patm_nor_read(struct patm_softc *sc, u_int reg) +{ + uint32_t val; + + val = bus_space_read_4(sc->memt, sc->memh, reg); + patm_debug(sc, REG, "reg(0x%x)=%04x", reg, val); + return (val); +} +static __inline void +patm_nor_write(struct patm_softc *sc, u_int reg, uint32_t val) +{ + + patm_debug(sc, REG, "reg(0x%x)=%04x", reg, val); + bus_space_write_4(sc->memt, sc->memh, reg, val); +} + +/* Execute command */ +static __inline void +patm_cmd_wait(struct patm_softc *sc) +{ + while (patm_nor_read(sc, IDT_NOR_STAT) & IDT_STAT_CMDBZ) + ; +} +static __inline void +patm_cmd_exec(struct patm_softc *sc, uint32_t cmd) +{ + patm_cmd_wait(sc); + patm_nor_write(sc, IDT_NOR_CMD, cmd); +} + +/* Read/write SRAM at the given word address. */ +static __inline uint32_t +patm_sram_read(struct patm_softc *sc, u_int addr) +{ + uint32_t val; + + patm_cmd_exec(sc, IDT_MKCMD_RSRAM(addr)); + patm_cmd_wait(sc); + val = patm_nor_read(sc, IDT_NOR_D0); + patm_debug(sc, SRAM, "read %04x=%08x", addr, val); + return (val); +} +static __inline void +patm_sram_write(struct patm_softc *sc, u_int addr, uint32_t val) +{ + patm_debug(sc, SRAM, "write %04x=%08x", addr, val); + patm_cmd_wait(sc); + patm_nor_write(sc, IDT_NOR_D0, val); + patm_cmd_exec(sc, IDT_MKCMD_WSRAM(addr, 0)); +} +static __inline void +patm_sram_write4(struct patm_softc *sc, u_int addr, uint32_t v0, uint32_t v1, + uint32_t v2, uint32_t v3) +{ + patm_debug(sc, SRAM, "write %04x=%08x,%08x,%08x,%08x", + addr, v0, v1, v2, v3); + patm_cmd_wait(sc); + patm_nor_write(sc, IDT_NOR_D0, v0); + patm_nor_write(sc, IDT_NOR_D1, v1); + patm_nor_write(sc, IDT_NOR_D2, v2); + patm_nor_write(sc, IDT_NOR_D3, v3); + patm_cmd_exec(sc, IDT_MKCMD_WSRAM(addr, 3)); +} + +#define LEGAL_VPI(SC, VPI) \ + (((VPI) & ~((1 << (SC)->ifatm.mib.vpi_bits) - 1)) == 0) +#define LEGAL_VCI(SC, VCI) \ + (((VCI) & ~((1 << (SC)->ifatm.mib.vci_bits) - 1)) == 0) + +extern const uint32_t patm_rtables155[]; +extern const uint32_t patm_rtables25[]; +extern const u_int patm_rtables_size; +extern const u_int patm_rtables_ntab; |