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)
86 * Allocate non-cacheable memory for transmit status words
88 memp = atm_dev_alloc(sizeof(Q_status) * XMIT_QUELEN,
89 QSTAT_ALIGN, ATM_DEV_NONCACHE);
93 fup->fu_xmit_stat = (Q_status *) memp;
95 memp = (void *)vtophys(fup->fu_xmit_stat);
99 fup->fu_xmit_statd = (Q_status *) memp;
102 * Allocate memory for transmit descriptors
104 * We will allocate the transmit descriptors individually rather than
105 * as a single memory block, which will often be larger than a memory
106 * page. On some systems (eg. FreeBSD) the physical addresses of
107 * adjacent virtual memory pages are not contiguous.
109 hxp = fup->fu_xmit_q;
110 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
113 * Allocate a transmit descriptor for this queue entry
115 hxp->hxq_descr = atm_dev_alloc(sizeof(Xmit_descr),
116 XMIT_DESCR_ALIGN, 0);
117 if (hxp->hxq_descr == NULL) {
121 hxp->hxq_descr_dma = (Xmit_descr *)vtophys(hxp->hxq_descr);
122 if (hxp->hxq_descr_dma == NULL) {
132 * Transmit Queue Initialization
134 * Allocate and initialize the host-resident transmit queue structures
135 * and then initialize the CP-resident queue structures.
137 * Called at interrupt level.
140 * fup pointer to device unit structure
146 fore_xmit_initialize(fup)
149 Aali *aap = fup->fu_aali;
157 * Point to CP-resident transmit queue
159 cqp = (Xmit_queue *)(fup->fu_ram + CP_READ(aap->aali_xmit_q));
162 * Point to host-resident transmit queue structures
164 hxp = fup->fu_xmit_q;
165 qsp = fup->fu_xmit_stat;
166 qsp_dma = fup->fu_xmit_statd;
169 * Loop thru all queue entries and do whatever needs doing
171 for (i = 0; i < XMIT_QUELEN; i++) {
174 * Set queue status word to free
179 * Set up host queue entry and link into ring
181 hxp->hxq_cpelem = cqp;
182 hxp->hxq_status = qsp;
183 if (i == (XMIT_QUELEN - 1))
184 hxp->hxq_next = fup->fu_xmit_q;
186 hxp->hxq_next = hxp + 1;
189 * Now let the CP into the game
191 cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);
194 * Bump all queue pointers
203 * Initialize queue pointers
205 fup->fu_xmit_head = fup->fu_xmit_tail = fup->fu_xmit_q;
212 * Drain Transmit Queue
214 * This function will free all completed entries at the head of the
215 * transmit queue. Freeing the entry includes releasing the transmit
216 * buffers (buffer chain) back to the kernel.
218 * May be called in interrupt state.
219 * Must be called with interrupts locked out.
222 * fup pointer to device unit structure
238 * Process each completed entry
240 while (*fup->fu_xmit_head->hxq_status & QSTAT_COMPLETED) {
242 hxp = fup->fu_xmit_head;
245 * Release the entry's DMA addresses and buffer chain
247 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
248 m = KB_NEXT(m), sdmap++) {
251 KB_DATASTART(m, cp, caddr_t);
253 KB_FREEALL(hxp->hxq_buf);
256 * Get VCC over which data was sent (may be null if
257 * VCC has been closed in the meantime)
262 * Now collect some statistics
264 if (*hxp->hxq_status & QSTAT_ERROR) {
266 * CP ran into problems, not much we can do
267 * other than record the event
269 fup->fu_pif.pif_oerrors++;
271 vcp = fvp->fv_connvc->cvc_vcc;
274 vcp->vc_nif->nif_if.if_oerrors++;
280 int len = XDS_GET_LEN(hxp->hxq_descr->xd_spec);
282 fup->fu_pif.pif_opdus++;
283 fup->fu_pif.pif_obytes += len;
285 vcp = fvp->fv_connvc->cvc_vcc;
287 vcp->vc_obytes += len;
289 vcp->vc_nif->nif_obytes += len;
290 vcp->vc_nif->nif_if.if_opackets++;
291 #if (defined(BSD) && (BSD >= 199103))
292 vcp->vc_nif->nif_if.if_obytes += len;
299 * Mark this entry free for use and bump head pointer
300 * to the next entry in the queue
302 *hxp->hxq_status = QSTAT_FREE;
303 fup->fu_xmit_head = hxp->hxq_next;
311 * Free Transmit Queue Data Structures
314 * fup pointer to device unit structure
329 * Free any transmit buffers left on the queue
331 if (fup->fu_flags & CUF_INITED) {
332 while (*fup->fu_xmit_head->hxq_status != QSTAT_FREE) {
334 hxp = fup->fu_xmit_head;
337 * Release the entry's DMA addresses and buffer chain
339 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
340 m = KB_NEXT(m), sdmap++) {
343 KB_DATASTART(m, cp, caddr_t);
345 KB_FREEALL(hxp->hxq_buf);
347 *hxp->hxq_status = QSTAT_FREE;
348 fup->fu_xmit_head = hxp->hxq_next;
353 * Free the status words
355 if (fup->fu_xmit_stat) {
356 atm_dev_free((volatile void *)fup->fu_xmit_stat);
357 fup->fu_xmit_stat = NULL;
358 fup->fu_xmit_statd = NULL;
362 * Free the transmit descriptors
364 hxp = fup->fu_xmit_q;
365 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
368 * Free the transmit descriptor for this queue entry
370 if (hxp->hxq_descr_dma) {
371 hxp->hxq_descr_dma = NULL;
374 if (hxp->hxq_descr) {
375 atm_dev_free(hxp->hxq_descr);
376 hxp->hxq_descr = NULL;