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