]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/hatm/if_hatmvar.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / hatm / if_hatmvar.h
1 /*-
2  * Copyright (c) 2001-2003
3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <harti@freebsd.org>
28  *
29  * $FreeBSD$
30  *
31  * Fore HE driver for NATM
32  */
33
34 /*
35  * Debug statistics of the HE driver
36  */
37 struct istats {
38         uint32_t        tdprq_full;
39         uint32_t        hbuf_error;
40         uint32_t        crc_error;
41         uint32_t        len_error;
42         uint32_t        flow_closed;
43         uint32_t        flow_drop;
44         uint32_t        tpd_no_mem;
45         uint32_t        rx_seg;
46         uint32_t        empty_hbuf;
47         uint32_t        short_aal5;
48         uint32_t        badlen_aal5;
49         uint32_t        bug_bad_isw;
50         uint32_t        bug_no_irq_upd;
51         uint32_t        itype_tbrq;
52         uint32_t        itype_tpd;
53         uint32_t        itype_rbps;
54         uint32_t        itype_rbpl;
55         uint32_t        itype_rbrq;
56         uint32_t        itype_rbrqt;
57         uint32_t        itype_unknown;
58         uint32_t        itype_phys;
59         uint32_t        itype_err;
60         uint32_t        defrag;
61         uint32_t        mcc;
62         uint32_t        oec;
63         uint32_t        dcc;
64         uint32_t        cec;
65         uint32_t        no_rcv_mbuf;
66 };
67
68 /* Card memory layout parameters */
69 #define HE_CONFIG_MEM_LAYOUT {                                          \
70         {                       /* 155 */                               \
71           20,                   /* cells_per_row */                     \
72           1024,                 /* bytes_per_row */                     \
73           512,                  /* r0_numrows */                        \
74           1018,                 /* tx_numrows */                        \
75           512,                  /* r1_numrows */                        \
76           6,                    /* r0_startrow */                       \
77           2                     /* cells_per_lbuf */                    \
78         }, {                    /* 622 */                               \
79           40,                   /* cells_per_row */                     \
80           2048,                 /* bytes_per_row */                     \
81           256,                  /* r0_numrows */                        \
82           512,                  /* tx_numrows */                        \
83           256,                  /* r1_numrows */                        \
84           0,                    /* r0_startrow */                       \
85           4                     /* cells_per_lbuf */                    \
86         }                                                               \
87 }
88
89 /*********************************************************************/
90 struct hatm_softc;
91
92 /*
93  * A chunk of DMA-able memory
94  */
95 struct dmamem {
96         u_int           size;           /* in bytes */
97         u_int           align;          /* alignement */
98         bus_dma_tag_t   tag;            /* DMA tag */
99         void            *base;          /* the memory */
100         bus_addr_t      paddr;          /* physical address */
101         bus_dmamap_t    map;            /* the MAP */
102 };
103
104 /*
105  * RBP (Receive Buffer Pool) queue entry and queue.
106  */
107 struct herbp {
108         u_int           size;           /* RBP number of entries (power of two) */
109         u_int           thresh;         /* interrupt treshold */
110         uint32_t        bsize;          /* buffer size in bytes */
111         u_int           offset;         /* free space at start for small bufs */
112         uint32_t        mask;           /* mask for index */
113         struct dmamem   mem;            /* the queue area */
114         struct he_rbpen *rbp;
115         uint32_t        head, tail;     /* head and tail */
116 };
117
118 /*
119  * RBRQ (Receive Buffer Return Queue) entry and queue.
120  */
121 struct herbrq {
122         u_int           size;           /* number of entries */
123         u_int           thresh;         /* interrupt threshold */
124         u_int           tout;           /* timeout value */
125         u_int           pcnt;           /* packet count threshold */
126         struct dmamem   mem;            /* memory */
127         struct he_rbrqen *rbrq;
128         uint32_t        head;           /* driver end */
129 };
130
131 /*
132  * TPDRQ (Transmit Packet Descriptor Ready Queue) entry and queue
133  */
134 struct hetpdrq {
135         u_int           size;           /* number of entries */
136         struct dmamem   mem;            /* memory */
137         struct he_tpdrqen *tpdrq;
138         u_int           head;           /* head (copy of adapter) */
139         u_int           tail;           /* written back to adapter */
140 };
141
142 /*
143  * TBRQ (Transmit Buffer Return Queue) entry and queue
144  */
145 struct hetbrq {
146         u_int           size;           /* number of entries */
147         u_int           thresh;         /* interrupt threshold */
148         struct dmamem   mem;            /* memory */
149         struct he_tbrqen *tbrq;
150         u_int           head;           /* adapter end */
151 };
152
153 /*==================================================================*/
154
155 /*
156  * TPDs are 32 byte and must be aligned on 64 byte boundaries. That means,
157  * that half of the space is free. We use this space to plug in a link for
158  * the list of free TPDs. Note, that the m_act member of the mbufs contain
159  * a pointer to the dmamap.
160  *
161  * The maximum number of TDPs is the size of the common transmit packet
162  * descriptor ready queue plus the sizes of the transmit buffer return queues
163  * (currently only queue 0). We allocate and map these TPD when initializing
164  * the card. We also allocate on DMA map for each TPD. Only the map in the
165  * last TPD of a packets is used when a packet is transmitted.
166  * This is signalled by having the mbuf member of this TPD non-zero and
167  * pointing to the mbuf.
168  */
169 #define HE_TPD_SIZE             64
170 struct tpd {
171         struct he_tpd           tpd;    /* at beginning */
172         SLIST_ENTRY(tpd)        link;   /* free cid list link */
173         struct mbuf             *mbuf;  /* the buf chain */
174         bus_dmamap_t            map;    /* map */
175         uint32_t                cid;    /* CID */
176         uint16_t                no;     /* number of this tpd */
177 };
178 SLIST_HEAD(tpd_list, tpd);
179
180 #define TPD_SET_USED(SC, I) do {                                \
181         (SC)->tpd_used[(I) / 8] |= (1 << ((I) % 8));            \
182     } while (0)
183
184 #define TPD_CLR_USED(SC, I) do {                                \
185         (SC)->tpd_used[(I) / 8] &= ~(1 << ((I) % 8));           \
186     } while (0)
187
188 #define TPD_TST_USED(SC, I) ((SC)->tpd_used[(I) / 8] & (1 << ((I) % 8)))
189
190 #define TPD_ADDR(SC, I) ((struct tpd *)((char *)sc->tpds.base + \
191     (I) * HE_TPD_SIZE))
192
193 /*==================================================================*/
194
195 /*
196  * External MBUFs. The card needs a lot of mbufs in the pools for high
197  * performance. The problem with using mbufs directly is that we would need
198  * a dmamap for each of the mbufs. This can exhaust iommu space on the sparc
199  * and it eats also a lot of processing time. So we use external mbufs
200  * for the small buffers and clusters for the large buffers.
201  * For receive group 0 we use 5 ATM cells, for group 1 one (52 byte) ATM
202  * cell. The mbuf storage is allocated pagewise and one dmamap is used per
203  * page.
204  *
205  * The handle we give to the card for the small buffers is a word combined
206  * of the page number and the number of the chunk in the page. This restricts
207  * the number of chunks per page to 256 (8 bit) and the number of pages to
208  * 65536 (16 bits).
209  *
210  * A chunk may be in one of three states: free, on the card and floating around
211  * in the system. If it is free, it is on one of the two free lists and
212  * start with a struct mbufx_free. Each page has a bitmap that tracks where
213  * its chunks are.
214  *
215  * For large buffers we use mbuf clusters. Here we have two problems: we need
216  * to track the buffers on the card (in the case we want to stop it) and
217  * we need to map the 64bit mbuf address to a 26bit handle for 64-bit machines.
218  * The card uses the buffers in the order we give it to the card. Therefor
219  * we can use a private array holding pointers to the mbufs as a circular
220  * queue for both tasks. This is done with the lbufs member of softc. The
221  * handle for these buffer is the lbufs index ored with a flag.
222  */
223
224 /* data space in each external mbuf */
225 #define MBUF0_SIZE      (5 * 48)        /* 240 */
226 #define MBUF1_SIZE      (52)            /* 1 raw cell */
227
228 /* size of the buffer. Must fit data, offset and header */
229 #define MBUF0_CHUNK     256             /* 16 free bytes */
230 #define MBUF1_CHUNK     96              /* 44 free bytes */
231
232 /* start of actual data in buffer */
233 #define MBUF0_OFFSET    0
234 #define MBUF1_OFFSET    16
235
236 #define MBUFL_OFFSET    16              /* two pointers for HARP */
237
238 #if PAGE_SIZE > 8192
239 #define MBUF_ALLOC_SIZE (8192)
240 #else
241 #define MBUF_ALLOC_SIZE (PAGE_SIZE)
242 #endif
243
244 /* each allocated page has one of these structures at its very end. */
245 struct mbuf_page_hdr {
246         uint16_t        nchunks;        /* chunks on this page */
247         bus_dmamap_t    map;            /* the DMA MAP */
248         uint32_t        phys;           /* physical base address */
249         uint32_t        hdroff;         /* chunk header offset */
250         uint32_t        chunksize;      /* chunk size */
251         u_int           pool;           /* pool number */
252 };
253 struct mbuf_page {
254         char    storage[MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)];
255         struct mbuf_page_hdr    hdr;
256 };
257
258 /* numbers per page */
259 #define MBUF0_PER_PAGE  ((MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)) / \
260     MBUF0_CHUNK)
261 #define MBUF1_PER_PAGE  ((MBUF_ALLOC_SIZE - sizeof(struct mbuf_page_hdr)) / \
262     MBUF1_CHUNK)
263
264 /*
265  * Convert to/from handles
266  */
267 /* small buffers */
268 #define MBUF_MAKE_HANDLE(PAGENO, CHUNKNO) \
269         ((((PAGENO) << 10) | (CHUNKNO)) << HE_REGS_RBRQ_ADDR)
270 #define MBUF_MAKE_LHANDLE(INDEX) \
271         (MBUF_LARGE_FLAG | ((INDEX) << HE_REGS_RBRQ_ADDR))
272
273 /* large buffers */
274 #define MBUF_PARSE_HANDLE(HANDLE, PAGENO, CHUNKNO) do {                 \
275         (CHUNKNO) = ((HANDLE) >> HE_REGS_RBRQ_ADDR) & 0x3ff;            \
276         (PAGENO) = (((HANDLE) >> 10) >> HE_REGS_RBRQ_ADDR) & 0x3fff;    \
277     } while (0)
278 #define MBUF_PARSE_LHANDLE(HANDLE, INDEX) do {                          \
279         (INDEX) = ((HANDLE) >> HE_REGS_RBRQ_ADDR) & 0xffffff;           \
280     } while (0)
281
282 #define MBUF_LARGE_FLAG 0x80000000
283
284 /* chunks have the following structure at the end (8 byte) */
285 struct mbuf_chunk_hdr {
286         uint16_t        pageno;
287         uint8_t         chunkno;
288         uint8_t         flags;
289         u_int           ref_cnt;
290 };
291 #define MBUF_CARD       0x01    /* buffer is on card */
292 #define MBUF_USED       0x02    /* buffer is somewhere in the system */
293
294 #define MBUFX_STORAGE_SIZE(X) (MBUF##X##_CHUNK  \
295     - sizeof(struct mbuf_chunk_hdr))
296
297 struct mbuf0_chunk {
298         char                    storage[MBUFX_STORAGE_SIZE(0)];
299         struct mbuf_chunk_hdr   hdr;
300 };
301
302 struct mbuf1_chunk {
303         char                    storage[MBUFX_STORAGE_SIZE(1)];
304         struct mbuf_chunk_hdr   hdr;
305 };
306
307 struct mbufx_free {
308         struct mbufx_free       *link;
309 };
310
311 /*==================================================================*/
312
313 /*
314  * Interrupt queue
315  */
316 struct heirq {
317         u_int           size;   /* number of entries */
318         u_int           thresh; /* re-interrupt threshold */
319         u_int           line;   /* interrupt line to use */
320         struct dmamem   mem;    /* interrupt queues */
321         uint32_t *      irq;    /* interrupt queue */
322         uint32_t        head;   /* head index */
323         uint32_t *      tailp;  /* pointer to tail */
324         struct hatm_softc *sc;  /* back pointer */
325         u_int           group;  /* interrupt group */
326 };
327
328 /*
329  * This structure describes all information for a VCC open on the card.
330  * The array of these structures is indexed by the compressed connection ID
331  * (CID). This structure must begin with the atmio_vcc.
332  */
333 struct hevcc {
334         struct atmio_vcc param;         /* traffic parameters */
335         void *          rxhand;         /* NATM protocol block */
336         u_int           vflags;         /* private flags */
337         uint32_t        ipackets;
338         uint32_t        opackets;
339         uint32_t        ibytes;
340         uint32_t        obytes;
341
342         u_int           rc;             /* rate control group for CBR */
343         struct mbuf *   chain;          /* partial received PDU */
344         struct mbuf *   last;           /* last mbuf in chain */
345         u_int           ntpds;          /* number of active TPDs */
346 };
347 #define HE_VCC_OPEN             0x000f0000
348 #define HE_VCC_RX_OPEN          0x00010000
349 #define HE_VCC_RX_CLOSING       0x00020000
350 #define HE_VCC_TX_OPEN          0x00040000
351 #define HE_VCC_TX_CLOSING       0x00080000
352 #define HE_VCC_FLOW_CTRL        0x00100000
353
354 /*
355  * CBR rate groups
356  */
357 struct herg {
358         u_int   refcnt;         /* how many connections reference this group */
359         u_int   rate;           /* the value */
360 };
361
362 /*
363  * Softc
364  */
365 struct hatm_softc {
366         struct ifnet            *ifp;
367         struct mtx              mtx;            /* lock */
368         struct ifmedia          media;          /* media */
369         device_t                dev;            /* device */
370         int                     memid;          /* resoure id for memory */
371         struct resource *       memres;         /* memory resource */
372         bus_space_handle_t      memh;           /* handle */
373         bus_space_tag_t         memt;           /* ... and tag */
374         bus_dma_tag_t           parent_tag;     /* global restriction */
375         struct cv               vcc_cv;         /* condition variable */
376         int                     irqid;          /* resource id */
377         struct resource *       irqres;         /* resource */
378         void *                  ih;             /* interrupt handle */
379         struct utopia           utopia;         /* utopia state */
380
381         /* rest has to be reset by stop */
382         int                     he622;          /* this is a HE622 */
383         int                     pci64;          /* 64bit bus */
384         char                    prod_id[HE_EEPROM_PROD_ID_LEN + 1];
385         char                    rev[HE_EEPROM_REV_LEN + 1];
386         struct heirq            irq_0;          /* interrupt queues 0 */
387
388         /* generic network controller state */
389         u_int                   cells_per_row;
390         u_int                   bytes_per_row;
391         u_int                   r0_numrows;
392         u_int                   tx_numrows;
393         u_int                   r1_numrows;
394         u_int                   r0_startrow;
395         u_int                   tx_startrow;
396         u_int                   r1_startrow;
397         u_int                   cells_per_lbuf;
398         u_int                   r0_numbuffs;
399         u_int                   r1_numbuffs;
400         u_int                   tx_numbuffs;
401
402         /* HSP */
403         struct he_hsp           *hsp;
404         struct dmamem           hsp_mem;
405
406         /*** TX ***/
407         struct hetbrq           tbrq;           /* TBRQ 0 */
408         struct hetpdrq          tpdrq;          /* TPDRQ */
409         struct tpd_list         tpd_free;       /* Free TPDs */
410         u_int                   tpd_nfree;      /* number of free TPDs */
411         u_int                   tpd_total;      /* total TPDs */
412         uint8_t                 *tpd_used;      /* bitmap of used TPDs */
413         struct dmamem           tpds;           /* TPD memory */
414         bus_dma_tag_t           tx_tag;         /* DMA tag for all tx mbufs */
415
416         /*** RX ***/
417         /* receive/transmit groups */
418         struct herbp            rbp_s0;         /* RBPS0 */
419         struct herbp            rbp_l0;         /* RBPL0 */
420         struct herbp            rbp_s1;         /* RBPS1 */
421         struct herbrq           rbrq_0;         /* RBRQ0 */
422         struct herbrq           rbrq_1;         /* RBRQ1 */
423
424         /* list of external mbuf storage */
425         bus_dma_tag_t           mbuf_tag;
426         struct mbuf_page        **mbuf_pages;
427         u_int                   mbuf_npages;
428         u_int                   mbuf_max_pages;
429         struct mbufx_free       *mbuf_list[2];
430
431         /* mbuf cluster tracking and mapping for group 0 */
432         struct mbuf             **lbufs;        /* mbufs */
433         bus_dmamap_t            *rmaps;         /* DMA maps */
434         u_int                   lbufs_size;
435         u_int                   lbufs_next;
436
437         /* VCCs */
438         struct hevcc            *vccs[HE_MAX_VCCS];
439         u_int                   cbr_bw;         /* BW allocated to CBR */
440         u_int                   max_tpd;        /* per VCC */
441         u_int                   open_vccs;
442         uma_zone_t              vcc_zone;
443
444         /* rate groups */
445         struct herg             rate_ctrl[HE_REGN_CS_STPER];
446
447         /* memory offsets */
448         u_int                   tsrb, tsrc, tsrd;
449         u_int                   rsrb;
450
451         struct cv               cv_rcclose;     /* condition variable */
452         uint32_t                rate_grid[16][16]; /* our copy */
453
454         /* sysctl support */
455         struct sysctl_ctx_list  sysctl_ctx;
456         struct sysctl_oid       *sysctl_tree;
457
458         /* internal statistics */
459         struct istats           istats;
460
461         u_int                   mpsafe;
462
463 #ifdef HATM_DEBUG
464         /* debugging */
465         u_int                   debug;
466
467         /* transmit mbuf count */
468         int                     txmbuf;
469 #endif
470 };
471
472 #define READ4(SC,OFF)   bus_space_read_4(SC->memt, SC->memh, (OFF))
473 #define READ2(SC,OFF)   bus_space_read_2(SC->memt, SC->memh, (OFF))
474 #define READ1(SC,OFF)   bus_space_read_1(SC->memt, SC->memh, (OFF))
475
476 #define WRITE4(SC,OFF,VAL) bus_space_write_4(SC->memt, SC->memh, (OFF), (VAL))
477 #define WRITE2(SC,OFF,VAL) bus_space_write_2(SC->memt, SC->memh, (OFF), (VAL))
478 #define WRITE1(SC,OFF,VAL) bus_space_write_1(SC->memt, SC->memh, (OFF), (VAL))
479
480 #define BARRIER_R(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \
481         BUS_SPACE_BARRIER_READ)
482 #define BARRIER_W(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \
483         BUS_SPACE_BARRIER_WRITE)
484 #define BARRIER_RW(SC) bus_space_barrier(SC->memt, SC->memh, 0, HE_REGO_END, \
485         BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
486
487 #define READ_SUNI(SC,OFF) READ4(SC, HE_REGO_SUNI + 4 * (OFF))
488 #define WRITE_SUNI(SC,OFF,VAL) WRITE4(SC, HE_REGO_SUNI + 4 * (OFF), (VAL))
489
490 #define READ_LB4(SC,OFF)                                                \
491     ({                                                                  \
492         WRITE4(SC, HE_REGO_LB_MEM_ADDR, (OFF));                         \
493         WRITE4(SC, HE_REGO_LB_MEM_ACCESS,                               \
494             (HE_REGM_LB_MEM_HNDSHK | HE_REGM_LB_MEM_READ));             \
495         while((READ4(SC, HE_REGO_LB_MEM_ACCESS) & HE_REGM_LB_MEM_HNDSHK))\
496                 ;                                                       \
497         READ4(SC, HE_REGO_LB_MEM_DATA);                                 \
498     })
499 #define WRITE_LB4(SC,OFF,VAL)                                           \
500     do {                                                                \
501         WRITE4(SC, HE_REGO_LB_MEM_ADDR, (OFF));                         \
502         WRITE4(SC, HE_REGO_LB_MEM_DATA, (VAL));                         \
503         WRITE4(SC, HE_REGO_LB_MEM_ACCESS,                               \
504             (HE_REGM_LB_MEM_HNDSHK | HE_REGM_LB_MEM_WRITE));            \
505         while((READ4(SC, HE_REGO_LB_MEM_ACCESS) & HE_REGM_LB_MEM_HNDSHK))\
506                 ;                                                       \
507     } while(0)
508
509 #define WRITE_MEM4(SC,OFF,VAL,SPACE)                                    \
510     do {                                                                \
511         WRITE4(SC, HE_REGO_CON_DAT, (VAL));                             \
512         WRITE4(SC, HE_REGO_CON_CTL,                                     \
513             (SPACE | HE_REGM_CON_WE | HE_REGM_CON_STATUS | (OFF)));     \
514         while((READ4(SC, HE_REGO_CON_CTL) & HE_REGM_CON_STATUS) != 0)   \
515                 ;                                                       \
516     } while(0)
517
518 #define READ_MEM4(SC,OFF,SPACE)                                 \
519     ({                                                                  \
520         WRITE4(SC, HE_REGO_CON_CTL,                                     \
521             (SPACE | HE_REGM_CON_STATUS | (OFF)));                      \
522         while((READ4(SC, HE_REGO_CON_CTL) & HE_REGM_CON_STATUS) != 0)   \
523                 ;                                                       \
524         READ4(SC, HE_REGO_CON_DAT);                                     \
525     })
526
527 #define WRITE_TCM4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_TCM)
528 #define WRITE_RCM4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_RCM)
529 #define WRITE_MBOX4(SC,OFF,VAL) WRITE_MEM4(SC,(OFF),(VAL),HE_REGM_CON_MBOX)
530
531 #define READ_TCM4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_TCM)
532 #define READ_RCM4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_RCM)
533 #define READ_MBOX4(SC,OFF) READ_MEM4(SC,(OFF),HE_REGM_CON_MBOX)
534
535 #define WRITE_TCM(SC,OFF,BYTES,VAL)                                     \
536         WRITE_MEM4(SC,(OFF) | ((~(BYTES) & 0xf) << HE_REGS_CON_DIS),    \
537             (VAL), HE_REGM_CON_TCM)
538 #define WRITE_RCM(SC,OFF,BYTES,VAL)                                     \
539         WRITE_MEM4(SC,(OFF) | ((~(BYTES) & 0xf) << HE_REGS_CON_DIS),    \
540             (VAL), HE_REGM_CON_RCM)
541
542 #define READ_TSR(SC,CID,NR)                                             \
543     ({                                                                  \
544         uint32_t _v;                                                    \
545         if((NR) <= 7) {                                                 \
546                 _v = READ_TCM4(SC, HE_REGO_TSRA(0,CID,NR));             \
547         } else if((NR) <= 11) {                                         \
548                 _v = READ_TCM4(SC, HE_REGO_TSRB((SC)->tsrb,CID,(NR-8)));\
549         } else if((NR) <= 13) {                                         \
550                 _v = READ_TCM4(SC, HE_REGO_TSRC((SC)->tsrc,CID,(NR-12)));\
551         } else {                                                        \
552                 _v = READ_TCM4(SC, HE_REGO_TSRD((SC)->tsrd,CID));       \
553         }                                                               \
554         _v;                                                             \
555     })
556
557 #define WRITE_TSR(SC,CID,NR,BEN,VAL)                                    \
558     do {                                                                \
559         if((NR) <= 7) {                                                 \
560                 WRITE_TCM(SC, HE_REGO_TSRA(0,CID,NR),BEN,VAL);          \
561         } else if((NR) <= 11) {                                         \
562                 WRITE_TCM(SC, HE_REGO_TSRB((SC)->tsrb,CID,(NR-8)),BEN,VAL);\
563         } else if((NR) <= 13) {                                         \
564                 WRITE_TCM(SC, HE_REGO_TSRC((SC)->tsrc,CID,(NR-12)),BEN,VAL);\
565         } else {                                                        \
566                 WRITE_TCM(SC, HE_REGO_TSRD((SC)->tsrd,CID),BEN,VAL);    \
567         }                                                               \
568     } while(0)
569
570 #define READ_RSR(SC,CID,NR)                                             \
571     ({                                                                  \
572         uint32_t _v;                                                    \
573         if((NR) <= 7) {                                                 \
574                 _v = READ_RCM4(SC, HE_REGO_RSRA(0,CID,NR));             \
575         } else {                                                        \
576                 _v = READ_RCM4(SC, HE_REGO_RSRB((SC)->rsrb,CID,(NR-8)));\
577         }                                                               \
578         _v;                                                             \
579     })
580
581 #define WRITE_RSR(SC,CID,NR,BEN,VAL)                                    \
582     do {                                                                \
583         if((NR) <= 7) {                                                 \
584                 WRITE_RCM(SC, HE_REGO_RSRA(0,CID,NR),BEN,VAL);          \
585         } else {                                                        \
586                 WRITE_RCM(SC, HE_REGO_RSRB((SC)->rsrb,CID,(NR-8)),BEN,VAL);\
587         }                                                               \
588     } while(0)
589
590 #ifdef HATM_DEBUG
591 #define DBG(SC, FL, PRINT) do {                                         \
592         if((SC)->debug & DBG_##FL) {                                    \
593                 if_printf((SC)->ifp, "%s: ", __func__);                 \
594                 printf PRINT;                                           \
595                 printf("\n");                                           \
596         }                                                               \
597     } while (0)
598
599 enum {
600         DBG_DUMMY       = 0x0001,       /* default value for -DHATM_DEBUG */
601         DBG_RX          = 0x0002,
602         DBG_TX          = 0x0004,
603         DBG_VCC         = 0x0008,
604         DBG_IOCTL       = 0x0010,
605         DBG_ATTACH      = 0x0020,
606         DBG_INTR        = 0x0040,
607         DBG_DMA         = 0x0080,
608         DBG_DMAH        = 0x0100,
609         DBG_DUMP        = 0x0200,
610
611         DBG_ALL         = 0x03ff
612 };
613
614 #else
615 #define DBG(SC, FL, PRINT)
616 #endif
617
618 u_int hatm_cps2atmf(uint32_t);
619 u_int hatm_atmf2cps(uint32_t);
620
621 void hatm_intr(void *);
622 int hatm_ioctl(struct ifnet *, u_long, caddr_t);
623 void hatm_initialize(struct hatm_softc *);
624 void hatm_stop(struct hatm_softc *sc);
625 void hatm_start(struct ifnet *);
626
627 void hatm_rx(struct hatm_softc *sc, u_int cid, u_int flags, struct mbuf *m,
628     u_int len);
629 void hatm_tx_complete(struct hatm_softc *sc, struct tpd *tpd, uint32_t);
630
631 int hatm_tx_vcc_can_open(struct hatm_softc *sc, u_int cid, struct hevcc *);
632 void hatm_tx_vcc_open(struct hatm_softc *sc, u_int cid);
633 void hatm_rx_vcc_open(struct hatm_softc *sc, u_int cid);
634 void hatm_tx_vcc_close(struct hatm_softc *sc, u_int cid);
635 void hatm_rx_vcc_close(struct hatm_softc *sc, u_int cid);
636 void hatm_tx_vcc_closed(struct hatm_softc *sc, u_int cid);
637 void hatm_vcc_closed(struct hatm_softc *sc, u_int cid);
638 void hatm_load_vc(struct hatm_softc *sc, u_int cid, int reopen);
639
640 void hatm_ext_free(struct mbufx_free **, struct mbufx_free *);