import Chuck Cranor's ATM driver

This commit is contained in:
Kenjiro Cho 1997-05-09 07:48:14 +00:00
parent 3cc5346fb1
commit 413fe3928f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/CRANOR/; revision=25603
12 changed files with 5746 additions and 0 deletions

348
sys/dev/en/if_en_pci.c Normal file
View File

@ -0,0 +1,348 @@
/* $NetBSD: if_en_pci.c,v 1.1 1996/06/22 02:00:31 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
*
* i f _ e n _ p c i . c
*
* author: Chuck Cranor <chuck@ccrc.wustl.edu>
* started: spring, 1996.
*
* FreeBSD PCI glue for the eni155p card.
* thanks to Matt Thomas for figuring out FreeBSD vs NetBSD vs etc.. diffs.
*/
#include "en.h"
#include "pci.h"
#if (NEN > 0) && (NPCI > 0)
#include <sys/param.h>
#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#ifndef SHUTDOWN_PRE_SYNC
/*
* device shutdown mechanism has been changed since 2.2-ALPHA.
* if SHUTDOWN_PRE_SYNC is defined in "sys/systm.h", use new one.
* otherwise, use old one.
* new: 2.2-ALPHA, 2.2-BETA, 2.2-GAMME, 2.2-RELEASE, 3.0
* old: 2.1.5, 2.1.6, 2.2-SNAP
* -- kjc
*/
#include <sys/devconf.h>
#endif
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <machine/cpufunc.h> /* for rdtsc proto for clock.h below */
#include <machine/clock.h> /* for DELAY */
#include <net/if.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
#include <dev/en/midwayreg.h>
#include <dev/en/midwayvar.h>
/*
* prototypes
*/
static void en_pci_attach __P((pcici_t, int));
static char *en_pci_probe __P((pcici_t, pcidi_t));
#ifdef SHUTDOWN_PRE_SYNC
static void en_pci_shutdown __P((int, void *));
#else
static int en_pci_shutdown __P((struct kern_devconf *, int));
#endif
/*
* local structures
*/
struct en_pci_softc {
/* bus independent stuff */
struct en_softc esc; /* includes "device" structure */
/* PCI bus glue */
void *sc_ih; /* interrupt handle */
pci_chipset_tag_t en_pc; /* for PCI calls */
};
/*
* pointers to softcs (we alloc)
*/
static struct en_pci_softc *enpcis[NEN] = {0};
extern struct cfdriver en_cd;
/*
* autoconfig structures
*/
static u_long en_pci_count;
static struct pci_device endevice = {
"en",
en_pci_probe,
en_pci_attach,
&en_pci_count,
#ifdef SHUTDOWN_PRE_SYNC
NULL,
#else
en_pci_shutdown,
#endif
};
DATA_SET (pcidevice_set, endevice);
/*
* local defines (PCI specific stuff)
*/
/*
* address of config base memory address register in PCI config space
* (this is card specific)
*/
#define PCI_CBMA 0x10
/*
* tonga (pci bridge). ENI cards only!
*/
#define EN_TONGA 0x60 /* PCI config addr of tonga reg */
#define TONGA_SWAP_DMA 0x80 /* endian swap control */
#define TONGA_SWAP_BYTE 0x40
#define TONGA_SWAP_WORD 0x20
/*
* adaptec pci bridge. ADP cards only!
*/
#define ADP_PCIREG 0x050040 /* PCI control register */
#define ADP_PCIREG_RESET 0x1 /* reset card */
#define ADP_PCIREG_IENABLE 0x2 /* interrupt enable */
#define ADP_PCIREG_SWAP_WORD 0x4 /* swap byte on slave access */
#define ADP_PCIREG_SWAP_DMA 0x8 /* swap byte on DMA */
#define PCI_VENDOR_EFFICIENTNETS 0x111a /* Efficent Networks */
#define PCI_PRODUCT_EFFICIENTNETS_ENI155PF 0x0000 /* ENI-155P ATM */
#define PCI_PRODUCT_EFFICIENTNETS_ENI155PA 0x0002 /* ENI-155P ATM */
#define PCI_VENDOR_ADP 0x9004 /* adaptec */
#define PCI_PRODUCT_ADP_AIC5900 0x5900
#define PCI_PRODUCT_ADP_AIC5905 0x5905
#define PCI_VENDOR(x) ((x) & 0xFFFF)
#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF)
#if !defined(MIDWAY_ENIONLY)
static void adp_busreset __P((void *));
/*
* bus specific reset function [ADP only!]
*/
static void adp_busreset(v)
void *v;
{
struct en_softc *sc = (struct en_softc *) v;
u_int32_t dummy;
bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG, ADP_PCIREG_RESET);
DELAY(1000); /* let it reset */
dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG,
(ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA|ADP_PCIREG_IENABLE));
dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
if ((dummy & (ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA)) !=
(ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA))
printf("adp_busreset: Adaptec ATM did NOT reset!\n");
}
#endif
/***********************************************************************/
/*
* autoconfig stuff
*/
static char *en_pci_probe(config_id, device_id)
pcici_t config_id;
pcidi_t device_id;
{
#if !defined(MIDWAY_ADPONLY)
if (PCI_VENDOR(device_id) == PCI_VENDOR_EFFICIENTNETS &&
(PCI_CHIPID(device_id) == PCI_PRODUCT_EFFICIENTNETS_ENI155PF ||
PCI_CHIPID(device_id) == PCI_PRODUCT_EFFICIENTNETS_ENI155PA))
return "Efficient Networks ENI-155p";
#endif
#if !defined(MIDWAY_ENIONLY)
if (PCI_VENDOR(device_id) == PCI_VENDOR_ADP &&
(PCI_CHIPID(device_id) == PCI_PRODUCT_ADP_AIC5900 ||
PCI_CHIPID(device_id) == PCI_PRODUCT_ADP_AIC5905))
return "Adaptec 155 ATM";
#endif
return 0;
}
static void en_pci_attach(config_id, unit)
pcici_t config_id;
int unit;
{
struct en_softc *sc;
struct en_pci_softc *scp;
pcidi_t device_id;
int retval;
vm_offset_t pa;
if (unit >= NEN) {
printf("en%d: not configured; kernel is built for only %d device%s.\n",
unit, NEN, NEN == 1 ? "" : "s");
return;
}
scp = (struct en_pci_softc *) malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
if (scp == NULL)
return;
bzero(scp, sizeof(*scp)); /* zero */
sc = &scp->esc;
retval = pci_map_mem(config_id, PCI_CBMA, (vm_offset_t *) &sc->en_base, &pa);
if (!retval) {
free((caddr_t) scp, M_DEVBUF);
return;
}
enpcis[unit] = scp; /* lock it in */
en_cd.cd_devs[unit] = sc; /* fake a cfdriver structure */
en_cd.cd_ndevs = NEN;
sprintf(sc->sc_dev.dv_xname, "en%d", unit);
sc->enif.if_unit = unit;
sc->enif.if_name = "en";
/*
* figure out if we are an adaptec card or not.
* XXX: why do we have to re-read PC_ID_REG when en_pci_probe already
* had that info?
*/
device_id = pci_conf_read(config_id, PCI_ID_REG);
sc->is_adaptec = (PCI_VENDOR(device_id) == PCI_VENDOR_ADP) ? 1 : 0;
#ifdef SHUTDOWN_PRE_SYNC
/*
* Add shutdown hook so that DMA is disabled prior to reboot. Not
* doing so could allow DMA to corrupt kernel memory during the
* reboot before the driver initializes.
*/
at_shutdown(en_pci_shutdown, scp, SHUTDOWN_POST_SYNC);
#endif
if (!pci_map_int(config_id, en_intr, (void *) sc, &net_imask)) {
printf("%s: couldn't establish interrupt\n", sc->sc_dev.dv_xname);
return;
}
sc->ipl = 1; /* XXX */
/*
* set up pci bridge
*/
#if !defined(MIDWAY_ENIONLY)
if (sc->is_adaptec) {
sc->en_busreset = adp_busreset;
adp_busreset(sc);
}
#endif
#if !defined(MIDWAY_ADPONLY)
if (!sc->is_adaptec) {
sc->en_busreset = NULL;
pci_conf_write(config_id, EN_TONGA, (TONGA_SWAP_DMA|TONGA_SWAP_WORD));
}
#endif
/*
* done PCI specific stuff
*/
en_attach(sc);
}
#ifdef SHUTDOWN_PRE_SYNC
static void
en_pci_shutdown(
int howto,
void *sc)
{
struct en_pci_softc *psc = (struct en_pci_softc *)sc;
en_reset(&psc->esc);
DELAY(10);
}
#else /* !SHUTDOWN_PRE_SYNC */
static int
en_pci_shutdown(kdc, force)
struct kern_devconf *kdc;
int force;
{
if (kdc->kdc_unit < NEN) {
struct en_pci_softc *psc = enpcis[kdc->kdc_unit];
if (psc) /* can it be null? */
en_reset(&psc->esc);
DELAY(10);
}
dev_detach(kdc);
return(0);
}
#endif /* !SHUTDOWN_PRE_SYNC */
#endif /* NEN > 0 && NPCI > 0 */

