1139749Simp/*- 2116491Sharti * Copyright (c) 2001-2003 3116491Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4116491Sharti * All rights reserved. 5116491Sharti * 6116491Sharti * Redistribution and use in source and binary forms, with or without 7116491Sharti * modification, are permitted provided that the following conditions 8116491Sharti * are met: 9116491Sharti * 1. Redistributions of source code must retain the above copyright 10116491Sharti * notice, this list of conditions and the following disclaimer. 11116491Sharti * 2. Redistributions in binary form must reproduce the above copyright 12116491Sharti * notice, this list of conditions and the following disclaimer in the 13116491Sharti * documentation and/or other materials provided with the distribution. 14116491Sharti * 15116491Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16116491Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17116491Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18116491Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19116491Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20116491Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21116491Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22116491Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23116491Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24116491Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25116491Sharti * SUCH DAMAGE. 26116491Sharti * 27116491Sharti * Author: Hartmut Brandt <harti@freebsd.org> 28116491Sharti * 29116491Sharti * $FreeBSD$ 30116491Sharti * 31116491Sharti * Fore HE driver for NATM 32116491Sharti */ 33116491Sharti 34116491Sharti/* 35116491Sharti * Debug statistics of the HE driver 36116491Sharti */ 37116491Shartistruct istats { 38116491Sharti uint32_t tdprq_full; 39116491Sharti uint32_t hbuf_error; 40116491Sharti uint32_t crc_error; 41116491Sharti uint32_t len_error; 42116491Sharti uint32_t flow_closed; 43116491Sharti uint32_t flow_drop; 44116491Sharti uint32_t tpd_no_mem; 45116491Sharti uint32_t rx_seg; 46116491Sharti uint32_t empty_hbuf; 47116491Sharti uint32_t short_aal5; 48116491Sharti uint32_t badlen_aal5; 49116491Sharti uint32_t bug_bad_isw; 50116491Sharti uint32_t bug_no_irq_upd; 51116491Sharti uint32_t itype_tbrq; 52116491Sharti uint32_t itype_tpd; 53116491Sharti uint32_t itype_rbps; 54116491Sharti uint32_t itype_rbpl; 55116491Sharti uint32_t itype_rbrq; 56116491Sharti uint32_t itype_rbrqt; 57116491Sharti uint32_t itype_unknown; 58116491Sharti uint32_t itype_phys; 59116491Sharti uint32_t itype_err; 60116491Sharti uint32_t defrag; 61118169Sharti uint32_t mcc; 62118169Sharti uint32_t oec; 63118169Sharti uint32_t dcc; 64118169Sharti uint32_t cec; 65121676Sharti uint32_t no_rcv_mbuf; 66116491Sharti}; 67116491Sharti 68116491Sharti/* Card memory layout parameters */ 69116491Sharti#define HE_CONFIG_MEM_LAYOUT { \ 70116491Sharti { /* 155 */ \ 71116491Sharti 20, /* cells_per_row */ \ 72116491Sharti 1024, /* bytes_per_row */ \ 73116491Sharti 512, /* r0_numrows */ \ 74116491Sharti 1018, /* tx_numrows */ \ 75116491Sharti 512, /* r1_numrows */ \ 76116491Sharti 6, /* r0_startrow */ \ 77116491Sharti 2 /* cells_per_lbuf */ \ 78116491Sharti }, { /* 622 */ \ 79116491Sharti 40, /* cells_per_row */ \ 80116491Sharti 2048, /* bytes_per_row */ \ 81116491Sharti 256, /* r0_numrows */ \ 82116491Sharti 512, /* tx_numrows */ \ 83116491Sharti 256, /* r1_numrows */ \ 84116491Sharti 0, /* r0_startrow */ \ 85116491Sharti 4 /* cells_per_lbuf */ \ 86116491Sharti } \ 87116491Sharti} 88116491Sharti 89116491Sharti/*********************************************************************/ 90116491Shartistruct hatm_softc; 91116491Sharti 92116491Sharti/* 93116491Sharti * A chunk of DMA-able memory 94116491Sharti */ 95116491Shartistruct dmamem { 96116491Sharti u_int size; /* in bytes */ 97116491Sharti u_int align; /* alignement */ 98116491Sharti bus_dma_tag_t tag; /* DMA tag */ 99116491Sharti void *base; /* the memory */ 100116491Sharti bus_addr_t paddr; /* physical address */ 101116491Sharti bus_dmamap_t map; /* the MAP */ 102116491Sharti}; 103116491Sharti 104116491Sharti/* 105116491Sharti * RBP (Receive Buffer Pool) queue entry and queue. 106116491Sharti */ 107116491Shartistruct herbp { 108116491Sharti u_int size; /* RBP number of entries (power of two) */ 109116491Sharti u_int thresh; /* interrupt treshold */ 110116491Sharti uint32_t bsize; /* buffer size in bytes */ 111116491Sharti u_int offset; /* free space at start for small bufs */ 112116491Sharti uint32_t mask; /* mask for index */ 113116491Sharti struct dmamem mem; /* the queue area */ 114116491Sharti struct he_rbpen *rbp; 115116491Sharti uint32_t head, tail; /* head and tail */ 116116491Sharti}; 117116491Sharti 118116491Sharti/* 119116491Sharti * RBRQ (Receive Buffer Return Queue) entry and queue. 120116491Sharti */ 121116491Shartistruct herbrq { 122116491Sharti u_int size; /* number of entries */ 123116491Sharti u_int thresh; /* interrupt threshold */ 124116491Sharti u_int tout; /* timeout value */ 125116491Sharti u_int pcnt; /* packet count threshold */ 126116491Sharti struct dmamem mem; /* memory */ 127116491Sharti struct he_rbrqen *rbrq; 128116491Sharti uint32_t head; /* driver end */ 129116491Sharti}; 130116491Sharti 131116491Sharti/* 132116491Sharti * TPDRQ (Transmit Packet Descriptor Ready Queue) entry and queue 133116491Sharti */ 134116491Shartistruct hetpdrq { 135116491Sharti u_int size; /* number of entries */ 136116491Sharti struct dmamem mem; /* memory */ 137116491Sharti struct he_tpdrqen *tpdrq; 138116491Sharti u_int head; /* head (copy of adapter) */ 139116491Sharti u_int tail; /* written back to adapter */ 140116491Sharti}; 141116491Sharti 142116491Sharti/* 143116491Sharti * TBRQ (Transmit Buffer Return Queue) entry and queue 144116491Sharti */ 145116491Shartistruct hetbrq { 146116491Sharti u_int size; /* number of entries */ 147116491Sharti u_int thresh; /* interrupt threshold */ 148116491Sharti struct dmamem mem; /* memory */ 149116491Sharti struct he_tbrqen *tbrq; 150116491Sharti u_int head; /* adapter end */ 151116491Sharti}; 152116491Sharti 153116491Sharti/*==================================================================*/ 154116491Sharti 155116491Sharti/* 156116491Sharti * TPDs are 32 byte and must be aligned on 64 byte boundaries. That means, 157116491Sharti * that half of the space is free. We use this space to plug in a link for 158116491Sharti * the list of free TPDs. Note, that the m_act member of the mbufs contain 159116491Sharti * a pointer to the dmamap. 160116491Sharti * 161116491Sharti * The maximum number of TDPs is the size of the common transmit packet 162116491Sharti * descriptor ready queue plus the sizes of the transmit buffer return queues 163116491Sharti * (currently only queue 0). We allocate and map these TPD when initializing 164116491Sharti * the card. We also allocate on DMA map for each TPD. Only the map in the 165116491Sharti * last TPD of a packets is used when a packet is transmitted. 166116491Sharti * This is signalled by having the mbuf member of this TPD non-zero and 167116491Sharti * pointing to the mbuf. 168116491Sharti */ 169116491Sharti#define HE_TPD_SIZE 64 170116491Shartistruct tpd { 171116491Sharti struct he_tpd tpd; /* at beginning */ 172116491Sharti SLIST_ENTRY(tpd) link; /* free cid list link */ 173116491Sharti struct mbuf *mbuf; /* the buf chain */ 174116491Sharti bus_dmamap_t map; /* map */ 175116491Sharti uint32_t cid; /* CID */ 176116491Sharti uint16_t no; /* number of this tpd */ 177116491Sharti}; 178116491ShartiSLIST_HEAD(tpd_list, tpd); 179116491Sharti 180116491Sharti#define TPD_SET_USED(SC, I) do { \ 181116491Sharti (SC)->tpd_used[(I) / 8] |= (1 << ((I) % 8)); \ 182116491Sharti } while (0) 183116491Sharti 184116491Sharti#define TPD_CLR_USED(SC, I) do { \ 185116491Sharti (SC)->tpd_used[(I) / 8] &= ~(1 << ((I) % 8)); \ 186116491Sharti } while (0) 187116491Sharti 188116491Sharti#define TPD_TST_USED(SC, I) ((SC)->tpd_used[(I) / 8] & (1 << ((I) % 8))) 189116491Sharti 190116491Sharti#define TPD_ADDR(SC, I) ((struct tpd *)((char *)sc->tpds.base + \ 191116491Sharti (I) * HE_TPD_SIZE)) 192116491Sharti 193116491Sharti/*==================================================================*/ 194116491Sharti 195116491Sharti/* 196116491Sharti * External MBUFs. The card needs a lot of mbufs in the pools for high 197116491Sharti * performance. The problem with using mbufs directly is that we would need 198116491Sharti * a dmamap for each of the mbufs. This can exhaust iommu space on the sparc 199116491Sharti * and it eats also a lot of processing time. So we use external mbufs 200116491Sharti * for the small buffers and clusters for the large buffers. 201116491Sharti * For receive group 0 we use 5 ATM cells, for group 1 one (52 byte) ATM 202116491Sharti * cell. The mbuf storage is allocated pagewise and one dmamap is used per 203116491Sharti * page. 204116491Sharti * 205116491Sharti * The handle we give to the card for the small buffers is a word combined 206116491Sharti * of the page number and the number of the chunk in the page. This restricts 207116491Sharti * the number of chunks per page to 256 (8 bit) and the number of pages to 208116491Sharti * 65536 (16 bits). 209116491Sharti * 210116491Sharti * A chunk may be in one of three states: free, on the card and floating around 211116491Sharti * in the system. If it is free, it is on one of the two free lists and 212116491Sharti * start with a struct mbufx_free. Each page has a bitmap that tracks where 213116491Sharti * its chunks are. 214116491Sharti * 215116491Sharti * For large buffers we use mbuf clusters. Here we have two problems: we need 216116491Sharti * to track the buffers on the card (in the case we want to stop it) and 217116491Sharti * we need to map the 64bit mbuf address to a 26bit handle for 64-bit machines. 218116491Sharti * The card uses the buffers in the order we give it to the card. Therefor 219116491Sharti * we can use a private array holding pointers to the mbufs as a circular 220116491Sharti * queue for both tasks. This is done with the lbufs member of softc. The 221116491Sharti * handle for these buffer is the lbufs index ored with a flag. 222116491Sharti */ 223121680Sharti 224121680Sharti/* data space in each external mbuf */ 225116491Sharti#define MBUF0_SIZE (5 * 48) /* 240 */ 226121680Sharti#define MBUF1_SIZE (52) /* 1 raw cell */ 227116491Sharti 228121680Sharti/* size of the buffer. Must fit data, offset and header */ 229116491Sharti#define MBUF0_CHUNK 256 /* 16 free bytes */ 230116491Sharti#define MBUF1_CHUNK 96 /* 44 free bytes */ 231121680Sharti 232121680Sharti/* start of actual data in buffer */ 233116491Sharti#define MBUF0_OFFSET 0 234121680Sharti#define MBUF1_OFFSET 16 235121680Sharti 236116491Sharti#define MBUFL_OFFSET 16 /* two pointers for HARP */ 237116491Sharti 238121797Sharti#if PAGE_SIZE > 8192 239121797Sharti#define MBUF_ALLOC_SIZE (8192) 240121797Sharti#else 241121797Sharti#define MBUF_ALLOC_SIZE (PAGE_SIZE) 242121797Sharti#endif 243116491Sharti 244116491Sharti/* each allocated page has one of these structures at its very end. */ 245116491Shartistruct mbuf_page_hdr { 246116491Sharti uint16_t nchunks; /* chunks on this page */ 247116491Sharti bus_dmamap_t map; /* the DMA MAP */ 248116491Sharti uint32_t phys; /* physical base address */ 249116491Sharti uint32_t hdroff; /* chunk header offset */ 250116491Sharti uint32_t chunksize; /* chunk size */ 251121729Sharti u_int pool; /* pool number */ 252116491Sharti}; 253116491Shartistruct mbuf_page { 254116491Sharti char storage[MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)]; 255116491Sharti struct mbuf_page_hdr hdr; 256116491Sharti}; 257116491Sharti 258116491Sharti/* numbers per page */ 259116491Sharti#define MBUF0_PER_PAGE ((MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)) / \ 260116491Sharti MBUF0_CHUNK) 261116491Sharti#define MBUF1_PER_PAGE ((MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)) / \ 262116491Sharti MBUF1_CHUNK) 263116491Sharti 264121680Sharti/* 265121680Sharti * Convert to/from handles 266121680Sharti */ 267121680Sharti/* small buffers */ 268116491Sharti#define MBUF_MAKE_HANDLE(PAGENO, CHUNKNO) \ 269121680Sharti ((((PAGENO) << 10) | (CHUNKNO)) << HE_REGS_RBRQ_ADDR) 270121680Sharti#define MBUF_MAKE_LHANDLE(INDEX) \ 271121680Sharti (MBUF_LARGE_FLAG | ((INDEX) << HE_REGS_RBRQ_ADDR)) 272116491Sharti 273121680Sharti/* large buffers */ 274121680Sharti#define MBUF_PARSE_HANDLE(HANDLE, PAGENO, CHUNKNO) do { \ 275121680Sharti (CHUNKNO) = ((HANDLE) >> HE_REGS_RBRQ_ADDR) & 0x3ff; \ 276121680Sharti (PAGENO) = (((HANDLE) >> 10) >> HE_REGS_RBRQ_ADDR) & 0x3fff; \ 277116491Sharti } while (0) 278121680Sharti#define MBUF_PARSE_LHANDLE(HANDLE, INDEX) do { \ 279121680Sharti (INDEX) = ((HANDLE) >> HE_REGS_RBRQ_ADDR) & 0xffffff; \ 280121680Sharti } while (0) 281116491Sharti 282121680Sharti#define MBUF_LARGE_FLAG 0x80000000 283116491Sharti 284121729Sharti/* chunks have the following structure at the end (8 byte) */ 285116491Shartistruct mbuf_chunk_hdr { 286121729Sharti uint16_t pageno; 287121729Sharti uint8_t chunkno; 288121729Sharti uint8_t flags; 289121729Sharti u_int ref_cnt; 290116491Sharti}; 291121729Sharti#define MBUF_CARD 0x01 /* buffer is on card */ 292121729Sharti#define MBUF_USED 0x02 /* buffer is somewhere in the system */ 293116491Sharti 294116491Sharti#define MBUFX_STORAGE_SIZE(X) (MBUF##X##_CHUNK \ 295116491Sharti - sizeof(struct mbuf_chunk_hdr)) 296116491Sharti 297116491Shartistruct mbuf0_chunk { 298116491Sharti char storage[MBUFX_STORAGE_SIZE(0)]; 299116491Sharti struct mbuf_chunk_hdr hdr; 300116491Sharti}; 301116491Sharti 302116491Shartistruct mbuf1_chunk { 303116491Sharti char storage[MBUFX_STORAGE_SIZE(1)]; 304116491Sharti struct mbuf_chunk_hdr hdr; 305116491Sharti}; 306116491Sharti 307116491Shartistruct mbufx_free { 308121675Sharti struct mbufx_free *link; 309116491Sharti}; 310116491Sharti 311116491Sharti/*==================================================================*/ 312116491Sharti 313116491Sharti/* 314116491Sharti * Interrupt queue 315116491Sharti */ 316116491Shartistruct heirq { 317116491Sharti u_int size; /* number of entries */ 318116491Sharti u_int thresh; /* re-interrupt threshold */ 319116491Sharti u_int line; /* interrupt line to use */ 320116491Sharti struct dmamem mem; /* interrupt queues */ 321116491Sharti uint32_t * irq; /* interrupt queue */ 322116491Sharti uint32_t head; /* head index */ 323116491Sharti uint32_t * tailp; /* pointer to tail */ 324116491Sharti struct hatm_softc *sc; /* back pointer */ 325116491Sharti u_int group; /* interrupt group */ 326116491Sharti}; 327116491Sharti 328116491Sharti/* 329116491Sharti * This structure describes all information for a VCC open on the card. 330116491Sharti * The array of these structures is indexed by the compressed connection ID 331118205Sharti * (CID). This structure must begin with the atmio_vcc. 332116491Sharti */ 333116491Shartistruct hevcc { 334118205Sharti struct atmio_vcc param; /* traffic parameters */ 335118205Sharti void * rxhand; /* NATM protocol block */ 336116491Sharti u_int vflags; /* private flags */ 337118205Sharti uint32_t ipackets; 338118205Sharti uint32_t opackets; 339118205Sharti uint32_t ibytes; 340118205Sharti uint32_t obytes; 341118205Sharti 342116491Sharti u_int rc; /* rate control group for CBR */ 343116491Sharti struct mbuf * chain; /* partial received PDU */ 344116491Sharti struct mbuf * last; /* last mbuf in chain */ 345116491Sharti u_int ntpds; /* number of active TPDs */ 346116491Sharti}; 347116491Sharti#define HE_VCC_OPEN 0x000f0000 348116491Sharti#define HE_VCC_RX_OPEN 0x00010000 349116491Sharti#define HE_VCC_RX_CLOSING 0x00020000 350116491Sharti#define HE_VCC_TX_OPEN 0x00040000 351116491Sharti#define HE_VCC_TX_CLOSING 0x00080000 352116491Sharti#define HE_VCC_FLOW_CTRL 0x00100000 353116491Sharti 354116491Sharti/* 355116491Sharti * CBR rate groups 356116491Sharti */ 357116491Shartistruct herg { 358116491Sharti u_int refcnt; /* how many connections reference this group */ 359116491Sharti u_int rate; /* the value */ 360116491Sharti}; 361116491Sharti 362116491Sharti/* 363116491Sharti * Softc 364116491Sharti */ 365116491Shartistruct hatm_softc { 366147256Sbrooks struct ifnet *ifp; 367116491Sharti struct mtx mtx; /* lock */ 368116491Sharti struct ifmedia media; /* media */ 369116491Sharti device_t dev; /* device */ 370116491Sharti int memid; /* resoure id for memory */ 371116491Sharti struct resource * memres; /* memory resource */ 372116491Sharti bus_space_handle_t memh; /* handle */ 373116491Sharti bus_space_tag_t memt; /* ... and tag */ 374116491Sharti bus_dma_tag_t parent_tag; /* global restriction */ 375116491Sharti struct cv vcc_cv; /* condition variable */ 376116491Sharti int irqid; /* resource id */ 377116491Sharti struct resource * irqres; /* resource */ 378116491Sharti void * ih; /* interrupt handle */ 379116491Sharti struct utopia utopia; /* utopia state */ 380116491Sharti 381116491Sharti /* rest has to be reset by stop */ 382116491Sharti int he622; /* this is a HE622 */ 383116491Sharti int pci64; /* 64bit bus */ 384116491Sharti char prod_id[HE_EEPROM_PROD_ID_LEN + 1]; 385116491Sharti char rev[HE_EEPROM_REV_LEN + 1]; 386116491Sharti struct heirq irq_0; /* interrupt queues 0 */ 387116491Sharti 388116491Sharti /* generic network controller state */ 389116491Sharti u_int cells_per_row; 390116491Sharti u_int bytes_per_row; 391116491Sharti u_int r0_numrows; 392116491Sharti u_int tx_numrows; 393116491Sharti u_int r1_numrows; 394116491Sharti u_int r0_startrow; 395116491Sharti u_int tx_startrow; 396116491Sharti u_int r1_startrow; 397116491Sharti u_int cells_per_lbuf; 398116491Sharti u_int r0_numbuffs; 399116491Sharti u_int r1_numbuffs; 400116491Sharti u_int tx_numbuffs; 401116491Sharti 402116491Sharti /* HSP */ 403116491Sharti struct he_hsp *hsp; 404116491Sharti struct dmamem hsp_mem; 405116491Sharti 406116491Sharti /*** TX ***/ 407116491Sharti struct hetbrq tbrq; /* TBRQ 0 */ 408116491Sharti struct hetpdrq tpdrq; /* TPDRQ */ 409116491Sharti struct tpd_list tpd_free; /* Free TPDs */ 410116491Sharti u_int tpd_nfree; /* number of free TPDs */ 411116491Sharti u_int tpd_total; /* total TPDs */ 412116491Sharti uint8_t *tpd_used; /* bitmap of used TPDs */ 413116491Sharti struct dmamem tpds; /* TPD memory */ 414116491Sharti bus_dma_tag_t tx_tag; /* DMA tag for all tx mbufs */ 415116491Sharti 416116491Sharti /*** RX ***/ 417116491Sharti /* receive/transmit groups */ 418116491Sharti struct herbp rbp_s0; /* RBPS0 */ 419116491Sharti struct herbp rbp_l0; /* RBPL0 */ 420116491Sharti struct herbp rbp_s1; /* RBPS1 */ 421116491Sharti struct herbrq rbrq_0; /* RBRQ0 */ 422116491Sharti struct herbrq rbrq_1; /* RBRQ1 */ 423116491Sharti 424116491Sharti /* list of external mbuf storage */ 425116491Sharti bus_dma_tag_t mbuf_tag; 426116491Sharti struct mbuf_page **mbuf_pages; 427116491Sharti u_int mbuf_npages; 428121685Sharti u_int mbuf_max_pages; 429121675Sharti struct mbufx_free *mbuf_list[2]; 430116491Sharti 431116491Sharti /* mbuf cluster tracking and mapping for group 0 */ 432116491Sharti struct mbuf **lbufs; /* mbufs */ 433116491Sharti bus_dmamap_t *rmaps; /* DMA maps */ 434116491Sharti u_int lbufs_size; 435116491Sharti u_int lbufs_next; 436116491Sharti 437116491Sharti /* VCCs */ 438116491Sharti struct hevcc *vccs[HE_MAX_VCCS]; 439116491Sharti u_int cbr_bw; /* BW allocated to CBR */ 440116491Sharti u_int max_tpd; /* per VCC */ 441116491Sharti u_int open_vccs; 442116491Sharti uma_zone_t vcc_zone; 443116491Sharti 444116491Sharti /* rate groups */ 445116491Sharti struct herg rate_ctrl[HE_REGN_CS_STPER]; 446116491Sharti 447116491Sharti /* memory offsets */ 448116491Sharti u_int tsrb, tsrc, tsrd; 449116491Sharti u_int rsrb; 450116491Sharti 451116491Sharti struct cv cv_rcclose; /* condition variable */ 452116491Sharti uint32_t rate_grid[16][16]; /* our copy */ 453116491Sharti 454116491Sharti /* sysctl support */ 455116491Sharti struct sysctl_ctx_list sysctl_ctx; 456116491Sharti struct sysctl_oid *sysctl_tree; 457116491Sharti 458116491Sharti /* internal statistics */ 459116491Sharti struct istats istats; 460116491Sharti 461122113Sharti u_int mpsafe; 462122113Sharti 463116491Sharti#ifdef HATM_DEBUG 464116491Sharti /* debugging */ 465116491Sharti u_int debug; 466122112Sharti 467122112Sharti /* transmit mbuf count */ 468122112Sharti int txmbuf; 469116491Sharti#endif 470116491Sharti}; 471116491Sharti 472116491Sharti#define READ4(SC,OFF) bus_space_read_4(SC->memt, SC->memh, (OFF)) 473116491Sharti#define READ2(SC,OFF) bus_space_read_2(SC->memt, SC->memh, (OFF)) 474116491Sharti#define READ1(SC,OFF) bus_space_read_1(SC->memt, SC->memh, (OFF)) 475116491Sharti 476116491Sharti#define WRITE4(SC,OFF,VAL) bus_space_write_4(SC->memt, SC->memh, (OFF), (VAL)) 477116491Sharti#define WRITE2(SC,OFF,VAL) bus_space_write_2(SC->memt, SC->memh, (OFF), (VAL)) 478116491Sharti#define WRITE1(SC,OFF,VAL) bus_space_write_1(SC->memt, SC->memh, (OFF), (VAL)) 479116491Sharti 480116491Sharti#define BARRIER_R(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \ 481116491Sharti BUS_SPACE_BARRIER_READ) 482116491Sharti#define BARRIER_W(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \ 483116491Sharti BUS_SPACE_BARRIER_WRITE) 484116491Sharti#define BARRIER_RW(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \ 485116491Sharti BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) 486116491Sharti 487116491Sharti#define READ_SUNI(SC,OFF) READ4(SC, HE_REGO_SUNI + 4 * (OFF)) 488116491Sharti#define WRITE_SUNI(SC,OFF,VAL) WRITE4(SC, HE_REGO_SUNI + 4 * (OFF), (VAL)) 489116491Sharti 490116491Sharti#define READ_LB4(SC,OFF) \ 491116491Sharti ({ \ 492116491Sharti WRITE4(SC, HE_REGO_LB_MEM_ADDR, (OFF)); \ 493116491Sharti WRITE4(SC, HE_REGO_LB_MEM_ACCESS, \ 494116491Sharti (HE_REGM_LB_MEM_HNDSHK | HE_REGM_LB_MEM_READ)); \ 495116491Sharti while((READ4(SC, HE_REGO_LB_MEM_ACCESS) & HE_REGM_LB_MEM_HNDSHK))\ 496116491Sharti ; \ 497116491Sharti READ4(SC, HE_REGO_LB_MEM_DATA); \ 498116491Sharti }) 499116491Sharti#define WRITE_LB4(SC,OFF,VAL) \ 500116491Sharti do { \ 501116491Sharti WRITE4(SC, HE_REGO_LB_MEM_ADDR, (OFF)); \ 502116491Sharti WRITE4(SC, HE_REGO_LB_MEM_DATA, (VAL)); \ 503116491Sharti WRITE4(SC, HE_REGO_LB_MEM_ACCESS, \ 504116491Sharti (HE_REGM_LB_MEM_HNDSHK | HE_REGM_LB_MEM_WRITE)); \ 505116491Sharti while((READ4(SC, HE_REGO_LB_MEM_ACCESS) & HE_REGM_LB_MEM_HNDSHK))\ 506116491Sharti ; \ 507116491Sharti } while(0) 508116491Sharti 509116491Sharti#define WRITE_MEM4(SC,OFF,VAL,SPACE) \ 510116491Sharti do { \ 511116491Sharti WRITE4(SC, HE_REGO_CON_DAT, (VAL)); \ 512116491Sharti WRITE4(SC, HE_REGO_CON_CTL, \ 513116491Sharti (SPACE | HE_REGM_CON_WE | HE_REGM_CON_STATUS | (OFF))); \ 514116491Sharti while((READ4(SC, HE_REGO_CON_CTL) & HE_REGM_CON_STATUS) != 0) \ 515116491Sharti ; \ 516116491Sharti } while(0) 517116491Sharti 518116491Sharti#define READ_MEM4(SC,OFF,SPACE) \ 519116491Sharti ({ \ 520116491Sharti WRITE4(SC, HE_REGO_CON_CTL, \ 521116491Sharti (SPACE | HE_REGM_CON_STATUS | (OFF))); \ 522116491Sharti while((READ4(SC, HE_REGO_CON_CTL) & HE_REGM_CON_STATUS) != 0) \ 523116491Sharti ; \ 524116491Sharti READ4(SC, HE_REGO_CON_DAT); \ 525116491Sharti }) 526116491Sharti 527116491Sharti#define WRITE_TCM4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_TCM) 528116491Sharti#define WRITE_RCM4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_RCM) 529116491Sharti#define WRITE_MBOX4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_MBOX) 530116491Sharti 531116491Sharti#define READ_TCM4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_TCM) 532116491Sharti#define READ_RCM4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_RCM) 533116491Sharti#define READ_MBOX4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_MBOX) 534116491Sharti 535116491Sharti#define WRITE_TCM(SC,OFF,BYTES,VAL) \ 536116491Sharti WRITE_MEM4(SC,(OFF) | ((~(BYTES) & 0xf) << HE_REGS_CON_DIS), \ 537116491Sharti (VAL), HE_REGM_CON_TCM) 538116491Sharti#define WRITE_RCM(SC,OFF,BYTES,VAL) \ 539116491Sharti WRITE_MEM4(SC,(OFF) | ((~(BYTES) & 0xf) << HE_REGS_CON_DIS), \ 540116491Sharti (VAL), HE_REGM_CON_RCM) 541116491Sharti 542116491Sharti#define READ_TSR(SC,CID,NR) \ 543116491Sharti ({ \ 544116491Sharti uint32_t _v; \ 545116491Sharti if((NR) <= 7) { \ 546116491Sharti _v = READ_TCM4(SC, HE_REGO_TSRA(0,CID,NR)); \ 547116491Sharti } else if((NR) <= 11) { \ 548116491Sharti _v = READ_TCM4(SC, HE_REGO_TSRB((SC)->tsrb,CID,(NR-8)));\ 549116491Sharti } else if((NR) <= 13) { \ 550116491Sharti _v = READ_TCM4(SC, HE_REGO_TSRC((SC)->tsrc,CID,(NR-12)));\ 551116491Sharti } else { \ 552116491Sharti _v = READ_TCM4(SC, HE_REGO_TSRD((SC)->tsrd,CID)); \ 553116491Sharti } \ 554116491Sharti _v; \ 555116491Sharti }) 556116491Sharti 557116491Sharti#define WRITE_TSR(SC,CID,NR,BEN,VAL) \ 558116491Sharti do { \ 559116491Sharti if((NR) <= 7) { \ 560116491Sharti WRITE_TCM(SC, HE_REGO_TSRA(0,CID,NR),BEN,VAL); \ 561116491Sharti } else if((NR) <= 11) { \ 562116491Sharti WRITE_TCM(SC, HE_REGO_TSRB((SC)->tsrb,CID,(NR-8)),BEN,VAL);\ 563116491Sharti } else if((NR) <= 13) { \ 564116491Sharti WRITE_TCM(SC, HE_REGO_TSRC((SC)->tsrc,CID,(NR-12)),BEN,VAL);\ 565116491Sharti } else { \ 566116491Sharti WRITE_TCM(SC, HE_REGO_TSRD((SC)->tsrd,CID),BEN,VAL); \ 567116491Sharti } \ 568116491Sharti } while(0) 569116491Sharti 570116491Sharti#define READ_RSR(SC,CID,NR) \ 571116491Sharti ({ \ 572116491Sharti uint32_t _v; \ 573116491Sharti if((NR) <= 7) { \ 574116491Sharti _v = READ_RCM4(SC, HE_REGO_RSRA(0,CID,NR)); \ 575116491Sharti } else { \ 576116491Sharti _v = READ_RCM4(SC, HE_REGO_RSRB((SC)->rsrb,CID,(NR-8)));\ 577116491Sharti } \ 578116491Sharti _v; \ 579116491Sharti }) 580116491Sharti 581116491Sharti#define WRITE_RSR(SC,CID,NR,BEN,VAL) \ 582116491Sharti do { \ 583116491Sharti if((NR) <= 7) { \ 584116491Sharti WRITE_RCM(SC, HE_REGO_RSRA(0,CID,NR),BEN,VAL); \ 585116491Sharti } else { \ 586116491Sharti WRITE_RCM(SC, HE_REGO_RSRB((SC)->rsrb,CID,(NR-8)),BEN,VAL);\ 587116491Sharti } \ 588116491Sharti } while(0) 589116491Sharti 590116491Sharti#ifdef HATM_DEBUG 591116491Sharti#define DBG(SC, FL, PRINT) do { \ 592116491Sharti if((SC)->debug & DBG_##FL) { \ 593147524Sharti if_printf((SC)->ifp, "%s: ", __func__); \ 594116491Sharti printf PRINT; \ 595116491Sharti printf("\n"); \ 596116491Sharti } \ 597116491Sharti } while (0) 598116491Sharti 599116491Shartienum { 600121681Sharti DBG_DUMMY = 0x0001, /* default value for -DHATM_DEBUG */ 601121681Sharti DBG_RX = 0x0002, 602121681Sharti DBG_TX = 0x0004, 603121681Sharti DBG_VCC = 0x0008, 604121681Sharti DBG_IOCTL = 0x0010, 605121681Sharti DBG_ATTACH = 0x0020, 606121681Sharti DBG_INTR = 0x0040, 607121681Sharti DBG_DMA = 0x0080, 608121681Sharti DBG_DMAH = 0x0100, 609121681Sharti DBG_DUMP = 0x0200, 610116491Sharti 611121681Sharti DBG_ALL = 0x03ff 612116491Sharti}; 613116491Sharti 614116491Sharti#else 615116491Sharti#define DBG(SC, FL, PRINT) 616116491Sharti#endif 617116491Sharti 618116491Shartiu_int hatm_cps2atmf(uint32_t); 619116491Shartiu_int hatm_atmf2cps(uint32_t); 620116491Sharti 621116491Shartivoid hatm_intr(void *); 622116491Shartiint hatm_ioctl(struct ifnet *, u_long, caddr_t); 623116491Shartivoid hatm_initialize(struct hatm_softc *); 624116491Shartivoid hatm_stop(struct hatm_softc *sc); 625116491Shartivoid hatm_start(struct ifnet *); 626116491Sharti 627116491Shartivoid hatm_rx(struct hatm_softc *sc, u_int cid, u_int flags, struct mbuf *m, 628116491Sharti u_int len); 629116491Shartivoid hatm_tx_complete(struct hatm_softc *sc, struct tpd *tpd, uint32_t); 630116491Sharti 631116491Shartiint hatm_tx_vcc_can_open(struct hatm_softc *sc, u_int cid, struct hevcc *); 632116491Shartivoid hatm_tx_vcc_open(struct hatm_softc *sc, u_int cid); 633116491Shartivoid hatm_rx_vcc_open(struct hatm_softc *sc, u_int cid); 634116491Shartivoid hatm_tx_vcc_close(struct hatm_softc *sc, u_int cid); 635116491Shartivoid hatm_rx_vcc_close(struct hatm_softc *sc, u_int cid); 636116491Shartivoid hatm_tx_vcc_closed(struct hatm_softc *sc, u_int cid); 637116491Shartivoid hatm_vcc_closed(struct hatm_softc *sc, u_int cid); 638118598Shartivoid hatm_load_vc(struct hatm_softc *sc, u_int cid, int reopen); 639121729Sharti 640121729Shartivoid hatm_ext_free(struct mbufx_free **, struct mbufx_free *); 641