3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/dev/hfa/fore_transmit.c,v 1.4 1999/08/28 00:41:53 peter Exp $
27 * @(#) $DragonFly: src/sys/dev/atm/hfa/fore_transmit.c,v 1.5 2008/03/01 22:03:13 swildner Exp $
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
34 * Transmit queue management
38 #include "fore_include.h"
41 * Allocate Transmit Queue Data Structures
44 * fup pointer to device unit structure
47 * 0 allocations successful
48 * else allocation failed
51 fore_xmit_allocate(Fore_unit *fup)
58 * Allocate non-cacheable memory for transmit status words
60 memp = atm_dev_alloc(sizeof(Q_status) * XMIT_QUELEN,
61 QSTAT_ALIGN, ATM_DEV_NONCACHE);
65 fup->fu_xmit_stat = (Q_status *) memp;
67 memp = DMA_GET_ADDR(fup->fu_xmit_stat, sizeof(Q_status) * XMIT_QUELEN,
68 QSTAT_ALIGN, ATM_DEV_NONCACHE);
72 fup->fu_xmit_statd = (Q_status *) memp;
75 * Allocate memory for transmit descriptors
77 * We will allocate the transmit descriptors individually rather than
78 * as a single memory block, which will often be larger than a memory
79 * page. On some systems (eg. FreeBSD) the physical addresses of
80 * adjacent virtual memory pages are not contiguous.
83 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
86 * Allocate a transmit descriptor for this queue entry
88 hxp->hxq_descr = atm_dev_alloc(sizeof(Xmit_descr),
90 if (hxp->hxq_descr == NULL) {
94 hxp->hxq_descr_dma = DMA_GET_ADDR(hxp->hxq_descr,
95 sizeof(Xmit_descr), XMIT_DESCR_ALIGN, 0);
96 if (hxp->hxq_descr_dma == NULL) {
106 * Transmit Queue Initialization
108 * Allocate and initialize the host-resident transmit queue structures
109 * and then initialize the CP-resident queue structures.
111 * Called at interrupt level.
114 * fup pointer to device unit structure
120 fore_xmit_initialize(Fore_unit *fup)
122 Aali *aap = fup->fu_aali;
130 * Point to CP-resident transmit queue
132 cqp = (Xmit_queue *)(fup->fu_ram + CP_READ(aap->aali_xmit_q));
135 * Point to host-resident transmit queue structures
137 hxp = fup->fu_xmit_q;
138 qsp = fup->fu_xmit_stat;
139 qsp_dma = fup->fu_xmit_statd;
142 * Loop thru all queue entries and do whatever needs doing
144 for (i = 0; i < XMIT_QUELEN; i++) {
147 * Set queue status word to free
152 * Set up host queue entry and link into ring
154 hxp->hxq_cpelem = cqp;
155 hxp->hxq_status = qsp;
156 if (i == (XMIT_QUELEN - 1))
157 hxp->hxq_next = fup->fu_xmit_q;
159 hxp->hxq_next = hxp + 1;
162 * Now let the CP into the game
164 cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);
167 * Bump all queue pointers
176 * Initialize queue pointers
178 fup->fu_xmit_head = fup->fu_xmit_tail = fup->fu_xmit_q;
185 * Drain Transmit Queue
187 * This function will free all completed entries at the head of the
188 * transmit queue. Freeing the entry includes releasing the transmit
189 * buffers (buffer chain) back to the kernel.
191 * May be called in interrupt state.
192 * Must be called with interrupts locked out.
195 * fup pointer to device unit structure
201 fore_xmit_drain(Fore_unit *fup)
210 * Process each completed entry
212 while (*fup->fu_xmit_head->hxq_status & QSTAT_COMPLETED) {
214 hxp = fup->fu_xmit_head;
217 * Release the entry's DMA addresses and buffer chain
219 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
220 m = KB_NEXT(m), sdmap++) {
223 KB_DATASTART(m, cp, caddr_t);
224 DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0);
226 KB_FREEALL(hxp->hxq_buf);
229 * Get VCC over which data was sent (may be null if
230 * VCC has been closed in the meantime)
235 * Now collect some statistics
237 if (*hxp->hxq_status & QSTAT_ERROR) {
239 * CP ran into problems, not much we can do
240 * other than record the event
242 fup->fu_pif.pif_oerrors++;
244 vcp = fvp->fv_connvc->cvc_vcc;
247 vcp->vc_nif->nif_if.if_oerrors++;
253 int len = XDS_GET_LEN(hxp->hxq_descr->xd_spec);
255 fup->fu_pif.pif_opdus++;
256 fup->fu_pif.pif_obytes += len;
258 vcp = fvp->fv_connvc->cvc_vcc;
260 vcp->vc_obytes += len;
262 vcp->vc_nif->nif_obytes += len;
263 vcp->vc_nif->nif_if.if_opackets++;
264 vcp->vc_nif->nif_if.if_obytes += len;
270 * Mark this entry free for use and bump head pointer
271 * to the next entry in the queue
273 *hxp->hxq_status = QSTAT_FREE;
274 fup->fu_xmit_head = hxp->hxq_next;
282 * Free Transmit Queue Data Structures
285 * fup pointer to device unit structure
291 fore_xmit_free(Fore_unit *fup)
299 * Free any transmit buffers left on the queue
301 if (fup->fu_flags & CUF_INITED) {
302 while (*fup->fu_xmit_head->hxq_status != QSTAT_FREE) {
304 hxp = fup->fu_xmit_head;
307 * Release the entry's DMA addresses and buffer chain
309 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
310 m = KB_NEXT(m), sdmap++) {
313 KB_DATASTART(m, cp, caddr_t);
314 DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0);
316 KB_FREEALL(hxp->hxq_buf);
318 *hxp->hxq_status = QSTAT_FREE;
319 fup->fu_xmit_head = hxp->hxq_next;
324 * Free the status words
326 if (fup->fu_xmit_stat) {
327 if (fup->fu_xmit_statd) {
328 DMA_FREE_ADDR(fup->fu_xmit_stat, fup->fu_xmit_statd,
329 sizeof(Q_status) * XMIT_QUELEN,
332 atm_dev_free((volatile void *)fup->fu_xmit_stat);
333 fup->fu_xmit_stat = NULL;
334 fup->fu_xmit_statd = NULL;
338 * Free the transmit descriptors
340 hxp = fup->fu_xmit_q;
341 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
344 * Free the transmit descriptor for this queue entry
346 if (hxp->hxq_descr_dma) {
347 DMA_FREE_ADDR(hxp->hxq_descr, hxp->hxq_descr_dma,
348 sizeof(Xmit_descr), 0);
349 hxp->hxq_descr_dma = NULL;
352 if (hxp->hxq_descr) {
353 atm_dev_free(hxp->hxq_descr);
354 hxp->hxq_descr = NULL;