3208
sys/dev/en/midway.c Normal file

File diff suppressed because it is too large Load Diff

304
sys/dev/en/midwayreg.h Normal file
View File

@ -0,0 +1,304 @@
/* $NetBSD: midwayreg.h,v 1.6 1997/03/20 21:34:47 chuck Exp $ */
/*
* m i d w a y r e g . h
*
* this file contains the description of the ENI ATM midway chip
* data structures. see midway.c for more details.
*
*/
#if defined(sparc) || defined(__FreeBSD__)
/* XXX: gross. netbsd/sparc doesn't have machine/bus.h yet. */
typedef void * bus_space_tag_t;
typedef u_int32_t pci_chipset_tag_t;
typedef caddr_t bus_space_handle_t;
typedef u_int32_t bus_size_t;
typedef caddr_t bus_addr_t;
#define bus_space_read_4(t, h, o) ((void) t, \
(*(volatile u_int32_t *)((h) + (o))))
#define bus_space_write_4(t, h, o, v) \
((void) t, ((void)(*(volatile u_int32_t *)((h) + (o)) = (v))))
#if defined(sparc)
#define vtophys(x) ((u_int32_t)(x)) /* sun4c dvma */
#endif
#endif
#define MID_SZTOB(X) ((X) * 256 * 4) /* size to bytes */
#define MID_BTOSZ(X) ((X) / 256 / 4) /* bytes to "size" */
#define MID_N_VC 1024 /* # of VCs we can use */
#define MID_NTX_CH 8 /* 8 transmit channels (shared) */
#define MID_ATMDATASZ 48 /* need data in 48 byte blocks */
/*
* card data structures, top down
*
* in order to have a portable driver, the netbsd guys will not let us
* use structs. we have a bus_space_handle_t which is the en_base address.
* everything else is an offset from that base. all card data must be
* accessed with bus_space_read_4()/bus_space_write_4():
*
* rv = bus_space_read_4(sc->en_memt, sc->en_base, BYTE_OFFSET);
* bus_space_write_4(sc->en_memt, sc->en_base, BYTE_OFFSET, VALUE);
*
* en_card: the whole card (prom + phy + midway + obmem)
* obmem contains: vci tab + dma queues (rx & tx) + service list + bufs
*/
/* byte offsets from en_base of various items */
#define MID_PHYOFF 0x030000 /* PHY offset */
#define MID_MIDOFF 0x040000 /* midway regs offset */
#define MID_RAMOFF 0x200000 /* RAM offset */
#define MID_DRQOFF 0x204000 /* DRQ offset */
#define MID_DRQEND MID_DTQOFF /* DRQ end */
#define MID_DTQOFF 0x205000 /* DTQ offset */
#define MID_DTQEND MID_SLOFF /* DTQ end */
#define MID_SLOFF 0x206000 /* service list */
#define MID_SLEND MID_BUFOFF /* service list end */
#define MID_BUFOFF 0x207000 /* buffer area */
#define MID_PROBEOFF 0x21fffc /* start probe here */
#define MID_PROBSIZE 0x020000 /* 128 KB */
#define MID_MAXOFF 0x3ffffc /* max offset */
/*
* prom & phy: not defined here
*/
/*
* midway regs (byte offsets from en_base)
*/
#define MID_RESID 0x40000 /* write=reset reg, read=ID reg */
#define MID_VER(X) (((X) & 0xf0000000) >> 28) /* midway version # */
#define MID_MID(X) (((X) & 0x700) >> 8) /* motherboard ID */
#define MID_IS_SABRE(X) ((X) & 0x80) /* sabre controller? */
#define MID_IS_SUNI(X) ((X) & 0x40) /* SUNI? vs utopia */
#define MID_IS_UPIPE(X) ((X) & 0x20) /* utopia pipeline? */
#define MID_DID(X) ((X) & 0x1f) /* daughterboard ID */
#define MID_INTACK 0x40004 /* interrupt ACK */
#define MID_INTSTAT 0x40008 /* interrupt status */
#define MID_INTENA 0x4000c /* interrupt enable */
#define MID_TXCHAN(N) (1 << ((N) + 9)) /* ack/status/enable xmit channel bit*/
#define MID_INT_TX 0x1fe00 /* mask for any xmit interrupt */
#define MID_INT_DMA_OVR 0x00100 /* DMA overflow interrupt */
#define MID_INT_IDENT 0x00080 /* ident match error interrupt */
#define MID_INT_LERR 0x00040 /* LERR interrupt (sbus?) */
#define MID_INT_DMA_ERR 0x00020 /* DMA error interrupt */
#define MID_INT_DMA_RX 0x00010 /* DMA recv interrupt */
#define MID_INT_DMA_TX 0x00008 /* DMA xmit interrupt */
#define MID_INT_SERVICE 0x00004 /* service list interrupt */
#define MID_INT_SUNI 0x00002 /* SUNI interrupt */
#define MID_INT_STATS 0x00001 /* stats overflow interrupt */
#define MID_INT_ANY 0x1ffff /* any interrupt? */
#define MID_INTBITS "\20\21T7\20T6\17T5\16T4\15T3\14T2\13T1\12T0\11DMAOVR\10ID\7LERR\6DMAERR\5RXDMA\4TXDMA\3SERV\2SUNI\1STAT"
#define MID_MAST_CSR 0x40010 /* master CSR */
#define MID_IPL(X) (((X) & 0x1c0) >> 6) /* IPL */
#define MID_SETIPL(I) ((I) << 6)
#define MID_MCSR_TXLOCK 0x20 /* lock on xmit overflow mode */
/* NOTE: next 5 bits: write 1 means enable, write 0 means no change */
#define MID_MCSR_ENDMA 0x10 /* DMA enable */
#define MID_MCSR_ENTX 0x08 /* TX enable */
#define MID_MCSR_ENRX 0x04 /* RX enable */
#define MID_MCSR_W1MS 0x02 /* wait 1 msec */
#define MID_MCSR_W500US 0x01 /* wait 500 usec */
#define MID_MCSRBITS "\20\6LCK\5DMAON\4TXON\3RXON\2W1MS\1W500US"
#define MID_STAT 0x40014 /* stat register, clear on read */
#define MID_VTRASH(X) (((X) >> 16) & 0xffff)
/* # cells trashed due to VCI's mode */
#define MID_OTRASH(X) ((X) & 0xffff) /* # cells trashed due to overflow */
#define MID_SERV_WRITE 0x40018 /* 10 bit service write pointer (r/o) */
#define MID_DMA_ADDR 0x4001c /* VA of DMA (r/o) */
/* DMA queue pointers (bits 0 to 8) */
#define MID_DMA_WRRX 0x40020 /* write ptr. for DMA recv queue */
/* (for adaptor -> host xfers) */
#define MID_DMA_RDRX 0x40024 /* read ptr for DMA recv queue (r/o) */
/* (i.e. current adaptor->host xfer) */
#define MID_DMA_WRTX 0x40028 /* write ptr for DMA xmit queue */
/* (for host -> adaptor xfers) */
#define MID_DMA_RDTX 0x4002c /* read ptr for DMA xmit queue (r/o) */
/* (i.e. current host->adaptor xfer) */
/* xmit channel regs (1 per channel, MID_NTX_CH max channels) */
#define MIDX_PLACE(N) (0x40040+((N)*0x10)) /* xmit place */
#define MIDX_MKPLACE(SZ,LOC) ( ((SZ) << 11) | (LOC) )
#define MIDX_LOC(X) ((X) & 0x7ff) /* location in obmem */
#define MIDX_SZ(X) ((X) >> 11) /* (size of block / 256) in int32_t's*/
#define MIDX_BASE(X) \
(((MIDX_LOC(X) << MIDV_LOCTOPSHFT) * sizeof(u_int32_t)) + MID_RAMOFF)
/* the following two regs are word offsets in the block */
#define MIDX_READPTR(N) (0x40044+((N)*0x10)) /* xmit read pointer (r/o) */
#define MIDX_DESCSTART(N) (0x40048+((N)*0x10)) /* seg currently in DMA (r/o) */
/*
* obmem items
*/
/*
* vci table in obmem (offset from MID_VCTOFF)
*/
#define MID_VC(N) (MID_RAMOFF+((N)*0x10))
#define MIDV_TRASH 0x00000000 /* ignore VC */
#define MIDV_AAL5 0x80000000 /* do AAL5 on it */
#define MIDV_NOAAL 0x40000000 /* do per-cell stuff on it */
#define MIDV_MASK 0xc0000000 /* mode mask */
#define MIDV_SETMODE(VC,M) (((VC) & ~(MIDV_MASK)) | (M)) /* new mode */
#define MIDV_PTI 0x20000000 /* save PTI cells? */
#define MIDV_LOCTOPSHFT 8 /* shift to get top 11 bits of 19 */
#define MIDV_LOCSHIFT 18
#define MIDV_LOCMASK 0x7ff
#define MIDV_LOC(X) (((X) >> MIDV_LOCSHIFT) & MIDV_LOCMASK)
/* 11 most sig bits of addr */
#define MIDV_SZSHIFT 15
#define MIDV_SZ(X) (((X) >> MIDV_SZSHIFT) & 7)
/* size encoded the usual way */
#define MIDV_INSERVICE 0x1 /* in service list */
#define MID_DST_RP(N) (MID_VC(N)|0x4)
#define MIDV_DSTART_SHIFT 16 /* shift */
#define MIDV_DSTART(X) (((X) >> MIDV_DSTART_SHIFT) & 0x7fff)
#define MIDV_READP_MASK 0x7fff /* valid bits, (shift = 0) */
#define MID_WP_ST_CNT(N) (MID_VC(N)|0x8) /* write pointer/state/count */
#define MIDV_WRITEP_MASK 0x7fff0000 /* mask for write ptr. */
#define MIDV_WRITEP_SHIFT 16
#define MIDV_ST_IDLE 0x0000
#define MIDV_ST_TRASH 0xc000
#define MIDV_ST_REASS 0x4000
#define MIDV_CCOUNT 0x7ff /* cell count */
#define MID_CRC(N) (MID_VC(N)|0xc) /* CRC */
/*
* dma recv q.
*/
#define MID_DMA_END (1 << 5) /* for both tx and rx */
#define MID_DMA_CNT(X) (((X) >> 16) & 0xffff)
#define MID_DMA_TXCHAN(X) (((X) >> 6) & 0x7)
#define MID_DMA_RXVCI(X) (((X) >> 6) & 0x3ff)
#define MID_DMA_TYPE(X) ((X) & 0xf)
#define MID_DRQ_N 512 /* # of descriptors */
#define MID_DRQ_A2REG(N) (((N) - MID_DRQOFF) >> 3)
/* convert byte offset to reg value */
#define MID_DRQ_REG2A(N) (((N) << 3) + MID_DRQOFF) /* and back */
/* note: format of word 1 of RXQ is different beween ENI and ADP cards */
#define MID_MK_RXQ_ENI(CNT,VC,END,TYPE) \
( ((CNT) << 16)|((VC) << 6)|(END)|(TYPE) )
#define MID_MK_RXQ_ADP(CNT,VC,END,JK) \
( ((CNT) << 12)|((VC) << 2)|((END) >> 4)|(((JK) != 0) ? 1 : 0))
/*
* dma xmit q.
*/
#define MID_DTQ_N 512 /* # of descriptors */
#define MID_DTQ_A2REG(N) (((N) - MID_DTQOFF) >> 3)
/* convert byte offset to reg value */
#define MID_DTQ_REG2A(N) (((N) << 3) + MID_DTQOFF) /* and back */
/* note: format of word 1 of TXQ is different beween ENI and ADP cards */
#define MID_MK_TXQ_ENI(CNT,CHN,END,TYPE) \
( ((CNT) << 16)|((CHN) << 6)|(END)|(TYPE) )
#define MID_MK_TXQ_ADP(CNT,CHN,END,JK) \
( ((CNT) << 12)|((CHN) << 2)|((END) >> 4)|(((JK) != 0) ? 1 : 0) )
/*
* dma types
*/
#define MIDDMA_JK 0x3 /* just kidding */
#define MIDDMA_BYTE 0x1 /* byte */
#define MIDDMA_2BYTE 0x2 /* 2 bytes */
#define MIDDMA_WORD 0x0 /* word */
#define MIDDMA_2WORD 0x7 /* 2 words */
#define MIDDMA_4WORD 0x4 /* 4 words */
#define MIDDMA_8WORD 0x5 /* 8 words */
#define MIDDMA_16WORD 0x6 /* 16 words!!! */
#define MIDDMA_2WMAYBE 0xf /* 2 words, maybe */
#define MIDDMA_4WMAYBE 0xc /* 4 words, maybe */
#define MIDDMA_8WMAYBE 0xd /* 8 words, maybe */
#define MIDDMA_16WMAYBE 0xe /* 16 words, maybe */
#define MIDDMA_MAYBE 0xc /* mask to detect WMAYBE dma code */
#define MIDDMA_MAXBURST (16 * sizeof(u_int32_t)) /* largest burst */
/*
* service list
*/
#define MID_SL_N 1024 /* max # entries on slist */
#define MID_SL_A2REG(N) (((N) - MID_SLOFF) >> 2)
/* convert byte offset to reg value */
#define MID_SL_REG2A(N) (((N) << 2) + MID_SLOFF) /* and back */
/*
* data in the buffer area of obmem
*/
/*
* recv buffer desc. (1 u_int32_t at start of buffer)
*/
#define MID_RBD_SIZE 4 /* RBD size */
#define MID_CHDR_SIZE 4 /* on aal0, cell header size */
#define MID_RBD_ID(X) ((X) & 0xfe000000) /* get ID */
#define MID_RBD_STDID 0x36000000 /* standard ID */
#define MID_RBD_CLP 0x01000000 /* CLP: cell loss priority */
#define MID_RBD_CE 0x00010000 /* CE: congestion experienced */
#define MID_RBD_T 0x00001000 /* T: trashed due to overflow */
#define MID_RBD_CRCERR 0x00000800 /* CRC error */
#define MID_RBD_CNT(X) ((X) & 0x7ff) /* cell count */
/*
* xmit buffer desc. (2 u_int32_t's at start of buffer)
* (note we treat the PR & RATE as a single u_int8_t)
*/
#define MID_TBD_SIZE 8
#define MID_TBD_MK1(AAL,PR_RATE,CNT) \
(MID_TBD_STDID|(AAL)|((PR_RATE) << 19)|(CNT))
#define MID_TBD_STDID 0xb0000000 /* standard ID */
#define MID_TBD_AAL5 0x08000000 /* AAL 5 */
#define MID_TBD_NOAAL5 0x00000000 /* not AAL 5 */
#define MID_TBD_MK2(VCI,PTI,CLP) \
(((VCI) << 4)|((PTI) << 1)|(CLP))
/*
* aal5 pdu tail, last 2 words of last cell of AAL5 frame
* (word 2 is CRC .. handled by hw)
*/
#define MID_PDU_SIZE 8
#define MID_PDU_MK1(UU,CPI,LEN) \
(((UU) << 24)|((CPI) << 16)|(LEN))
#define MID_PDU_LEN(X) ((X) & 0xffff)

