summaryrefslogtreecommitdiffstats
path: root/sys/dev/hfa/fore_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hfa/fore_output.c')
-rw-r--r--sys/dev/hfa/fore_output.c479
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++;
- }
-}
-
OpenPOWER on IntegriCloud