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 $
31 * FORE Systems 200-Series Adapter Support
32 * ---------------------------------------
34 * Transmit queue management
38 #include <dev/hfa/fore_include.h>
41 __RCSID("@(#) $FreeBSD: src/sys/dev/hfa/fore_transmit.c,v 1.4 1999/08/28 00:41:53 peter Exp $");
46 * Allocate Transmit Queue Data Structures
49 * fup pointer to device unit structure
52 * 0 allocations successful
53 * else allocation failed
56 fore_xmit_allocate(fup)
64 * Allocate non-cacheable memory for transmit status words
66 memp = atm_dev_alloc(sizeof(Q_status) * XMIT_QUELEN,
67 QSTAT_ALIGN, ATM_DEV_NONCACHE);
71 fup->fu_xmit_stat = (Q_status *) memp;
73 memp = DMA_GET_ADDR(fup->fu_xmit_stat, sizeof(Q_status) * XMIT_QUELEN,
74 QSTAT_ALIGN, ATM_DEV_NONCACHE);
78 fup->fu_xmit_statd = (Q_status *) memp;
81 * Allocate memory for transmit descriptors
83 * We will allocate the transmit descriptors individually rather than
84 * as a single memory block, which will often be larger than a memory
85 * page. On some systems (eg. FreeBSD) the physical addresses of
86 * adjacent virtual memory pages are not contiguous.
89 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
92 * Allocate a transmit descriptor for this queue entry
94 hxp->hxq_descr = atm_dev_alloc(sizeof(Xmit_descr),
96 if (hxp->hxq_descr == NULL) {
100 hxp->hxq_descr_dma = DMA_GET_ADDR(hxp->hxq_descr,
101 sizeof(Xmit_descr), XMIT_DESCR_ALIGN, 0);
102 if (hxp->hxq_descr_dma == NULL) {
112 * Transmit Queue Initialization
114 * Allocate and initialize the host-resident transmit queue structures
115 * and then initialize the CP-resident queue structures.
117 * Called at interrupt level.
120 * fup pointer to device unit structure
126 fore_xmit_initialize(fup)
129 Aali *aap = fup->fu_aali;
137 * Point to CP-resident transmit queue
139 cqp = (Xmit_queue *)(fup->fu_ram + CP_READ(aap->aali_xmit_q));
142 * Point to host-resident transmit queue structures
144 hxp = fup->fu_xmit_q;
145 qsp = fup->fu_xmit_stat;
146 qsp_dma = fup->fu_xmit_statd;
149 * Loop thru all queue entries and do whatever needs doing
151 for (i = 0; i < XMIT_QUELEN; i++) {
154 * Set queue status word to free
159 * Set up host queue entry and link into ring
161 hxp->hxq_cpelem = cqp;
162 hxp->hxq_status = qsp;
163 if (i == (XMIT_QUELEN - 1))
164 hxp->hxq_next = fup->fu_xmit_q;
166 hxp->hxq_next = hxp + 1;
169 * Now let the CP into the game
171 cqp->cq_status = (CP_dma) CP_WRITE(qsp_dma);
174 * Bump all queue pointers
183 * Initialize queue pointers
185 fup->fu_xmit_head = fup->fu_xmit_tail = fup->fu_xmit_q;
192 * Drain Transmit Queue
194 * This function will free all completed entries at the head of the
195 * transmit queue. Freeing the entry includes releasing the transmit
196 * buffers (buffer chain) back to the kernel.
198 * May be called in interrupt state.
199 * Must be called with interrupts locked out.
202 * fup pointer to device unit structure
218 * Process each completed entry
220 while (*fup->fu_xmit_head->hxq_status & QSTAT_COMPLETED) {
222 hxp = fup->fu_xmit_head;
225 * Release the entry's DMA addresses and buffer chain
227 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
228 m = KB_NEXT(m), sdmap++) {
231 KB_DATASTART(m, cp, caddr_t);
232 DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0);
234 KB_FREEALL(hxp->hxq_buf);
237 * Get VCC over which data was sent (may be null if
238 * VCC has been closed in the meantime)
243 * Now collect some statistics
245 if (*hxp->hxq_status & QSTAT_ERROR) {
247 * CP ran into problems, not much we can do
248 * other than record the event
250 fup->fu_pif.pif_oerrors++;
252 vcp = fvp->fv_connvc->cvc_vcc;
255 vcp->vc_nif->nif_if.if_oerrors++;
261 int len = XDS_GET_LEN(hxp->hxq_descr->xd_spec);
263 fup->fu_pif.pif_opdus++;
264 fup->fu_pif.pif_obytes += len;
266 vcp = fvp->fv_connvc->cvc_vcc;
268 vcp->vc_obytes += len;
270 vcp->vc_nif->nif_obytes += len;
271 vcp->vc_nif->nif_if.if_opackets++;
272 #if (defined(BSD) && (BSD >= 199103))
273 vcp->vc_nif->nif_if.if_obytes += len;
280 * Mark this entry free for use and bump head pointer
281 * to the next entry in the queue
283 *hxp->hxq_status = QSTAT_FREE;
284 fup->fu_xmit_head = hxp->hxq_next;
292 * Free Transmit Queue Data Structures
295 * fup pointer to device unit structure
310 * Free any transmit buffers left on the queue
312 if (fup->fu_flags & CUF_INITED) {
313 while (*fup->fu_xmit_head->hxq_status != QSTAT_FREE) {
315 hxp = fup->fu_xmit_head;
318 * Release the entry's DMA addresses and buffer chain
320 for (m = hxp->hxq_buf, sdmap = hxp->hxq_dma; m;
321 m = KB_NEXT(m), sdmap++) {
324 KB_DATASTART(m, cp, caddr_t);
325 DMA_FREE_ADDR(cp, *sdmap, KB_LEN(m), 0);
327 KB_FREEALL(hxp->hxq_buf);
329 *hxp->hxq_status = QSTAT_FREE;
330 fup->fu_xmit_head = hxp->hxq_next;
335 * Free the status words
337 if (fup->fu_xmit_stat) {
338 if (fup->fu_xmit_statd) {
339 DMA_FREE_ADDR(fup->fu_xmit_stat, fup->fu_xmit_statd,
340 sizeof(Q_status) * XMIT_QUELEN,
343 atm_dev_free((volatile void *)fup->fu_xmit_stat);
344 fup->fu_xmit_stat = NULL;
345 fup->fu_xmit_statd = NULL;
349 * Free the transmit descriptors
351 hxp = fup->fu_xmit_q;
352 for (i = 0; i < XMIT_QUELEN; i++, hxp++) {
355 * Free the transmit descriptor for this queue entry
357 if (hxp->hxq_descr_dma) {
358 DMA_FREE_ADDR(hxp->hxq_descr, hxp->hxq_descr_dma,
359 sizeof(Xmit_descr), 0);
360 hxp->hxq_descr_dma = NULL;
363 if (hxp->hxq_descr) {
364 atm_dev_free(hxp->hxq_descr);
365 hxp->hxq_descr = NULL;