205
sys/dev/en/midwayvar.h Normal file
View File

@ -0,0 +1,205 @@
/* $NetBSD: midwayvar.h,v 1.10 1997/03/20 21:34:46 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* m i d w a y v a r . h
*
* we define the en_softc here so that bus specific modules can allocate
* it as the first item in their softc. note that BSD-required
* "struct device" is in the mid_softc!
*
* author: Chuck Cranor <chuck@ccrc.wustl.edu>
*/
/*
* params needed to determine softc size
*/
#ifndef EN_NTX
#define EN_NTX 8 /* number of tx bufs to use */
#endif
#ifndef EN_TXSZ
#define EN_TXSZ 32 /* trasmit buf size in KB */
#endif
#ifndef EN_RXSZ
#define EN_RXSZ 32 /* recv buf size in KB */
#endif
#define EN_MAXNRX ((2048-(EN_NTX*EN_TXSZ))/EN_RXSZ)
/* largest possible NRX (depends on RAM size) */
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
#define EN_INTR_TYPE int
#define EN_INTR_RET(X) return(X)
#if defined(__NetBSD__) || defined(__OpenBSD__)
#define EN_IOCTL_CMDT u_long
#elif defined(__bsdi__)
#define EN_IOCTL_CMDT int
#endif
#elif defined(__FreeBSD__)
#define EN_INTR_TYPE void
#define EN_INTR_RET(X) return
#define EN_IOCTL_CMDT int
struct device {
char dv_xname[IFNAMSIZ];
};
#define DV_IFNET 1
struct cfdriver {
int zero;
char *name;
int one;
int cd_ndevs;
void *cd_devs[NEN];
};
#endif
/*
* softc
*/
struct en_softc {
/* bsd glue */
struct device sc_dev; /* system device */
struct ifnet enif; /* network ifnet handle */
/* bus glue */
bus_space_tag_t en_memt; /* for EN_READ/EN_WRITE */
bus_space_handle_t en_base; /* base of en card */
bus_size_t en_obmemsz; /* size of en card (bytes) */
void (*en_busreset) __P((void *));
/* bus specific reset function */
/* serv list */
u_int32_t hwslistp; /* hw pointer to service list (byte offset) */
u_int16_t swslist[MID_SL_N]; /* software service list (see en_service()) */
u_int16_t swsl_head, /* ends of swslist (index into swslist) */
swsl_tail;
u_int32_t swsl_size; /* # of items in swsl */
/* xmit dma */
u_int32_t dtq[MID_DTQ_N]; /* sw copy of dma q (see ENIDQ macros) */
u_int32_t dtq_free; /* # of dtq's free */
u_int32_t dtq_us; /* software copy of our pointer (byte offset) */
u_int32_t dtq_chip; /* chip's pointer (byte offset) */
u_int32_t need_dtqs; /* true if we ran out of DTQs */
/* recv dma */
u_int32_t drq[MID_DRQ_N]; /* sw copy of dma q (see ENIDQ macros) */
u_int32_t drq_free; /* # of drq's free */
u_int32_t drq_us; /* software copy of our pointer (byte offset) */
u_int32_t drq_chip; /* chip's pointer (byte offset) */
u_int32_t need_drqs; /* true if we ran out of DRQs */
/* xmit buf ctrl. (per channel) */
struct {
u_int32_t mbsize; /* # mbuf bytes we are using (max=TXHIWAT) */
u_int32_t bfree; /* # free bytes in buffer (not dma or xmit) */
u_int32_t start, stop; /* ends of buffer area (byte offset) */
u_int32_t cur; /* next free area (byte offset) */
u_int32_t nref; /* # of VCs using this channel */
struct ifqueue indma; /* mbufs being dma'd now */
struct ifqueue q; /* mbufs waiting for dma now */
} txslot[MID_NTX_CH];
/* xmit vc ctrl. (per vc) */
u_int8_t txspeed[MID_N_VC]; /* speed of tx on a VC */
u_int8_t txvc2slot[MID_N_VC]; /* map VC to slot */
/* recv vc ctrl. (per vc). maps VC number to recv slot */
u_int16_t rxvc2slot[MID_N_VC];
int en_nrx; /* # of active rx slots */
/* recv buf ctrl. (per recv slot) */
struct {
void *rxhand; /* recv. handle if doing direct delivery */
u_int32_t mode; /* saved copy of mode info */
u_int32_t start, stop; /* ends of my buffer area */
u_int32_t cur; /* where I am at */
u_int16_t atm_vci; /* backpointer to VCI */
u_int8_t atm_flags; /* copy of atm_flags from atm_ph */
u_int8_t oth_flags; /* other flags */
u_int32_t raw_threshold; /* for raw mode */
struct ifqueue indma; /* mbufs being dma'd now */
struct ifqueue q; /* mbufs waiting for dma now */
} rxslot[EN_MAXNRX]; /* recv info */
/* stats */
u_int32_t vtrash; /* sw copy of counter */
u_int32_t otrash; /* sw copy of counter */
u_int32_t ttrash; /* # of RBD's with T bit set */
u_int32_t mfix; /* # of times we had to call mfix */
u_int32_t mfixfail; /* # of times mfix failed */
u_int32_t headbyte; /* # of times we used BYTE DMA at front */
u_int32_t tailbyte; /* # of times we used BYTE DMA at end */
u_int32_t tailflush; /* # of times we had to FLUSH out DMA bytes */
u_int32_t txmbovr; /* # of times we dropped due to mbsize */
u_int32_t dmaovr; /* tx dma overflow count */
u_int32_t txoutspace; /* out of space in xmit buffer */
u_int32_t txdtqout; /* out of DTQs */
u_int32_t launch; /* total # of launches */
u_int32_t lheader; /* # of launches without OB header */
u_int32_t ltail; /* # of launches without OB tail */
u_int32_t hwpull; /* # of pulls off hardware service list */
u_int32_t swadd; /* # of pushes on sw service list */
u_int32_t rxqnotus; /* # of times we pull from rx q, but fail */
u_int32_t rxqus; /* # of good pulls from rx q */
u_int32_t rxoutboth; /* # of times out of mbufs and DRQs */
u_int32_t rxdrqout; /* # of times out of DRQs */
u_int32_t rxmbufout; /* # of time out of mbufs */
/* random stuff */
u_int32_t ipl; /* sbus interrupt lvl (1 on pci?) */
u_int8_t bestburstcode; /* code of best burst we can use */
u_int8_t bestburstlen; /* length of best burst (bytes) */
u_int8_t bestburstshift; /* (x >> shift) == (x / bestburstlen) */
u_int8_t bestburstmask; /* bits to check if not multiple of burst */
u_int8_t alburst; /* align dma bursts? */
u_int8_t is_adaptec; /* adaptec version of midway? */
};
/*
* exported functions
*/
void en_attach __P((struct en_softc *));
EN_INTR_TYPE en_intr __P((void *));
void en_reset __P((struct en_softc *));

