2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
6 * This Host ATM Research Platform ("HARP") file (the "Software") is
7 * made available by Network Computing Services, Inc. ("NetworkCS")
8 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
12 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
14 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
15 * In no event shall NetworkCS be responsible for any damages, including
16 * but not limited to consequential damages, arising from or relating to
17 * any use of the Software or related support.
19 * Copyright 1994-1998 Network Computing Services, Inc.
21 * Copies of this Software may be made, however, the above copyright
22 * notice must be reproduced on all copies.
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
29 * FORE Systems 200-Series Adapter Support
30 * ---------------------------------------
32 * Transmit queue management
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/socket.h>
39 #include <sys/socketvar.h>
43 #include <netatm/port.h>
44 #include <netatm/queue.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_sys.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_cm.h>
49 #include <netatm/atm_if.h>
50 #include <netatm/atm_vc.h>
51 #include <netatm/atm_stack.h>
52 #include <netatm/atm_pcb.h>
53 #include <netatm/atm_var.h>
54 #include <dev/pci/pcivar.h>
55 #include <dev/hfa/fore.h>
56 #include <dev/hfa/fore_aali.h>
57 #include <dev/hfa/fore_slave.h>
58 #include <dev/hfa/fore_stats.h>
59 #include <dev/hfa/fore_var.h>
60 #include <dev/hfa/fore_include.h>
63 __RCSID("@(#) $FreeBSD$");
68 * Allocate Transmit Queue Data Structures
71 * fup pointer to device unit structure
74 * 0 allocations successful
75 * else allocation failed
78 fore_xmit_allocate(fup)
87 * Allocate non-cacheable memory for transmit status words
89 memp = atm_dev_alloc(sizeof(Q_status) * XMIT_QUELEN,
90 QSTAT_ALIGN, ATM_DEV_NONCACHE);
94 fup->fu_xmit_stat = (Q_status *) memp;
96 pmemp = vtophys(fup->fu_xmit_stat);
100 fup->fu_xmit_statd = pmemp;
103 * Allocate memory for transmit descriptors
105 * We will allocate the transmit descriptors individually rather than
106 * as a single memory block, which will often be larger than a memory
107 * page. On some systems (eg. FreeBSD) the physical addresses of
108 * adjacent virtual memory pages are not contiguous.
110 hxp = fup->fu_xmit_q;
111 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
114 * Allocate a transmit descriptor for this queue entry
116 hxp->hxq_descr = atm_dev_alloc(sizeof(Xmit_descr),
117 XMIT_DESCR_ALIGN, 0);
118 if (hxp->hxq_descr == NULL) {
122 hxp->hxq_descr_dma = vtophys(hxp->hxq_descr);
123 if (hxp->hxq_descr_dma == 0) {
133 * Transmit Queue Initialization
135 * Allocate and initialize the host-resident transmit queue structures
136 * and then initialize the CP-resident queue structures.
138 * Called at interrupt level.
141 * fup pointer to device unit structure
147 fore_xmit_initialize(fup)
150 Aali *aap = fup->fu_aali;
158 * Point to CP-resident transmit queue
160 cqp = (Xmit_queue *)(fup->fu_ram + CP_READ(aap->aali_xmit_q));
163 * Point to host-resident transmit queue structures
165 hxp = fup->fu_xmit_q;
166 qsp = fup->fu_xmit_stat;
167 qsp_dma = fup->fu_xmit_statd;
170 * Loop thru all queue entries and do whatever needs doing
172 for (i = 0; i < XMIT_QUELEN; i++) {
175 * Set queue status word to free
180 * Set up host queue entry and link into ring
182 hxp->hxq_cpelem = cqp;
183 hxp->hxq_status = qsp;
184 if (i == (XMIT_QUELEN - 1))
185 hxp->hxq_next = fup->fu_xmit_q;
187 hxp->hxq_next = hxp + 1;
190 * Now let the CP into the game
192 cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);
195 * Bump all queue pointers
199 qsp_dma += sizeof(Q_status);
204 * Initialize queue pointers
206 fup->fu_xmit_head = fup->fu_xmit_tail = fup->fu_xmit_q;
213 * Drain Transmit Queue
215 * This function will free all completed entries at the head of the
216 * transmit queue. Freeing the entry includes releasing the transmit
217 * buffers (buffer chain) back to the kernel.
219 * May be called in interrupt state.
220 * Must be called with interrupts locked out.
223 * fup pointer to device unit structure
239 * Process each completed entry
241 while (*fup->fu_xmit_head->hxq_status & QSTAT_COMPLETED) {
243 hxp = fup->fu_xmit_head;
246 * Release the entry's DMA addresses and buffer chain
248 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
249 m = KB_NEXT(m), sdmap++) {
252 KB_DATASTART(m, cp, caddr_t);
254 KB_FREEALL(hxp->hxq_buf);
257 * Get VCC over which data was sent (may be null if
258 * VCC has been closed in the meantime)
263 * Now collect some statistics
265 if (*hxp->hxq_status & QSTAT_ERROR) {
267 * CP ran into problems, not much we can do
268 * other than record the event
270 fup->fu_pif.pif_oerrors++;
272 vcp = fvp->fv_connvc->cvc_vcc;
275 vcp->vc_nif->nif_if.if_oerrors++;
281 int len = XDS_GET_LEN(hxp->hxq_descr->xd_spec);
283 fup->fu_pif.pif_opdus++;
284 fup->fu_pif.pif_obytes += len;
286 vcp = fvp->fv_connvc->cvc_vcc;
288 vcp->vc_obytes += len;
290 vcp->vc_nif->nif_obytes += len;
291 vcp->vc_nif->nif_if.if_opackets++;
292 #if (defined(BSD) && (BSD >= 199103))
293 vcp->vc_nif->nif_if.if_obytes += len;
300 * Mark this entry free for use and bump head pointer
301 * to the next entry in the queue
303 *hxp->hxq_status = QSTAT_FREE;
304 fup->fu_xmit_head = hxp->hxq_next;
312 * Free Transmit Queue Data Structures
315 * fup pointer to device unit structure
330 * Free any transmit buffers left on the queue
332 if (fup->fu_flags & CUF_INITED) {
333 while (*fup->fu_xmit_head->hxq_status != QSTAT_FREE) {
335 hxp = fup->fu_xmit_head;
338 * Release the entry's DMA addresses and buffer chain
340 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
341 m = KB_NEXT(m), sdmap++) {
344 KB_DATASTART(m, cp, caddr_t);
346 KB_FREEALL(hxp->hxq_buf);
348 *hxp->hxq_status = QSTAT_FREE;
349 fup->fu_xmit_head = hxp->hxq_next;
354 * Free the status words
356 if (fup->fu_xmit_stat) {
357 atm_dev_free((volatile void *)fup->fu_xmit_stat);
358 fup->fu_xmit_stat = NULL;
359 fup->fu_xmit_statd = 0;
363 * Free the transmit descriptors
365 hxp = fup->fu_xmit_q;
366 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
369 * Free the transmit descriptor for this queue entry
371 if (hxp->hxq_descr_dma) {
372 hxp->hxq_descr_dma = 0;
375 if (hxp->hxq_descr) {
376 atm_dev_free(hxp->hxq_descr);
377 hxp->hxq_descr = NULL;