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.3 2003/08/07 21:16:49 dillon 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(fup)
59 * Allocate non-cacheable memory for transmit status words
61 memp = atm_dev_alloc(sizeof(Q_status) * XMIT_QUELEN,
62 QSTAT_ALIGN, ATM_DEV_NONCACHE);
66 fup->fu_xmit_stat = (Q_status *) memp;
68 memp = DMA_GET_ADDR(fup->fu_xmit_stat, sizeof(Q_status) * XMIT_QUELEN,
69 QSTAT_ALIGN, ATM_DEV_NONCACHE);
73 fup->fu_xmit_statd = (Q_status *) memp;
76 * Allocate memory for transmit descriptors
78 * We will allocate the transmit descriptors individually rather than
79 * as a single memory block, which will often be larger than a memory
80 * page. On some systems (eg. FreeBSD) the physical addresses of
81 * adjacent virtual memory pages are not contiguous.
84 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
87 * Allocate a transmit descriptor for this queue entry
89 hxp->hxq_descr = atm_dev_alloc(sizeof(Xmit_descr),
91 if (hxp->hxq_descr == NULL) {
95 hxp->hxq_descr_dma = DMA_GET_ADDR(hxp->hxq_descr,
96 sizeof(Xmit_descr), XMIT_DESCR_ALIGN, 0);
97 if (hxp->hxq_descr_dma == NULL) {
107 * Transmit Queue Initialization
109 * Allocate and initialize the host-resident transmit queue structures
110 * and then initialize the CP-resident queue structures.
112 * Called at interrupt level.
115 * fup pointer to device unit structure
121 fore_xmit_initialize(fup)
124 Aali *aap = fup->fu_aali;
132 * Point to CP-resident transmit queue
134 cqp = (Xmit_queue *)(fup->fu_ram + CP_READ(aap->aali_xmit_q));
137 * Point to host-resident transmit queue structures
139 hxp = fup->fu_xmit_q;
140 qsp = fup->fu_xmit_stat;
141 qsp_dma = fup->fu_xmit_statd;
144 * Loop thru all queue entries and do whatever needs doing
146 for (i = 0; i < XMIT_QUELEN; i++) {
149 * Set queue status word to free
154 * Set up host queue entry and link into ring
156 hxp->hxq_cpelem = cqp;
157 hxp->hxq_status = qsp;
158 if (i == (XMIT_QUELEN - 1))
159 hxp->hxq_next = fup->fu_xmit_q;
161 hxp->hxq_next = hxp + 1;
164 * Now let the CP into the game
166 cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);
169 * Bump all queue pointers
178 * Initialize queue pointers
180 fup->fu_xmit_head = fup->fu_xmit_tail = fup->fu_xmit_q;
187 * Drain Transmit Queue
189 * This function will free all completed entries at the head of the
190 * transmit queue. Freeing the entry includes releasing the transmit
191 * buffers (buffer chain) back to the kernel.
193 * May be called in interrupt state.
194 * Must be called with interrupts locked out.
197 * fup pointer to device unit structure
213 * Process each completed entry
215 while (*fup->fu_xmit_head->hxq_status & QSTAT_COMPLETED) {
217 hxp = fup->fu_xmit_head;
220 * Release the entry's DMA addresses and buffer chain
222 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
223 m = KB_NEXT(m), sdmap++) {
226 KB_DATASTART(m, cp, caddr_t);
227 DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0);
229 KB_FREEALL(hxp->hxq_buf);
232 * Get VCC over which data was sent (may be null if
233 * VCC has been closed in the meantime)
238 * Now collect some statistics
240 if (*hxp->hxq_status & QSTAT_ERROR) {
242 * CP ran into problems, not much we can do
243 * other than record the event
245 fup->fu_pif.pif_oerrors++;
247 vcp = fvp->fv_connvc->cvc_vcc;
250 vcp->vc_nif->nif_if.if_oerrors++;
256 int len = XDS_GET_LEN(hxp->hxq_descr->xd_spec);
258 fup->fu_pif.pif_opdus++;
259 fup->fu_pif.pif_obytes += len;
261 vcp = fvp->fv_connvc->cvc_vcc;
263 vcp->vc_obytes += len;
265 vcp->vc_nif->nif_obytes += len;
266 vcp->vc_nif->nif_if.if_opackets++;
267 #if (defined(BSD) && (BSD >= 199103))
268 vcp->vc_nif->nif_if.if_obytes += len;
275 * Mark this entry free for use and bump head pointer
276 * to the next entry in the queue
278 *hxp->hxq_status = QSTAT_FREE;
279 fup->fu_xmit_head = hxp->hxq_next;
287 * Free Transmit Queue Data Structures
290 * fup pointer to device unit structure
305 * Free any transmit buffers left on the queue
307 if (fup->fu_flags & CUF_INITED) {
308 while (*fup->fu_xmit_head->hxq_status != QSTAT_FREE) {
310 hxp = fup->fu_xmit_head;
313 * Release the entry's DMA addresses and buffer chain
315 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
316 m = KB_NEXT(m), sdmap++) {
319 KB_DATASTART(m, cp, caddr_t);
320 DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0);
322 KB_FREEALL(hxp->hxq_buf);
324 *hxp->hxq_status = QSTAT_FREE;
325 fup->fu_xmit_head = hxp->hxq_next;
330 * Free the status words
332 if (fup->fu_xmit_stat) {
333 if (fup->fu_xmit_statd) {
334 DMA_FREE_ADDR(fup->fu_xmit_stat, fup->fu_xmit_statd,
335 sizeof(Q_status) * XMIT_QUELEN,
338 atm_dev_free((volatile void *)fup->fu_xmit_stat);
339 fup->fu_xmit_stat = NULL;
340 fup->fu_xmit_statd = NULL;
344 * Free the transmit descriptors
346 hxp = fup->fu_xmit_q;
347 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
350 * Free the transmit descriptor for this queue entry
352 if (hxp->hxq_descr_dma) {
353 DMA_FREE_ADDR(hxp->hxq_descr, hxp->hxq_descr_dma,
354 sizeof(Xmit_descr), 0);
355 hxp->hxq_descr_dma = NULL;
358 if (hxp->hxq_descr) {
359 atm_dev_free(hxp->hxq_descr);
360 hxp->hxq_descr = NULL;