111
sys/net/if_atm.h Normal file
View File

@ -0,0 +1,111 @@
/* $NetBSD: if_atm.h,v 1.7 1996/11/09 23:02:27 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* net/if_atm.h
*/
#if (defined(__FreeBSD__) || defined(__bsdi__)) && defined(KERNEL)
#ifndef _KERNEL
#define _KERNEL
#endif
#endif /* freebsd doesn't define _KERNEL */
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
#define RTALLOC1(A,B) rtalloc1((A),(B))
#elif defined(__FreeBSD__)
#define RTALLOC1(A,B) rtalloc1((A),(B),0UL)
#endif
/*
* pseudo header for packet transmission
*/
struct atm_pseudohdr {
u_int8_t atm_ph[4]; /* flags+VPI+VCI1(msb)+VCI2(lsb) */
};
#define ATM_PH_FLAGS(X) ((X)->atm_ph[0])
#define ATM_PH_VPI(X) ((X)->atm_ph[1])
#define ATM_PH_VCI(X) ((((X)->atm_ph[2]) << 8) | ((X)->atm_ph[3]))
#define ATM_PH_SETVCI(X,V) { \
(X)->atm_ph[2] = ((V) >> 8) & 0xff; \
(X)->atm_ph[3] = ((V) & 0xff); \
}
#define ATM_PH_AAL5 0x01 /* use AAL5? (0 == aal0) */
#define ATM_PH_LLCSNAP 0x02 /* use the LLC SNAP encoding (iff aal5) */
#define ATM_PH_DRIVER7 0x40 /* reserve for driver's use */
#define ATM_PH_DRIVER8 0x80 /* reserve for driver's use */
#define ATMMTU 9180 /* ATM MTU size for IP */
/* XXX: could be 9188 with LLC/SNAP according
to comer */
/* user's ioctl hook for raw atm mode */
#define SIOCRAWATM _IOWR('a', 122, int) /* set driver's raw mode */
/* atm_pseudoioctl: turns on and off RX VCIs [for internal use only!] */
struct atm_pseudoioctl {
struct atm_pseudohdr aph;
void *rxhand;
};
#define SIOCATMENA _IOWR('a', 123, struct atm_pseudoioctl) /* enable */
#define SIOCATMDIS _IOWR('a', 124, struct atm_pseudoioctl) /* disable */
/*
* XXX forget all the garbage in if_llc.h and do it the easy way
*/
#define ATMLLC_HDR "\252\252\3\0\0\0"
struct atmllc {
u_int8_t llchdr[6]; /* aa.aa.03.00.00.00 */
u_int8_t type[2]; /* "ethernet" type */
};
/* ATM_LLC macros: note type code in host byte order */
#define ATM_LLC_TYPE(X) (((X)->type[0] << 8) | ((X)->type[1]))
#define ATM_LLC_SETTYPE(X,V) { \
(X)->type[1] = ((V) >> 8) & 0xff; \
(X)->type[0] = ((V) & 0xff); \
}
#ifdef _KERNEL
void atm_ifattach __P((struct ifnet *));
void atm_input __P((struct ifnet *, struct atm_pseudohdr *,
struct mbuf *, void *));
int atm_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *));
#endif

410
sys/net/if_atmsubr.c Normal file
View File

