diff options
Diffstat (limited to 'sys/dev/hfa/fore_output.c')
-rw-r--r-- | sys/dev/hfa/fore_output.c | 479 |
1 files changed, 0 insertions, 479 deletions
diff --git a/sys/dev/hfa/fore_output.c b/sys/dev/hfa/fore_output.c deleted file mode 100644 index 3910186..0000000 --- a/sys/dev/hfa/fore_output.c +++ /dev/null @@ -1,479 +0,0 @@ -/*- - * - * =================================== - * HARP | Host ATM Research Platform - * =================================== - * - * - * This Host ATM Research Platform ("HARP") file (the "Software") is - * made available by Network Computing Services, Inc. ("NetworkCS") - * "AS IS". NetworkCS does not provide maintenance, improvements or - * support of any kind. - * - * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED, - * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE - * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE. - * In no event shall NetworkCS be responsible for any damages, including - * but not limited to consequential damages, arising from or relating to - * any use of the Software or related support. - * - * Copyright 1994-1998 Network Computing Services, Inc. - * - * Copies of this Software may be made, however, the above copyright - * notice must be reproduced on all copies. - * - * @(#) $FreeBSD$ - * - */ - -/* - * FORE Systems 200-Series Adapter Support - * --------------------------------------- - * - * PDU output processing - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/socketvar.h> -#include <vm/vm.h> -#include <vm/pmap.h> -#include <net/if.h> -#include <netatm/port.h> -#include <netatm/queue.h> -#include <netatm/atm.h> -#include <netatm/atm_sys.h> -#include <netatm/atm_sap.h> -#include <netatm/atm_cm.h> -#include <netatm/atm_if.h> -#include <netatm/atm_vc.h> -#include <netatm/atm_stack.h> -#include <netatm/atm_pcb.h> -#include <netatm/atm_var.h> -#include <dev/pci/pcivar.h> -#include <dev/hfa/fore.h> -#include <dev/hfa/fore_aali.h> -#include <dev/hfa/fore_slave.h> -#include <dev/hfa/fore_stats.h> -#include <dev/hfa/fore_var.h> -#include <dev/hfa/fore_include.h> - -#ifndef lint -__RCSID("@(#) $FreeBSD$"); -#endif - - -/* - * Local functions - */ -static KBuffer * fore_xmit_segment(Fore_unit *, KBuffer *, - H_xmit_queue *, int *, int *); -static void fore_seg_dma_free(H_xmit_queue *, KBuffer *, int); - - -/* - * Output a PDU - * - * This function is called via the common driver code after receiving a - * stack *_DATA* command. The common code has already validated most of - * the request so we just need to check a few more Fore-specific details. - * Then we just build a transmit descriptor request for the PDU and issue - * the command to the CP. - * - * Arguments: - * cup pointer to device common unit - * cvp pointer to common VCC entry - * m pointer to output PDU buffer chain head - * - * Returns: - * none - * - */ -void -fore_output(cup, cvp, m) - Cmn_unit *cup; - Cmn_vcc *cvp; - KBuffer *m; -{ - Fore_unit *fup = (Fore_unit *)cup; - Fore_vcc *fvp = (Fore_vcc *)cvp; - struct vccb *vcp; - H_xmit_queue *hxp; - Xmit_queue *cqp; - Xmit_descr *xdp; - int retry, nsegs, pdulen; - int s; - -#ifdef DIAGNOSTIC - if (atm_dev_print) - atm_dev_pdu_print(cup, cvp, m, "fore_output"); -#endif - - vcp = fvp->fv_connvc->cvc_vcc; - - /* - * If we're still waiting for activation to finish, delay for - * a little while before we toss the PDU - */ - if (fvp->fv_state == CVS_INITED) { - retry = 3; - while (retry-- && (fvp->fv_state == CVS_INITED)) - DELAY(1000); - if (fvp->fv_state != CVS_ACTIVE) { - /* - * Activation still hasn't finished, oh well.... - */ - fup->fu_stats->st_drv.drv_xm_notact++; - vcp->vc_oerrors++; - if (vcp->vc_nif) - ANIF2IFP(vcp->vc_nif)->if_oerrors++; - KB_FREEALL(m); - return; - } - } - - /* - * Queue PDU at end of transmit queue - * - * If queue is full we'll delay a bit before tossing the PDU - */ - s = splnet(); - hxp = fup->fu_xmit_tail; - if (!((*hxp->hxq_status) & QSTAT_FREE)) { - - fup->fu_stats->st_drv.drv_xm_full++; - retry = 3; - do { - DELAY(1000); - - DEVICE_LOCK((Cmn_unit *)fup); - fore_xmit_drain(fup); - DEVICE_UNLOCK((Cmn_unit *)fup); - - } while (--retry && (!((*hxp->hxq_status) & QSTAT_FREE))); - - if (!((*hxp->hxq_status) & QSTAT_FREE)) { - /* - * Queue is still full, bye-bye PDU - */ - fup->fu_pif.pif_oerrors++; - vcp->vc_oerrors++; - if (vcp->vc_nif) - ANIF2IFP(vcp->vc_nif)->if_oerrors++; - KB_FREEALL(m); - (void) splx(s); - return; - } - } - - /* - * We've got a free transmit queue entry - */ - - /* - * Now build the transmit segment descriptors for this PDU - */ - m = fore_xmit_segment(fup, m, hxp, &nsegs, &pdulen); - if (m == NULL) { - /* - * The build failed, buffer chain has been freed - */ - vcp->vc_oerrors++; - if (vcp->vc_nif) - ANIF2IFP(vcp->vc_nif)->if_oerrors++; - (void) splx(s); - return; - } - - /* - * Set up the descriptor header - */ - xdp = hxp->hxq_descr; - xdp->xd_cell_hdr = ATM_HDR_SET(vcp->vc_vpi, vcp->vc_vci, 0, 0); - xdp->xd_spec = XDS_SET_SPEC(0, fvp->fv_aal, nsegs, pdulen); - xdp->xd_rate = fvp->rate; - - /* - * Everything is ready to go, so officially claim the host queue - * entry and setup the CP-resident queue entry. The CP will grab - * the PDU when the descriptor pointer is set. - */ - fup->fu_xmit_tail = hxp->hxq_next; - hxp->hxq_buf = m; - hxp->hxq_vcc = fvp; - (*hxp->hxq_status) = QSTAT_PENDING; - cqp = hxp->hxq_cpelem; - cqp->cq_descr = (CP_dma) - CP_WRITE((u_long)hxp->hxq_descr_dma | XMIT_SEGS_TO_BLKS(nsegs)); - - (void) splx(s); - - /* - * See if there are any completed queue entries - */ - DEVICE_LOCK((Cmn_unit *)fup); - fore_xmit_drain(fup); - DEVICE_UNLOCK((Cmn_unit *)fup); - - return; -} - - -/* - * Build Transmit Segment Descriptors - * - * This function will take a supplied buffer chain of data to be transmitted - * and build the transmit segment descriptors for the data. This will include - * the dreaded operation of ensuring that the data for each transmit segment - * is full-word aligned and (except for the last segment) is an integral number - * of words in length. If the data isn't already aligned and sized as - * required, then the data must be shifted (copied) into place - a sure - * performance killer. Note that we rely on the fact that all buffer data - * areas are allocated with (at least) full-word alignments/lengths. - * - * If any errors are encountered, the buffer chain will be freed. - * - * Arguments: - * fup pointer to device unit - * m pointer to output PDU buffer chain head - * hxp pointer to host transmit queue entry - * segp pointer to return the number of transmit segments - * lenp pointer to return the pdu length - * - * Returns: - * m build successful, pointer to (possibly new) head of - * output PDU buffer chain - * NULL build failed, buffer chain freed - * - */ -static KBuffer * -fore_xmit_segment(fup, m, hxp, segp, lenp) - Fore_unit *fup; - KBuffer *m; - H_xmit_queue *hxp; - int *segp; - int *lenp; -{ - Xmit_descr *xdp = hxp->hxq_descr; - Xmit_seg_descr *xsp; - H_dma *sdmap; - KBuffer *m0, *m1, *mprev; - caddr_t cp, bfr; - vm_paddr_t dma; - int pdulen, nsegs, len, align; - int compressed = 0; - - m0 = m; - -retry: - xsp = xdp->xd_seg; - sdmap = hxp->hxq_dma; - mprev = NULL; - pdulen = 0; - nsegs = 0; - - /* - * Loop thru each buffer in the chain, performing the necessary - * data positioning and then building a segment descriptor for - * that data. - */ - while (m) { - /* - * Get rid of any zero-length buffers - */ - if (KB_LEN(m) == 0) { - if (mprev) { - KB_UNLINK(m, mprev, m1); - } else { - KB_UNLINKHEAD(m, m1); - m0 = m1; - } - m = m1; - continue; - } - - /* - * Make sure we don't try to use too many segments - */ - if (nsegs >= XMIT_MAX_SEGS) { - /* - * First, free already allocated DMA addresses - */ - fore_seg_dma_free(hxp, m0, nsegs); - - /* - * Try to compress buffer chain (but only once) - */ - if (compressed) { - KB_FREEALL(m0); - return (NULL); - } - - fup->fu_stats->st_drv.drv_xm_maxpdu++; - - m = atm_dev_compress(m0); - if (m == NULL) { - return (NULL); - } - - /* - * Build segment descriptors for compressed chain - */ - m0 = m; - compressed = 1; - goto retry; - } - - /* - * Get start of data onto full-word alignment - */ - KB_DATASTART(m, cp, caddr_t); - if ((align = ((uintptr_t)cp) & (XMIT_SEG_ALIGN - 1)) != 0) { - /* - * Gotta slide the data up - */ - fup->fu_stats->st_drv.drv_xm_segnoal++; - bfr = cp - align; - bcopy(cp, bfr, KB_LEN(m)); - KB_HEADMOVE(m, -align); - } else { - /* - * Data already aligned - */ - bfr = cp; - } - - /* - * Now work on getting the data length correct - */ - len = KB_LEN(m); - while ((align = (len & (XMIT_SEG_ALIGN - 1))) && - (m1 = KB_NEXT(m))) { - - /* - * Have to move some data from following buffer(s) - * to word-fill this buffer - */ - int ncopy = MIN(XMIT_SEG_ALIGN - align, KB_LEN(m1)); - - if (ncopy) { - /* - * Move data to current buffer - */ - caddr_t dest; - - fup->fu_stats->st_drv.drv_xm_seglen++; - KB_DATASTART(m1, cp, caddr_t); - dest = bfr + len; - KB_HEADADJ(m1, -ncopy); - KB_TAILADJ(m, ncopy); - len += ncopy; - while (ncopy--) { - *dest++ = *cp++; - } - } - - /* - * If we've drained the buffer, free it - */ - if (KB_LEN(m1) == 0) { - KBuffer *m2; - - KB_UNLINK(m1, m, m2); - } - } - - /* - * Finally, build the segment descriptor - */ - - /* - * Round last segment to fullword length (if needed) - */ - if (len & (XMIT_SEG_ALIGN - 1)) - xsp->xsd_len = KB_LEN(m) = - (len + XMIT_SEG_ALIGN) & ~(XMIT_SEG_ALIGN - 1); - else - xsp->xsd_len = KB_LEN(m) = len; - - /* - * Get a DMA address for the data - */ - dma = vtophys(bfr); - if (dma == 0) { - fup->fu_stats->st_drv.drv_xm_segdma++; - fore_seg_dma_free(hxp, m0, nsegs); - KB_FREEALL(m0); - return (NULL); - } - - /* - * Now we're really ready to call it a segment - */ - *sdmap++ = xsp->xsd_buffer = (H_dma) dma; - - /* - * Bump counters and get ready for next buffer - */ - pdulen += len; - nsegs++; - xsp++; - mprev = m; - m = KB_NEXT(m); - } - - /* - * Validate PDU length - */ - if (pdulen > XMIT_MAX_PDULEN) { - fup->fu_stats->st_drv.drv_xm_maxpdu++; - fore_seg_dma_free(hxp, m0, nsegs); - KB_FREEALL(m0); - return (NULL); - } - - /* - * Return the good news to the caller - */ - *segp = nsegs; - *lenp = pdulen; - - return (m0); -} - - -/* - * Free Transmit Segment Queue DMA addresses - * - * Arguments: - * hxp pointer to host transmit queue entry - * m0 pointer to output PDU buffer chain head - * nsegs number of processed transmit segments - * - * Returns: - * none - * - */ -static void -fore_seg_dma_free(hxp, m0, nsegs) - H_xmit_queue *hxp; - KBuffer *m0; - int nsegs; -{ - KBuffer *m = m0; - H_dma *sdmap = hxp->hxq_dma; - caddr_t cp; - int i; - - for (i = 0; i < nsegs; i++) { - KB_DATASTART(m, cp, caddr_t); - m = KB_NEXT(m); - sdmap++; - } -} - |