@ -0,0 +1,410 @@
/* $NetBSD: if_atmsubr.c,v 1.10 1997/03/11 23:19:51 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* if_atmsubr.c
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#if defined(__FreeBSD__)
#include <sys/sockio.h>
#else
#include <sys/ioctl.h>
#endif
#include <sys/errno.h>
#include <sys/syslog.h>
#include <machine/cpu.h>
#include <net/if.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_atm.h>
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */
#ifdef INET
#include <netinet/in_var.h>
#endif
#ifdef NATM
#include <netnatm/natm.h>
#endif
#include "bpfilter.h"
#if NBPFILTER > 0
/*
* bpf support.
* the code is derived from if_loop.c.
* bpf support should belong to the driver but it's easier to implement
* it here since we can call bpf_mtap before atm_output adds a pseudo
* header to the mbuf.
* --kjc
*/
#include <sys/time.h>
#include <net/bpf.h>
#endif /* NBPFILTER > 0 */
#define senderr(e) { error = (e); goto bad;}
/*
* atm_output: ATM output routine
* inputs:
* "ifp" = ATM interface to output to
* "m0" = the packet to output
* "dst" = the sockaddr to send to (either IP addr, or raw VPI/VCI)
* "rt0" = the route to use
* returns: error code [0 == ok]
*
* note: special semantic: if (dst == NULL) then we assume "m" already
* has an atm_pseudohdr on it and just send it directly.
* [for native mode ATM output] if dst is null, then
* rt0 must also be NULL.
*/
int
atm_output(ifp, m0, dst, rt0)
register struct ifnet *ifp;
struct mbuf *m0;
struct sockaddr *dst;
struct rtentry *rt0;
{
u_int16_t etype = 0; /* if using LLC/SNAP */
int s, error = 0, sz;
struct atm_pseudohdr atmdst, *ad;
register struct mbuf *m = m0;
register struct rtentry *rt;
struct atmllc *atmllc;
u_int32_t atm_flags;
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
ifp->if_lastchange = time;
/*
* check route
*/
if ((rt = rt0) != NULL) {
if ((rt->rt_flags & RTF_UP) == 0) { /* route went down! */
if ((rt0 = rt = RTALLOC1(dst, 0)) != NULL)
rt->rt_refcnt--;
else
senderr(EHOSTUNREACH);
}
if (rt->rt_flags & RTF_GATEWAY) {
if (rt->rt_gwroute == 0)
goto lookup;
if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
rtfree(rt); rt = rt0;
lookup: rt->rt_gwroute = RTALLOC1(rt->rt_gateway, 0);
if ((rt = rt->rt_gwroute) == 0)
senderr(EHOSTUNREACH);
}
}
/* XXX: put RTF_REJECT code here if doing ATMARP */
}
/*
* check for non-native ATM traffic (dst != NULL)
*/
if (dst) {
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
if (!atmresolve(rt, m, dst, &atmdst)) {
m = NULL;
/* XXX: atmresolve already free'd it */
senderr(EHOSTUNREACH);
/* XXX: put ATMARP stuff here */
/* XXX: watch who frees m on failure */
}
etype = htons(ETHERTYPE_IP);
break;
#endif
default:
#if defined(__NetBSD__) || defined(__OpenBSD__)
printf("%s: can't handle af%d\n", ifp->if_xname,
dst->sa_family);
#elif defined(__FreeBSD__) || defined(__bsdi__)
printf("%s%d: can't handle af%d\n", ifp->if_name,
ifp->if_unit, dst->sa_family);
#endif
senderr(EAFNOSUPPORT);
}
#if NBPFILTER > 0
/* BPF write needs to be handled specially */
if (dst && dst->sa_family == AF_UNSPEC) {
dst->sa_family = *(mtod(m, int *));
m->m_len -= sizeof(int);
m->m_pkthdr.len -= sizeof(int);
m->m_data += sizeof(int);
}
if (ifp->if_bpf) {
/*
* We need to prepend the address family as
* a four byte field. Cons up a dummy header
* to pacify bpf. This is safe because bpf
* will only read from the mbuf (i.e., it won't
* try to free it or keep a pointer a to it).
*/
struct mbuf m1;
u_int af = dst->sa_family;
m1.m_next = m;
m1.m_len = 4;
m1.m_data = (char *)&af;
s = splimp();
#if defined(__NetBSD__) || defined(__OpenBSD__)
bpf_mtap(&ifp->if_bpf, &m0);
#elif defined(__FreeBSD__)
bpf_mtap(ifp, &m1);
#endif
splx(s);
}
#endif /* NBPFILTER > 0 */
/*
* must add atm_pseudohdr to data
*/
sz = sizeof(atmdst);
atm_flags = ATM_PH_FLAGS(&atmdst);
if (atm_flags & ATM_PH_LLCSNAP) sz += 8; /* sizeof snap == 8 */
M_PREPEND(m, sz, M_DONTWAIT);
if (m == 0)
senderr(ENOBUFS);
ad = mtod(m, struct atm_pseudohdr *);
*ad = atmdst;
if (atm_flags & ATM_PH_LLCSNAP) {
atmllc = (struct atmllc *)(ad + 1);
bcopy(ATMLLC_HDR, atmllc->llchdr,
sizeof(atmllc->llchdr));
ATM_LLC_SETTYPE(atmllc, etype);
/* note: already in network order */
}
}
/*
* Queue message on interface, and start output if interface
* not yet active.
*/
s = splimp();
if (IF_QFULL(&ifp->if_snd)) {
IF_DROP(&ifp->if_snd);
splx(s);
senderr(ENOBUFS);
}
ifp->if_obytes += m->m_pkthdr.len;
IF_ENQUEUE(&ifp->if_snd, m);
if ((ifp->if_flags & IFF_OACTIVE) == 0)
(*ifp->if_start)(ifp);
splx(s);
return (error);
bad:
if (m)
m_freem(m);
return (error);
}
/*
* Process a received ATM packet;
* the packet is in the mbuf chain m.
*/
void
atm_input(ifp, ah, m, rxhand)
struct ifnet *ifp;
register struct atm_pseudohdr *ah;
struct mbuf *m;
void *rxhand;
{
register struct ifqueue *inq;
u_int16_t etype = ETHERTYPE_IP; /* default */
int s;
if ((ifp->if_flags & IFF_UP) == 0) {
m_freem(m);
return;
}
ifp->if_lastchange = time;
ifp->if_ibytes += m->m_pkthdr.len;
#if NBPFILTER > 0
if (ifp->if_bpf) {
/*
* We need to prepend the address family as
* a four byte field. Cons up a dummy header
* to pacify bpf. This is safe because bpf
* will only read from the mbuf (i.e., it won't
* try to free it or keep a pointer to it).
*/
struct mbuf m0;
u_int af = AF_INET;
m0.m_next = m;
m0.m_len = 4;
m0.m_data = (char *)&af;
#if defined(__NetBSD__) || defined(__OpenBSD__)
bpf_mtap(&ifp->if_bpf, &m0);
#elif defined(__FreeBSD__)
bpf_mtap(ifp, &m0);
#endif
}
#endif /* NBPFILTER > 0 */
if (rxhand) {
#ifdef NATM
struct natmpcb *npcb = rxhand;
s = splimp(); /* in case 2 atm cards @ diff lvls */
npcb->npcb_inq++; /* count # in queue */
splx(s);
schednetisr(NETISR_NATM);
inq = &natmintrq;
m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
#else
printf("atm_input: NATM detected but not configured in kernel\n");
m_freem(m);
return;
#endif
} else {
/*
* handle LLC/SNAP header, if present
*/
if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
struct atmllc *alc;
if (m->m_len < sizeof(*alc) && (m = m_pullup(m, sizeof(*alc))) == 0)
return; /* failed */
alc = mtod(m, struct atmllc *);
if (bcmp(alc, ATMLLC_HDR, 6)) {
#if defined(__NetBSD__) || defined(__OpenBSD__)
printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
#elif defined(__FreeBSD__) || defined(__bsdi__)
printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
#endif
m_freem(m);
return;
}
etype = ATM_LLC_TYPE(alc);
m_adj(m, sizeof(*alc));
}
switch (etype) {
#ifdef INET
case ETHERTYPE_IP:
schednetisr(NETISR_IP);
inq = &ipintrq;
break;
#endif
default:
m_freem(m);
return;
}
}
s = splimp();
if (IF_QFULL(inq)) {
IF_DROP(inq);
m_freem(m);
} else
IF_ENQUEUE(inq, m);
splx(s);
}
/*
* Perform common duties while attaching to interface list
*/
void
atm_ifattach(ifp)
register struct ifnet *ifp;
{
register struct ifaddr *ifa;
register struct sockaddr_dl *sdl;
ifp->if_type = IFT_ATM;
ifp->if_addrlen = 0;
ifp->if_hdrlen = 0;
ifp->if_mtu = ATMMTU;
ifp->if_output = atm_output;
#if defined(__NetBSD__) || defined(__OpenBSD__)
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
ifa = ifa->ifa_list.tqe_next)
#elif defined(__FreeBSD__) && ((__FreeBSD__ > 2) || defined(_NET_IF_VAR_H_))
/*
* for FreeBSD-3.0. 3.0-SNAP-970124 still sets -D__FreeBSD__=2!
* XXX -- for now, use newly-introduced "net/if_var.h" as an identifier.
* need a better way to identify 3.0. -- kjc
*/
for (ifa = ifp->if_addrhead.tqh_first; ifa;
ifa = ifa->ifa_link.tqe_next)
#elif defined(__FreeBSD__) || defined(__bsdi__)
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
#endif
if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
sdl->sdl_family == AF_LINK) {
sdl->sdl_type = IFT_ATM;
sdl->sdl_alen = ifp->if_addrlen;
#ifdef notyet /* if using ATMARP, store hardware address using the next line */
bcopy(ifp->hw_addr, LLADDR(sdl), ifp->if_addrlen);
#endif
break;
}
#if NBPFILTER > 0
#if defined(__NetBSD__) || defined(__OpenBSD__)
bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
#elif defined(__FreeBSD__)
bpfattach(ifp, DLT_NULL, sizeof(u_int));
#endif
#endif /* NBPFILTER > 0 */
}

285
sys/netinet/if_atm.c Normal file
View File

@ -0,0 +1,285 @@
/* $NetBSD: if_atm.c,v 1.6 1996/10/13 02:03:01 christos Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* IP <=> ATM address resolution.
*/
#ifdef INET
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/errno.h>
#if defined(__FreeBSD__)
#include <sys/sockio.h>
#else
#include <sys/ioctl.h>
#endif
#include <sys/syslog.h>
#include <sys/proc.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <net/if_atm.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/if_atm.h>
#ifdef NATM
#include <netnatm/natm.h>
#endif
#define SDL(s) ((struct sockaddr_dl *)s)
/*
* atm_rtrequest: handle ATM rt request (in support of generic code)
* inputs: "req" = request code
* "rt" = route entry
* "sa" = sockaddr
*/
void
atm_rtrequest(req, rt, sa)
int req;
register struct rtentry *rt;
struct sockaddr *sa;
{
register struct sockaddr *gate = rt->rt_gateway;
struct atm_pseudoioctl api;
#ifdef NATM
struct sockaddr_in *sin;
struct natmpcb *npcb = NULL;
struct atm_pseudohdr *aph;
#endif
static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
if (rt->rt_flags & RTF_GATEWAY) /* link level requests only */
return;
switch (req) {
case RTM_RESOLVE: /* resolve: only happens when cloning */
printf("atm_rtrequest: RTM_RESOLVE request detected?\n");
break;
case RTM_ADD:
/*
* route added by a command (e.g. ifconfig, route, arp...).
*
* first check to see if this is not a host route, in which
* case we are being called via "ifconfig" to set the address.
*/
if ((rt->rt_flags & RTF_HOST) == 0) {
rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl);
gate = rt->rt_gateway;
SDL(gate)->sdl_type = rt->rt_ifp->if_type;
SDL(gate)->sdl_index = rt->rt_ifp->if_index;
break;
}
if ((rt->rt_flags & RTF_CLONING) != 0) {
printf("atm_rtrequest: cloning route detected?\n");
break;
}
if (gate->sa_family != AF_LINK ||
gate->sa_len < sizeof(null_sdl)) {
log(LOG_DEBUG, "atm_rtrequest: bad gateway value");
break;
}
#ifdef DIAGNOSTIC
if (rt->rt_ifp->if_ioctl == NULL) panic("atm null ioctl");
#endif
#ifdef NATM
/*
* let native ATM know we are using this VCI/VPI
* (i.e. reserve it)
*/
sin = (struct sockaddr_in *) rt_key(rt);
if (sin->sin_family != AF_INET)
goto failed;
aph = (struct atm_pseudohdr *) LLADDR(SDL(gate));
npcb = npcb_add(NULL, rt->rt_ifp, ATM_PH_VCI(aph),
ATM_PH_VPI(aph));
if (npcb == NULL)
goto failed;
npcb->npcb_flags |= NPCB_IP;
npcb->ipaddr.s_addr = sin->sin_addr.s_addr;
/* XXX: move npcb to llinfo when ATM ARP is ready */
rt->rt_llinfo = (caddr_t) npcb;
rt->rt_flags |= RTF_LLINFO;
#endif
/*
* let the lower level know this circuit is active
*/
bcopy(LLADDR(SDL(gate)), &api.aph, sizeof(api.aph));
api.rxhand = NULL;
if (rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMENA,
(caddr_t)&api) != 0) {
printf("atm: couldn't add VC\n");
goto failed;
}
SDL(gate)->sdl_type = rt->rt_ifp->if_type;
SDL(gate)->sdl_index = rt->rt_ifp->if_index;
break;
failed:
#ifdef NATM
if (npcb) {
npcb_free(npcb, NPCB_DESTROY);
rt->rt_llinfo = NULL;
rt->rt_flags &= ~RTF_LLINFO;
}
#endif
rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
rt_mask(rt), 0, (struct rtentry **) 0);
break;
case RTM_DELETE:
#ifdef NATM
/*
* tell native ATM we are done with this VC
*/
if (rt->rt_flags & RTF_LLINFO) {
npcb_free((struct natmpcb *)rt->rt_llinfo,
NPCB_DESTROY);
rt->rt_llinfo = NULL;
rt->rt_flags &= ~RTF_LLINFO;
}
#endif
/*
* tell the lower layer to disable this circuit
*/
bcopy(LLADDR(SDL(gate)), &api.aph, sizeof(api.aph));
api.rxhand = NULL;
(void)rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMDIS,
(caddr_t)&api);
break;
}
}
/*
* atmresolve:
* inputs:
* [1] "rt" = the link level route to use (or null if need to look one up)
* [2] "m" = mbuf containing the data to be sent
* [3] "dst" = sockaddr_in (IP) address of dest.
* output:
* [4] "desten" = ATM pseudo header which we will fill in VPI/VCI info
* return:
* 0 == resolve FAILED; note that "m" gets m_freem'd in this case
* 1 == resolve OK; desten contains result
*
* XXX: will need more work if we wish to support ATMARP in the kernel,
* but this is enough for PVCs entered via the "route" command.
*/
int
atmresolve(rt, m, dst, desten)
register struct rtentry *rt;
struct mbuf *m;
register struct sockaddr *dst;
register struct atm_pseudohdr *desten; /* OUT */
{
struct sockaddr_dl *sdl;
if (m->m_flags & (M_BCAST|M_MCAST)) {
log(LOG_INFO, "atmresolve: BCAST/MCAST packet detected/dumped");
goto bad;
}
if (rt == NULL) {
rt = RTALLOC1(dst, 0);
if (rt == NULL) goto bad; /* failed */
rt->rt_refcnt--; /* don't keep LL references */
if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
(rt->rt_flags & RTF_LLINFO) == 0 ||
/* XXX: are we using LLINFO? */
rt->rt_gateway->sa_family != AF_LINK) {
goto bad;
}
}
/*
* note that rt_gateway is a sockaddr_dl which contains the
* atm_pseudohdr data structure for this route. we currently
* don't need any rt_llinfo info (but will if we want to support
* ATM ARP [c.f. if_ether.c]).
*/
sdl = SDL(rt->rt_gateway);
/*
* Check the address family and length is valid, the address
* is resolved; otherwise, try to resolve.
*/
if (sdl->sdl_family == AF_LINK && sdl->sdl_alen == sizeof(*desten)) {
bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
return(1); /* ok, go for it! */
}
/*
* we got an entry, but it doesn't have valid link address
* info in it (it is prob. the interface route, which has
* sdl_alen == 0). dump packet. (fall through to "bad").
*/
bad:
m_freem(m);
return(0);
}
#endif /* INET */

41
sys/netinet/if_atm.h Normal file
View File

@ -0,0 +1,41 @@
/* $NetBSD: if_atm.h,v 1.2 1996/07/03 17:17:17 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* if_atm.h
*/
void atm_rtrequest __P((int, struct rtentry *, struct sockaddr *));
int atmresolve __P((struct rtentry *, struct mbuf *, struct sockaddr *,
struct atm_pseudohdr *));

161
sys/netnatm/natm.h Normal file
View File

@ -0,0 +1,161 @@
/* $NetBSD: natm.h,v 1.1 1996/07/04 03:20:12 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* natm.h: native mode atm
*/
/*
* supported protocols
*/
#define PROTO_NATMAAL0 1
#define PROTO_NATMAAL5 2
/*
* sockaddr_natm
*/
struct sockaddr_natm {
u_int8_t snatm_len; /* length */
u_int8_t snatm_family; /* AF_NATM */
char snatm_if[IFNAMSIZ]; /* interface name */
u_int16_t snatm_vci; /* vci */
u_int8_t snatm_vpi; /* vpi */
};
#if defined(__FreeBSD__) && defined(KERNEL)
#ifndef _KERNEL
#define _KERNEL
#endif
#define SPLSOFTNET() splnet()
#elif defined(__NetBSD__) || defined(__OpenBSD__)
#define SPLSOFTNET() splsoftnet()
#endif
#ifdef _KERNEL
/*
* natm protocol control block
*/
struct natmpcb {
LIST_ENTRY(natmpcb) pcblist; /* list pointers */
u_int npcb_inq; /* # of our pkts in proto q */
struct socket *npcb_socket; /* backpointer to socket */
struct ifnet *npcb_ifp; /* pointer to hardware */
struct in_addr ipaddr; /* remote IP address, if APCB_IP */
u_int16_t npcb_vci; /* VCI */
u_int8_t npcb_vpi; /* VPI */
u_int8_t npcb_flags; /* flags */
};
/* flags */
#define NPCB_FREE 0x01 /* free (not on any list) */
#define NPCB_CONNECTED 0x02 /* connected */
#define NPCB_IP 0x04 /* used by IP */
#define NPCB_DRAIN 0x08 /* destory as soon as inq == 0 */
#define NPCB_RAW 0x10 /* in 'raw' mode? */
/* flag arg to npcb_free */
#define NPCB_REMOVE 0 /* remove from global list */
#define NPCB_DESTROY 1 /* destroy and be free */
/*
* NPCB_RAWCC is a hack which applies to connections in 'raw' mode. it
* is used to override the sbspace() macro when you *really* don't want
* to drop rcv data. the recv socket buffer size is raised to this value.
*
* XXX: socket buffering needs to be looked at.
*/
#define NPCB_RAWCC (1024*1024) /* 1MB */
LIST_HEAD(npcblist, natmpcb);
/* global data structures */
struct npcblist natm_pcbs; /* global list of pcbs */
extern struct ifqueue natmintrq; /* natm packet input queue */
#define NATM_STAT
#ifdef NATM_STAT
extern u_int natm_sodropcnt,
natm_sodropbytes; /* account of droppage */
extern u_int natm_sookcnt,
natm_sookbytes; /* account of ok */
#endif
/* atm_rawioctl: kernel's version of SIOCRAWATM [for internal use only!] */
struct atm_rawioctl {
struct natmpcb *npcb;
int rawvalue;
};
#define SIOCXRAWATM _IOWR('a', 125, struct atm_rawioctl)
/* external functions */
/* natm_pcb.c */
struct natmpcb *npcb_alloc __P((int));
void npcb_free __P((struct natmpcb *, int));
struct natmpcb *npcb_add __P((struct natmpcb *, struct ifnet *, int, int));
/* natm.c */
#if defined(__NetBSD__) || defined(__OpenBSD__)
int natm_usrreq __P((struct socket *, int, struct mbuf *,
struct mbuf *, struct mbuf *, struct proc *));
#elif defined(__FreeBSD__)
#if __FreeBSD__ > 2
/*
* FreeBSD new usrreqs style appeared since 2.2. compatibility to old style
* has gone since 3.0.
*/
#define FREEBSD_USRREQS
extern struct pr_usrreqs natm_usrreqs;
#else /* !( __FreeBSD__ > 2) */
int natm_usrreq __P((struct socket *, int, struct mbuf *,
struct mbuf *, struct mbuf *));
#endif /* !( __FreeBSD__ > 2) */
#endif
int natm0_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
int natm5_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
void natmintr __P((void));
#endif

194
sys/netnatm/natm_pcb.c Normal file
View File

@ -0,0 +1,194 @@
/* $NetBSD: natm_pcb.c,v 1.4 1996/11/09 03:26:27 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* atm_pcb.c: manage atm protocol control blocks and keep IP and NATM
* from trying to use each other's VCs.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <net/if.h>
#include <net/radix.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netnatm/natm.h>
/*
* npcb_alloc: allocate a npcb [in the free state]
*/
struct natmpcb *npcb_alloc(wait)
int wait;
{
struct natmpcb *npcb;
MALLOC(npcb, struct natmpcb *, sizeof(*npcb), M_PCB, wait);
#ifdef DIAGNOSTIC
if (wait == M_WAITOK && npcb == NULL) panic("npcb_alloc: malloc didn't wait");
#endif
if (npcb) {
bzero(npcb, sizeof(*npcb));
npcb->npcb_flags = NPCB_FREE;
}
return(npcb);
}
/*
* npcb_free: free a npcb
*/
void npcb_free(npcb, op)
struct natmpcb *npcb;
int op;
{
int s = splimp();
if ((npcb->npcb_flags & NPCB_FREE) == 0) {
LIST_REMOVE(npcb, pcblist);
npcb->npcb_flags = NPCB_FREE;
}
if (op == NPCB_DESTROY) {
if (npcb->npcb_inq) {
npcb->npcb_flags = NPCB_DRAIN; /* flag for distruction */
} else {
FREE(npcb, M_PCB); /* kill it! */
}
}
splx(s);
}
/*
* npcb_add: add or remove npcb from main list
* returns npcb if ok
*/
struct natmpcb *npcb_add(npcb, ifp, vci, vpi)
struct natmpcb *npcb;
struct ifnet *ifp;
u_int16_t vci;
u_int8_t vpi;
{
struct natmpcb *cpcb = NULL; /* current pcb */
int s = splimp();
/*
* lookup required
*/
for (cpcb = natm_pcbs.lh_first ; cpcb != NULL ;
cpcb = cpcb->pcblist.le_next) {
if (ifp == cpcb->npcb_ifp && vci == cpcb->npcb_vci && vpi == cpcb->npcb_vpi)
break;
}
/*
* add & something already there?
*/
if (cpcb) {
cpcb = NULL;
goto done; /* fail */
}
/*
* need to allocate a pcb?
*/
if (npcb == NULL) {
cpcb = npcb_alloc(M_NOWAIT); /* could be called from lower half */
if (cpcb == NULL)
goto done; /* fail */
} else {
cpcb = npcb;
}
cpcb->npcb_ifp = ifp;
cpcb->ipaddr.s_addr = 0;
cpcb->npcb_vci = vci;
cpcb->npcb_vpi = vpi;
cpcb->npcb_flags = NPCB_CONNECTED;
LIST_INSERT_HEAD(&natm_pcbs, cpcb, pcblist);
done:
splx(s);
return(cpcb);
}
#ifdef DDB
int npcb_dump __P((void));
int npcb_dump()
{
struct natmpcb *cpcb;
printf("npcb dump:\n");
for (cpcb = natm_pcbs.lh_first ; cpcb != NULL ;
cpcb = cpcb->pcblist.le_next) {
printf("if=%s, vci=%d, vpi=%d, IP=0x%x, sock=%p, flags=0x%x, inq=%d\n",
cpcb->npcb_ifp->if_xname, cpcb->npcb_vci, cpcb->npcb_vpi,
cpcb->ipaddr.s_addr, cpcb->npcb_socket,
cpcb->npcb_flags, cpcb->npcb_inq);
}
printf("done\n");
return(0);
}
#endif

131
sys/netnatm/natm_proto.c Normal file
View File

@ -0,0 +1,131 @@
/* $NetBSD: natm_proto.c,v 1.3 1996/09/18 00:56:41 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* protocol layer for access to native mode ATM
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <net/if.h>
#include <net/radix.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netnatm/natm.h>
extern struct domain natmdomain;
static void natm_init __P((void));
struct protosw natmsw[] = {
{ SOCK_STREAM, &natmdomain, PROTO_NATMAAL5, PR_CONNREQUIRED,
0, 0, 0, 0,
#ifdef FREEBSD_USRREQS
0,
#else
natm_usrreq,
#endif
0, 0, 0, 0,
#if defined(__NetBSD__) || defined(__OpenBSD__)
natm5_sysctl
#elif defined(FREEBSD_USRREQS)
&natm_usrreqs
#endif
},
{ SOCK_DGRAM, &natmdomain, PROTO_NATMAAL5, PR_CONNREQUIRED | PR_ATOMIC,
0, 0, 0, 0,
#ifdef FREEBSD_USRREQS
0,
#else
natm_usrreq,
#endif
0, 0, 0, 0,
#if defined(__NetBSD__) || defined(__OpenBSD__)
natm5_sysctl
#elif defined(FREEBSD_USRREQS)
&natm_usrreqs
#endif
},
{ SOCK_STREAM, &natmdomain, PROTO_NATMAAL0, PR_CONNREQUIRED,
0, 0, 0, 0,
#ifdef FREEBSD_USRREQS
0,
#else
natm_usrreq,
#endif
0, 0, 0, 0,
#if defined(__NetBSD__) || defined(__OpenBSD__)
natm0_sysctl
#elif defined(FREEBSD_USRREQS)
&natm_usrreqs
#endif
},
};
struct domain natmdomain =
{ AF_NATM, "natm", natm_init, 0, 0,
natmsw, &natmsw[sizeof(natmsw)/sizeof(natmsw[0])], 0,
0, 0, 0};
struct ifqueue natmintrq; /* natm packet input queue */
int natmqmaxlen = IFQ_MAXLEN; /* max # of packets on queue */
#ifdef NATM_STAT
u_int natm_sodropcnt = 0; /* # mbufs dropped due to full sb */
u_int natm_sodropbytes = 0; /* # of bytes dropped */
u_int natm_sookcnt = 0; /* # mbufs ok */
u_int natm_sookbytes = 0; /* # of bytes ok */
#endif
void natm_init()
{
LIST_INIT(&natm_pcbs);
bzero(&natmintrq, sizeof(natmintrq));
natmintrq.ifq_maxlen = natmqmaxlen;
}
#if defined(__FreeBSD__)
DOMAIN_SET(natm);
#endif

348
sys/pci/if_en_pci.c Normal file
View File

@ -0,0 +1,348 @@
/* $NetBSD: if_en_pci.c,v 1.1 1996/06/22 02:00:31 chuck Exp $ */
/*
*
* Copyright (c) 1996 Charles D. Cranor and Washington University.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Charles D. Cranor and
* Washington University.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
*
* i f _ e n _ p c i . c
*
* author: Chuck Cranor <chuck@ccrc.wustl.edu>
* started: spring, 1996.
*
* FreeBSD PCI glue for the eni155p card.
* thanks to Matt Thomas for figuring out FreeBSD vs NetBSD vs etc.. diffs.
*/
#include "en.h"
#include "pci.h"
#if (NEN > 0) && (NPCI > 0)
#include <sys/param.h>
#include <sys/types.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#ifndef SHUTDOWN_PRE_SYNC
/*
* device shutdown mechanism has been changed since 2.2-ALPHA.
* if SHUTDOWN_PRE_SYNC is defined in "sys/systm.h", use new one.
* otherwise, use old one.
* new: 2.2-ALPHA, 2.2-BETA, 2.2-GAMME, 2.2-RELEASE, 3.0
* old: 2.1.5, 2.1.6, 2.2-SNAP
* -- kjc
*/
#include <sys/devconf.h>
#endif
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <machine/cpufunc.h> /* for rdtsc proto for clock.h below */
#include <machine/clock.h> /* for DELAY */
#include <net/if.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
#include <dev/en/midwayreg.h>
#include <dev/en/midwayvar.h>
/*
* prototypes
*/
static void en_pci_attach __P((pcici_t, int));
static char *en_pci_probe __P((pcici_t, pcidi_t));
#ifdef SHUTDOWN_PRE_SYNC
static void en_pci_shutdown __P((int, void *));
#else
static int en_pci_shutdown __P((struct kern_devconf *, int));
#endif
/*
* local structures
*/
struct en_pci_softc {
/* bus independent stuff */
struct en_softc esc; /* includes "device" structure */
/* PCI bus glue */
void *sc_ih; /* interrupt handle */
pci_chipset_tag_t en_pc; /* for PCI calls */
};
/*
* pointers to softcs (we alloc)
*/
static struct en_pci_softc *enpcis[NEN] = {0};
extern struct cfdriver en_cd;
/*
* autoconfig structures
*/
static u_long en_pci_count;
static struct pci_device endevice = {
"en",
en_pci_probe,
en_pci_attach,
&en_pci_count,
#ifdef SHUTDOWN_PRE_SYNC
NULL,
#else
en_pci_shutdown,
#endif
};
DATA_SET (pcidevice_set, endevice);
/*
* local defines (PCI specific stuff)
*/
/*
* address of config base memory address register in PCI config space
* (this is card specific)
*/
#define PCI_CBMA 0x10
/*
* tonga (pci bridge). ENI cards only!
*/
#define EN_TONGA 0x60 /* PCI config addr of tonga reg */
#define TONGA_SWAP_DMA 0x80 /* endian swap control */
#define TONGA_SWAP_BYTE 0x40
#define TONGA_SWAP_WORD 0x20
/*
* adaptec pci bridge. ADP cards only!
*/
#define ADP_PCIREG 0x050040 /* PCI control register */
#define ADP_PCIREG_RESET 0x1 /* reset card */
#define ADP_PCIREG_IENABLE 0x2 /* interrupt enable */
#define ADP_PCIREG_SWAP_WORD 0x4 /* swap byte on slave access */
#define ADP_PCIREG_SWAP_DMA 0x8 /* swap byte on DMA */
#define PCI_VENDOR_EFFICIENTNETS 0x111a /* Efficent Networks */
#define PCI_PRODUCT_EFFICIENTNETS_ENI155PF 0x0000 /* ENI-155P ATM */
#define PCI_PRODUCT_EFFICIENTNETS_ENI155PA 0x0002 /* ENI-155P ATM */
#define PCI_VENDOR_ADP 0x9004 /* adaptec */
#define PCI_PRODUCT_ADP_AIC5900 0x5900
#define PCI_PRODUCT_ADP_AIC5905 0x5905
#define PCI_VENDOR(x) ((x) & 0xFFFF)
#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF)
#if !defined(MIDWAY_ENIONLY)
static void adp_busreset __P((void *));
/*
* bus specific reset function [ADP only!]
*/
static void adp_busreset(v)
void *v;
{
struct en_softc *sc = (struct en_softc *) v;
u_int32_t dummy;
bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG, ADP_PCIREG_RESET);
DELAY(1000); /* let it reset */
dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG,
(ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA|ADP_PCIREG_IENABLE));
dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
if ((dummy & (ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA)) !=
(ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA))
printf("adp_busreset: Adaptec ATM did NOT reset!\n");
}
#endif
/***********************************************************************/
/*
* autoconfig stuff
*/
static char *en_pci_probe(config_id, device_id)
pcici_t config_id;
pcidi_t device_id;
{
#if !defined(MIDWAY_ADPONLY)
if (PCI_VENDOR(device_id) == PCI_VENDOR_EFFICIENTNETS &&
(PCI_CHIPID(device_id) == PCI_PRODUCT_EFFICIENTNETS_ENI155PF ||
PCI_CHIPID(device_id) == PCI_PRODUCT_EFFICIENTNETS_ENI155PA))
return "Efficient Networks ENI-155p";
#endif
#if !defined(MIDWAY_ENIONLY)
if (PCI_VENDOR(device_id) == PCI_VENDOR_ADP &&
(PCI_CHIPID(device_id) == PCI_PRODUCT_ADP_AIC5900 ||
PCI_CHIPID(device_id) == PCI_PRODUCT_ADP_AIC5905))
return "Adaptec 155 ATM";
#endif
return 0;
}
static void en_pci_attach(config_id, unit)
pcici_t config_id;
int unit;
{
struct en_softc *sc;
struct en_pci_softc *scp;
pcidi_t device_id;
int retval;
vm_offset_t pa;
if (unit >= NEN) {
printf("en%d: not configured; kernel is built for only %d device%s.\n",
unit, NEN, NEN == 1 ? "" : "s");
return;
}
scp = (struct en_pci_softc *) malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT);
if (scp == NULL)
return;
bzero(scp, sizeof(*scp)); /* zero */
sc = &scp->esc;
retval = pci_map_mem(config_id, PCI_CBMA, (vm_offset_t *) &sc->en_base, &pa);
if (!retval) {
free((caddr_t) scp, M_DEVBUF);
return;
}
enpcis[unit] = scp; /* lock it in */
en_cd.cd_devs[unit] = sc; /* fake a cfdriver structure */
en_cd.cd_ndevs = NEN;
sprintf(sc->sc_dev.dv_xname, "en%d", unit);
sc->enif.if_unit = unit;
sc->enif.if_name = "en";
/*
* figure out if we are an adaptec card or not.
* XXX: why do we have to re-read PC_ID_REG when en_pci_probe already
* had that info?
*/
device_id = pci_conf_read(config_id, PCI_ID_REG);
sc->is_adaptec = (PCI_VENDOR(device_id) == PCI_VENDOR_ADP) ? 1 : 0;
#ifdef SHUTDOWN_PRE_SYNC
/*
* Add shutdown hook so that DMA is disabled prior to reboot. Not
* doing so could allow DMA to corrupt kernel memory during the
* reboot before the driver initializes.
*/
at_shutdown(en_pci_shutdown, scp, SHUTDOWN_POST_SYNC);
#endif
if (!pci_map_int(config_id, en_intr, (void *) sc, &net_imask)) {
printf("%s: couldn't establish interrupt\n", sc->sc_dev.dv_xname);
return;
}
sc->ipl = 1; /* XXX */
/*
* set up pci bridge
*/
#if !defined(MIDWAY_ENIONLY)
if (sc->is_adaptec) {
sc->en_busreset = adp_busreset;
adp_busreset(sc);
}
#endif
#if !defined(MIDWAY_ADPONLY)
if (!sc->is_adaptec) {
sc->en_busreset = NULL;
pci_conf_write(config_id, EN_TONGA, (TONGA_SWAP_DMA|TONGA_SWAP_WORD));
}
#endif
/*
* done PCI specific stuff
*/
en_attach(sc);
}
#ifdef SHUTDOWN_PRE_SYNC
static void
en_pci_shutdown(
int howto,
void *sc)
{
struct en_pci_softc *psc = (struct en_pci_softc *)sc;
en_reset(&psc->esc);
DELAY(10);
}
#else /* !SHUTDOWN_PRE_SYNC */
static int
en_pci_shutdown(kdc, force)
struct kern_devconf *kdc;
int force;
{
if (kdc->kdc_unit < NEN) {
struct en_pci_softc *psc = enpcis[kdc->kdc_unit];
if (psc) /* can it be null? */
en_reset(&psc->esc);
DELAY(10);
}
dev_detach(kdc);
return(0);
}
#endif /* !SHUTDOWN_PRE_SYNC */
#endif /* NEN > 0 && NPCI > 0 */