summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/oltr/if_oltr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/oltr/if_oltr.c')
-rw-r--r--sys/contrib/dev/oltr/if_oltr.c1094
1 files changed, 1094 insertions, 0 deletions
diff --git a/sys/contrib/dev/oltr/if_oltr.c b/sys/contrib/dev/oltr/if_oltr.c
new file mode 100644
index 0000000..1f62d41
--- /dev/null
+++ b/sys/contrib/dev/oltr/if_oltr.c
@@ -0,0 +1,1094 @@
+/*
+ * Copyright (c) 1998, Larry Lile
+ * All rights reserved.
+ *
+ * For latest sources and information on this driver, please
+ * go to http://anarchy.stdio.com.
+ *
+ * Questions, comments or suggestions should be directed to
+ * Larry Lile <lile@stdio.com>.
+ *
+ * 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 unmodified, 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/iso88025.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/bpf.h>
+
+#ifndef BPF_MTAP
+#define BPF_MTAP(_ifp, _m) do { \
+ if ((_ifp)->if_bpf) \
+ bpf_mtap((_ifp), (_m)); \
+} while (0)
+#endif
+
+#include <vm/vm.h> /* for vtophys */
+#include <vm/pmap.h> /* for vtophys */
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include "contrib/dev/oltr/trlld.h"
+#include "contrib/dev/oltr/if_oltrvar.h"
+
+/*
+ * Glue function prototypes for PMW kit IO
+ */
+
+#ifndef TRlldInlineIO
+static void DriverOutByte __P((unsigned short, unsigned char));
+static void DriverOutWord __P((unsigned short, unsigned short));
+static void DriverOutDword __P((unsigned short, unsigned long));
+static void DriverRepOutByte __P((unsigned short, unsigned char *, int));
+static void DriverRepOutWord __P((unsigned short, unsigned short *, int));
+static void DriverRepOutDword __P((unsigned short, unsigned long *, int));
+static unsigned char DriverInByte __P((unsigned short));
+static unsigned short DriverInWord __P((unsigned short));
+static unsigned long DriverInDword __P((unsigned short));
+static void DriverRepInByte __P((unsigned short, unsigned char *, int));
+static void DriverRepInWord __P((unsigned short, unsigned short *, int));
+static void DriverRepInDword __P((unsigned short, unsigned long *, int));
+#endif /*TRlldInlineIO*/
+static void DriverSuspend __P((unsigned short));
+static void DriverStatus __P((void *, TRlldStatus_t *));
+static void DriverCloseCompleted __P((void *));
+static void DriverStatistics __P((void *, TRlldStatistics_t *));
+static void DriverTransmitFrameCompleted __P((void *, void *, int));
+static void DriverReceiveFrameCompleted __P((void *, int, int, void *, int));
+
+TRlldDriver_t LldDriver = {
+ TRLLD_VERSION,
+#ifndef TRlldInlineIO
+ DriverOutByte,
+ DriverOutWord,
+ DriverOutDword,
+ DriverRepOutByte,
+ DriverRepOutWord,
+ DriverRepOutDword,
+ DriverInByte,
+ DriverInWord,
+ DriverInDword,
+ DriverRepInByte,
+ DriverRepInWord,
+ DriverRepInDword,
+#endif /*TRlldInlineIO*/
+ DriverSuspend,
+ DriverStatus,
+ DriverCloseCompleted,
+ DriverStatistics,
+ DriverTransmitFrameCompleted,
+ DriverReceiveFrameCompleted,
+};
+
+
+static void oltr_start __P((struct ifnet *));
+static void oltr_close __P((struct oltr_softc *));
+static void oltr_init __P((void *));
+static int oltr_ioctl __P((struct ifnet *, u_long, caddr_t));
+static void oltr_intr __P((void *));
+static int oltr_ifmedia_upd __P((struct ifnet *));
+static void oltr_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
+
+
+
+int
+oltr_attach(device_t dev)
+{
+
+ struct oltr_softc *sc = device_get_softc(dev);
+ struct ifnet *ifp;
+ int rc = 0;
+ int media = IFM_TOKEN|IFM_TOK_UTP16;
+
+ ifp = sc->ifp = if_alloc(IFT_ISO88025);
+ if (ifp == NULL) {
+ device_printf(dev, "couldn't if_alloc()");
+ return (-1);
+ }
+
+ /*
+ * Allocate interrupt and DMA channel
+ */
+
+ sc->irq_rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
+ (sc->config.mode & TRLLD_MODE_SHARE_INTERRUPT) ?
+ RF_ACTIVE | RF_SHAREABLE : RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "couldn't map interrupt\n");
+ if_free(ifp);
+ return (-1);
+ }
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, NULL, oltr_intr,
+ sc, &sc-> oltr_intrhand)) {
+ device_printf(dev, "couldn't setup interrupt\n");
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if_free(ifp);
+ return (-1);
+ }
+
+ /*
+ * Do the ifnet initialization
+ */
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_init = oltr_init;
+ ifp->if_start = oltr_start;
+ ifp->if_ioctl = oltr_ioctl;
+ ifp->if_flags = IFF_BROADCAST | IFF_NEEDSGIANT;
+ ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+
+ /*
+ * Do ifmedia setup.
+ */
+ ifmedia_init(&sc->ifmedia, 0, oltr_ifmedia_upd, oltr_ifmedia_sts);
+ rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
+ switch(sc->config.type) {
+ case TRLLD_ADAPTER_PCI7: /* OC-3540 */
+ ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP100, 0, NULL);
+ /* FALL THROUGH */
+ case TRLLD_ADAPTER_PCI4: /* OC-3139 */
+ case TRLLD_ADAPTER_PCI5: /* OC-3140 */
+ case TRLLD_ADAPTER_PCI6: /* OC-3141 */
+ ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_AUTO, 0, NULL);
+ media = IFM_TOKEN|IFM_AUTO;
+ rc = TRlldSetSpeed(sc->TRlldAdapter, 0);
+ /* FALL THROUGH */
+ default:
+ ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP4, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16, 0, NULL);
+ break;
+ }
+ sc->ifmedia.ifm_media = media;
+ ifmedia_set(&sc->ifmedia, media);
+
+ /*
+ * Attach the interface
+ */
+
+ iso88025_ifattach(ifp, sc->config.macaddress, ISO88025_BPF_SUPPORTED);
+
+ return(0);
+}
+
+
+static void
+oltr_intr(void *xsc)
+{
+ struct oltr_softc *sc = (struct oltr_softc *)xsc;
+
+ if (DEBUG_MASK & DEBUG_INT)
+ printf("I");
+
+ TRlldInterruptService(sc->TRlldAdapter);
+
+ return;
+}
+
+static void
+oltr_start(struct ifnet *ifp)
+{
+ struct oltr_softc *sc = ifp->if_softc;
+ struct mbuf *m0, *m;
+ int copy_len, buffer, frame, fragment, rc, s;
+
+ /*
+ * Check to see if output is already active
+ */
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
+ return;
+
+outloop:
+
+ /*
+ * Make sure we have buffers to transmit with
+ */
+ if (sc->tx_avail <= 0) {
+ printf("oltr%d: tx queue full\n", sc->unit);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ return;
+ }
+
+ if (sc->restart == NULL) {
+ IF_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ return;
+ } else {
+ m = sc->restart;
+ sc->restart = NULL;
+ }
+
+ m0 = m;
+ frame = RING_BUFFER(sc->tx_frame);
+ buffer = RING_BUFFER(sc->tx_head);
+ fragment = 0;
+ copy_len = 0;
+ sc->frame_ring[frame].FragmentCount = 0;
+
+ while (copy_len < m0->m_pkthdr.len) {
+ sc->frame_ring[frame].FragmentCount++;
+ if (sc->frame_ring[frame].FragmentCount > sc->tx_avail)
+ goto nobuffers;
+ sc->frame_ring[frame].TransmitFragment[fragment].VirtualAddress = sc->tx_ring[buffer].data;
+ sc->frame_ring[frame].TransmitFragment[fragment].PhysicalAddress = sc->tx_ring[buffer].address;
+ sc->frame_ring[frame].TransmitFragment[fragment].count = MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN);
+ m_copydata(m0, copy_len, MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN), sc->tx_ring[buffer].data);
+ copy_len += MIN(m0->m_pkthdr.len - copy_len, TX_BUFFER_LEN);
+ fragment++;
+ buffer = RING_BUFFER((buffer + 1));
+ }
+
+ s = splimp();
+ rc = TRlldTransmitFrame(sc->TRlldAdapter, &sc->frame_ring[frame], (void *)&sc->frame_ring[frame]);
+ (void)splx(s);
+
+ if (rc != TRLLD_TRANSMIT_OK) {
+ printf("oltr%d: TRlldTransmitFrame returned %d\n", sc->unit, rc);
+ ifp->if_oerrors++;
+ goto bad;
+ }
+
+ sc->tx_avail -= sc->frame_ring[frame].FragmentCount;
+ sc->tx_head = RING_BUFFER((sc->tx_head + sc->frame_ring[frame].FragmentCount));
+ sc->tx_frame++;
+
+ BPF_MTAP(ifp, m0);
+ /*ifp->if_opackets++;*/
+
+bad:
+ m_freem(m0);
+
+ goto outloop;
+
+nobuffers:
+
+ printf("oltr%d: queue full\n", sc->unit);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ ifp->if_oerrors++;
+ /*m_freem(m0);*/
+ sc->restart = m0;
+
+ return;
+}
+
+static void
+oltr_close(struct oltr_softc *sc)
+{
+ /*printf("oltr%d: oltr_close\n", sc->unit);*/
+
+ oltr_stop(sc);
+
+ tsleep(sc, PWAIT, "oltrclose", 30*hz);
+}
+
+void
+oltr_stop(struct oltr_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
+
+ /*printf("oltr%d: oltr_stop\n", sc->unit);*/
+
+ ifp->if_flags &= ~IFF_UP;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ TRlldClose(sc->TRlldAdapter, 0);
+ sc->state = OL_CLOSING;
+}
+
+static void
+oltr_init(void * xsc)
+{
+ struct oltr_softc *sc = (struct oltr_softc *)xsc;
+ struct ifnet *ifp = sc->ifp;
+ struct ifmedia *ifm = &sc->ifmedia;
+ int poll = 0, i, rc = 0, s;
+ int work_size;
+
+ /*
+ * Check adapter state, don't allow multiple inits
+ */
+ if (sc->state > OL_CLOSED) {
+ printf("oltr%d: adapter not ready\n", sc->unit);
+ return;
+ }
+
+ s = splimp();
+
+ /*
+ * Initialize Adapter
+ */
+ if ((rc = TRlldAdapterInit(&LldDriver, sc->TRlldAdapter, sc->TRlldAdapter_phys,
+ (void *)sc, &sc->config)) != TRLLD_INIT_OK) {
+ switch(rc) {
+ case TRLLD_INIT_NOT_FOUND:
+ printf("oltr%d: adapter not found\n", sc->unit);
+ break;
+ case TRLLD_INIT_UNSUPPORTED:
+ printf("oltr%d: adapter not supported by low level driver\n", sc->unit);
+ break;
+ case TRLLD_INIT_PHYS16:
+ printf("oltr%d: adapter memory block above 16M cannot DMA\n", sc->unit);
+ break;
+ case TRLLD_INIT_VERSION:
+ printf("oltr%d: low level driver version mismatch\n", sc->unit);
+ break;
+ default:
+ printf("oltr%d: unknown init error %d\n", sc->unit, rc);
+ break;
+ }
+ goto init_failed;
+ }
+ sc->state = OL_INIT;
+
+ switch(sc->config.type) {
+ case TRLLD_ADAPTER_PCI4: /* OC-3139 */
+ work_size = 32 * 1024;
+ break;
+ case TRLLD_ADAPTER_PCI7: /* OC-3540 */
+ work_size = 256;
+ break;
+ default:
+ work_size = 0;
+ }
+
+ if (work_size) {
+ if ((sc->work_memory = malloc(work_size, M_DEVBUF, M_NOWAIT)) == NULL) {
+ printf("oltr%d: failed to allocate work memory (%d octets).\n", sc->unit, work_size);
+ } else {
+ TRlldAddMemory(sc->TRlldAdapter, sc->work_memory,
+ vtophys(sc->work_memory), work_size);
+ }
+ }
+
+ switch(IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */
+ break;
+ case IFM_TOK_UTP4:
+ rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
+ break;
+ case IFM_TOK_UTP16:
+ rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
+ break;
+ case IFM_TOK_UTP100:
+ rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS);
+ break;
+ }
+
+ /*
+ * Download adapter micro-code
+ */
+ if (bootverbose)
+ printf("oltr%d: Downloading adapter microcode: ", sc->unit);
+
+ switch(sc->config.mactype) {
+ case TRLLD_MAC_TMS:
+ rc = TRlldDownload(sc->TRlldAdapter, TRlldMacCode);
+ if (bootverbose)
+ printf("TMS-380");
+ break;
+ case TRLLD_MAC_HAWKEYE:
+ rc = TRlldDownload(sc->TRlldAdapter, TRlldHawkeyeMac);
+ if (bootverbose)
+ printf("Hawkeye");
+ break;
+ case TRLLD_MAC_BULLSEYE:
+ rc = TRlldDownload(sc->TRlldAdapter, TRlldBullseyeMac);
+ if (bootverbose)
+ printf("Bullseye");
+ break;
+ default:
+ if (bootverbose)
+ printf("unknown - failed!\n");
+ goto init_failed;
+ break;
+ }
+
+ /*
+ * Check download status
+ */
+ switch(rc) {
+ case TRLLD_DOWNLOAD_OK:
+ if (bootverbose)
+ printf(" - ok\n");
+ break;
+ case TRLLD_DOWNLOAD_ERROR:
+ if (bootverbose)
+ printf(" - failed\n");
+ else
+ printf("oltr%d: adapter microcode download failed\n", sc->unit);
+ goto init_failed;
+ break;
+ case TRLLD_STATE:
+ if (bootverbose)
+ printf(" - not ready\n");
+ goto init_failed;
+ break;
+ }
+
+ /*
+ * Wait for self-test to complete
+ */
+ i = 0;
+ while ((poll++ < SELF_TEST_POLLS) && (sc->state < OL_READY)) {
+ if (DEBUG_MASK & DEBUG_INIT)
+ printf("p");
+ DELAY(TRlldPoll(sc->TRlldAdapter) * 1000);
+ if (TRlldInterruptService(sc->TRlldAdapter) != 0)
+ if (DEBUG_MASK & DEBUG_INIT) printf("i");
+ }
+
+ if (sc->state != OL_CLOSED) {
+ printf("oltr%d: self-test failed\n", sc->unit);
+ goto init_failed;
+ }
+
+ /*
+ * Set up adapter poll
+ */
+ callout_handle_init(&sc->oltr_poll_ch);
+ sc->oltr_poll_ch = timeout(oltr_poll, (void *)sc, 1);
+
+ sc->state = OL_OPENING;
+
+ /*
+ * Open the adapter
+ */
+ rc = TRlldOpen(sc->TRlldAdapter, IF_LLADDR(sc->ifp), sc->GroupAddress,
+ sc->FunctionalAddress, 1552, sc->AdapterMode);
+ switch(rc) {
+ case TRLLD_OPEN_OK:
+ break;
+ case TRLLD_OPEN_STATE:
+ printf("oltr%d: adapter not ready for open\n", sc->unit);
+ (void)splx(s);
+ return;
+ case TRLLD_OPEN_ADDRESS_ERROR:
+ printf("oltr%d: illegal MAC address\n", sc->unit);
+ (void)splx(s);
+ return;
+ case TRLLD_OPEN_MODE_ERROR:
+ printf("oltr%d: illegal open mode\n", sc->unit);
+ (void)splx(s);
+ return;
+ default:
+ printf("oltr%d: unknown open error (%d)\n", sc->unit, rc);
+ (void)splx(s);
+ return;
+ }
+
+ /*
+ * Set promiscious mode for now...
+ */
+ TRlldSetPromiscuousMode(sc->TRlldAdapter, TRLLD_PROM_LLC);
+ ifp->if_flags |= IFF_PROMISC;
+
+ /*
+ * Block on the ring insert and set a timeout
+ */
+ tsleep(sc, PWAIT, "oltropen", 30*hz);
+
+ /*
+ * Set up receive buffer ring
+ */
+ for (i = 0; i < RING_BUFFER_LEN; i++) {
+ rc = TRlldReceiveFragment(sc->TRlldAdapter, (void *)sc->rx_ring[i].data,
+ sc->rx_ring[i].address, RX_BUFFER_LEN, (void *)sc->rx_ring[i].index);
+ if (rc != TRLLD_RECEIVE_OK) {
+ printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc);
+ break;
+ }
+ }
+
+ sc->tx_avail = RING_BUFFER_LEN;
+ sc->tx_head = 0;
+ sc->tx_frame = 0;
+
+ sc->restart = NULL;
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ /*
+ * Set up adapter statistics poll
+ */
+ /*callout_handle_init(&sc->oltr_stat_ch);*/
+ /*sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);*/
+
+ (void)splx(s);
+ return;
+
+init_failed:
+ sc->state = OL_DEAD;
+ (void)splx(s);
+ return;
+}
+
+static int
+oltr_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct oltr_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ int error = 0, s;
+
+ s = splimp();
+
+ switch(command) {
+ case SIOCSIFADDR:
+ case SIOCGIFADDR:
+ case SIOCSIFMTU:
+ error = iso88025_ioctl(ifp, command, data);
+ break;
+
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ oltr_init(sc);
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ oltr_close(sc);
+ }
+ }
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ (void)splx(s);
+
+ return(error);
+}
+
+
+void
+oltr_poll(void *arg)
+{
+ struct oltr_softc *sc = (struct oltr_softc *)arg;
+ int s;
+
+ s = splimp();
+
+ if (DEBUG_MASK & DEBUG_POLL) printf("P");
+
+ /* Set up next adapter poll */
+ sc->oltr_poll_ch = timeout(oltr_poll, (void *)sc, (TRlldPoll(sc->TRlldAdapter) * hz / 1000));
+
+ (void)splx(s);
+}
+
+#ifdef NOTYET
+void
+oltr_stat(void *arg)
+{
+ struct oltr_softc *sc = (struct oltr_softc *)arg;
+ int s;
+
+ s = splimp();
+
+ /* Set up next adapter poll */
+ sc->oltr_stat_ch = timeout(oltr_stat, (void *)sc, 1*hz);
+ if (TRlldGetStatistics(sc->TRlldAdapter, &sc->current, 0) != 0) {
+ /*printf("oltr%d: statistics available immediately...\n", sc->unit);*/
+ DriverStatistics((void *)sc, &sc->current);
+ }
+
+ (void)splx(s);
+}
+#endif
+static int
+oltr_ifmedia_upd(struct ifnet *ifp)
+{
+ struct oltr_softc *sc = ifp->if_softc;
+ struct ifmedia *ifm = &sc->ifmedia;
+ int rc;
+
+ if (IFM_TYPE(ifm->ifm_media) != IFM_TOKEN)
+ return(EINVAL);
+
+ switch(IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_AUTO:
+ rc = TRlldSetSpeed(sc->TRlldAdapter, 0); /* TRLLD_SPEED_AUTO */
+ break;
+ case IFM_TOK_UTP4:
+ rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_4MBPS);
+ break;
+ case IFM_TOK_UTP16:
+ rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
+ break;
+ case IFM_TOK_UTP100:
+ rc = TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_100MBPS);
+ break;
+ default:
+ return(EINVAL);
+ break;
+ }
+
+ return(0);
+
+}
+
+static void
+oltr_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct oltr_softc *sc = ifp->if_softc;
+ struct ifmedia *ifm = &sc->ifmedia;
+
+ /*printf("oltr%d: oltr_ifmedia_sts\n", sc->unit);*/
+
+ ifmr->ifm_active = IFM_TYPE(ifm->ifm_media)|IFM_SUBTYPE(ifm->ifm_media);
+
+}
+
+/*
+ * ---------------------- PMW Callback Functions -----------------------
+ */
+
+void
+DriverStatistics(void *DriverHandle, TRlldStatistics_t *statistics)
+{
+#ifdef NOTYET
+ struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
+
+ if (sc->statistics.LineErrors != statistics->LineErrors)
+ printf("oltr%d: Line Errors %lu\n", sc->unit,
+ statistics->LineErrors);
+ if (sc->statistics.InternalErrors != statistics->InternalErrors)
+ printf("oltr%d: Internal Errors %lu\n", sc->unit,
+ statistics->InternalErrors);
+ if (sc->statistics.BurstErrors != statistics->BurstErrors)
+ printf("oltr%d: Burst Errors %lu\n", sc->unit,
+ statistics->BurstErrors);
+ if (sc->statistics.AbortDelimiters != statistics->AbortDelimiters)
+ printf("oltr%d: Abort Delimiters %lu\n", sc->unit,
+ statistics->AbortDelimiters);
+ if (sc->statistics.ARIFCIErrors != statistics->ARIFCIErrors)
+ printf("oltr%d: ARIFCI Errors %lu\n", sc->unit,
+ statistics->ARIFCIErrors);
+ if (sc->statistics.LostFrames != statistics->LostFrames)
+ printf("oltr%d: Lost Frames %lu\n", sc->unit,
+ statistics->LostFrames);
+ if (sc->statistics.CongestionErrors != statistics->CongestionErrors)
+ printf("oltr%d: Congestion Errors %lu\n", sc->unit,
+ statistics->CongestionErrors);
+ if (sc->statistics.FrequencyErrors != statistics->FrequencyErrors)
+ printf("oltr%d: Frequency Errors %lu\n", sc->unit,
+ statistics->FrequencyErrors);
+ if (sc->statistics.TokenErrors != statistics->TokenErrors)
+ printf("oltr%d: Token Errors %lu\n", sc->unit,
+ statistics->TokenErrors);
+ if (sc->statistics.DMABusErrors != statistics->DMABusErrors)
+ printf("oltr%d: DMA Bus Errors %lu\n", sc->unit,
+ statistics->DMABusErrors);
+ if (sc->statistics.DMAParityErrors != statistics->DMAParityErrors)
+ printf("oltr%d: DMA Parity Errors %lu\n", sc->unit,
+ statistics->DMAParityErrors);
+ if (sc->statistics.ReceiveLongFrame != statistics->ReceiveLongFrame)
+ printf("oltr%d: Long frames received %lu\n", sc->unit,
+ statistics->ReceiveLongFrame);
+ if (sc->statistics.ReceiveCRCErrors != statistics->ReceiveCRCErrors)
+ printf("oltr%d: Receive CRC Errors %lu\n", sc->unit,
+ statistics->ReceiveCRCErrors);
+ if (sc->statistics.ReceiveOverflow != statistics->ReceiveOverflow)
+ printf("oltr%d: Recieve overflows %lu\n", sc->unit,
+ statistics->ReceiveOverflow);
+ if (sc->statistics.TransmitUnderrun != statistics->TransmitUnderrun)
+ printf("oltr%d: Frequency Errors %lu\n", sc->unit,
+ statistics->TransmitUnderrun);
+ bcopy(statistics, &sc->statistics, sizeof(TRlldStatistics_t));
+#endif
+}
+
+static void
+DriverSuspend(unsigned short MicroSeconds)
+{
+ DELAY(MicroSeconds);
+}
+
+
+static void
+DriverStatus(void *DriverHandle, TRlldStatus_t *Status)
+{
+ struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
+ struct ifnet *ifp = sc->ifp;
+
+ char *Protocol[] = { /* 0 */ "Unknown",
+ /* 1 */ "TKP",
+ /* 2 */ "TXI" };
+ char *Timeout[] = { /* 0 */ "command",
+ /* 1 */ "transmit",
+ /* 2 */ "interrupt" };
+
+ switch (Status->Type) {
+
+ case TRLLD_STS_ON_WIRE:
+ printf("oltr%d: ring insert (%d Mbps - %s)\n", sc->unit,
+ Status->Specification.OnWireInformation.Speed,
+ Protocol[Status->Specification.OnWireInformation.AccessProtocol]);
+ sc->state = OL_OPEN;
+ wakeup(sc);
+ break;
+ case TRLLD_STS_SELFTEST_STATUS:
+ if (Status->Specification.SelftestStatus == TRLLD_ST_OK) {
+ sc->state = OL_CLOSED;
+ if (bootverbose)
+ printf("oltr%d: self test complete\n", sc->unit);
+ }
+ if (Status->Specification.SelftestStatus & TRLLD_ST_ERROR) {
+ printf("oltr%d: Adapter self test error %d", sc->unit,
+ Status->Specification.SelftestStatus & ~TRLLD_ST_ERROR);
+ sc->state = OL_DEAD;
+ }
+ if (Status->Specification.SelftestStatus & TRLLD_ST_TIMEOUT) {
+ printf("oltr%d: Adapter self test timed out.\n", sc->unit);
+ sc->state = OL_DEAD;
+ }
+ break;
+ case TRLLD_STS_INIT_STATUS:
+ if (Status->Specification.InitStatus == 0x800) {
+ oltr_stop(sc);
+ ifmedia_set(&sc->ifmedia, IFM_TOKEN|IFM_TOK_UTP16);
+ TRlldSetSpeed(sc->TRlldAdapter, TRLLD_SPEED_16MBPS);
+ oltr_init(sc);
+ break;
+ }
+ printf("oltr%d: adapter init failure 0x%03x\n", sc->unit,
+ Status->Specification.InitStatus);
+ oltr_stop(sc);
+ break;
+ case TRLLD_STS_RING_STATUS:
+ if (Status->Specification.RingStatus) {
+ printf("oltr%d: Ring status change: ", sc->unit);
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_SIGNAL_LOSS)
+ printf(" [Signal Loss]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_HARD_ERROR)
+ printf(" [Hard Error]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_SOFT_ERROR)
+ printf(" [Soft Error]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_TRANSMIT_BEACON)
+ printf(" [Beacon]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_LOBE_WIRE_FAULT)
+ printf(" [Wire Fault]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_AUTO_REMOVAL_ERROR)
+ printf(" [Auto Removal]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_REMOVE_RECEIVED)
+ printf(" [Remove Received]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_COUNTER_OVERFLOW)
+ printf(" [Counter Overflow]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_SINGLE_STATION)
+ printf(" [Single Station]");
+ if (Status->Specification.RingStatus &
+ TRLLD_RS_RING_RECOVERY)
+ printf(" [Ring Recovery]");
+ printf("\n");
+ }
+ break;
+ case TRLLD_STS_ADAPTER_CHECK:
+ printf("oltr%d: adapter check (%04x %04x %04x %04x)\n", sc->unit,
+ Status->Specification.AdapterCheck[0],
+ Status->Specification.AdapterCheck[1],
+ Status->Specification.AdapterCheck[2],
+ Status->Specification.AdapterCheck[3]);
+ sc->state = OL_DEAD;
+ oltr_stop(sc);
+ break;
+ case TRLLD_STS_PROMISCUOUS_STOPPED:
+ printf("oltr%d: promiscuous mode ", sc->unit);
+ if (Status->Specification.PromRemovedCause == 1)
+ printf("remove received.");
+ if (Status->Specification.PromRemovedCause == 2)
+ printf("poll failure.");
+ if (Status->Specification.PromRemovedCause == 2)
+ printf("buffer size failure.");
+ printf("\n");
+ ifp->if_flags &= ~IFF_PROMISC;
+ break;
+ case TRLLD_STS_LLD_ERROR:
+ printf("oltr%d: low level driver internal error ", sc->unit);
+ printf("(%04x %04x %04x %04x).\n",
+ Status->Specification.InternalError[0],
+ Status->Specification.InternalError[1],
+ Status->Specification.InternalError[2],
+ Status->Specification.InternalError[3]);
+ sc->state = OL_DEAD;
+ oltr_stop(sc);
+ break;
+ case TRLLD_STS_ADAPTER_TIMEOUT:
+ printf("oltr%d: adapter %s timeout.\n", sc->unit,
+ Timeout[Status->Specification.AdapterTimeout]);
+ break;
+ default:
+ printf("oltr%d: driver status Type = %d\n", sc->unit, Status->Type);
+ break;
+
+ }
+ if (Status->Closed) {
+ sc->state = OL_CLOSING;
+ oltr_stop(sc);
+ }
+
+}
+
+static void
+DriverCloseCompleted(void *DriverHandle)
+{
+ struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
+
+ printf("oltr%d: adapter closed\n", sc->unit);
+ wakeup(sc);
+ sc->state = OL_CLOSED;
+}
+
+static void
+DriverTransmitFrameCompleted(void *DriverHandle, void *FrameHandle, int TransmitStatus)
+{
+ struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
+ struct ifnet *ifp = sc->ifp;
+ TRlldTransmit_t *frame = (TRlldTransmit_t *)FrameHandle;
+
+ /*printf("oltr%d: DriverTransmitFrameCompleted\n", sc->unit);*/
+
+ if (TransmitStatus != TRLLD_TRANSMIT_OK) {
+ ifp->if_oerrors++;
+ printf("oltr%d: transmit error %d\n", sc->unit, TransmitStatus);
+ } else {
+ ifp->if_opackets++;
+ }
+
+ sc->tx_avail += frame->FragmentCount;
+
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
+ printf("oltr%d: queue restart\n", sc->unit);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ oltr_start(ifp);
+ }
+
+
+}
+
+static void
+DriverReceiveFrameCompleted(void *DriverHandle, int ByteCount, int FragmentCount, void *FragmentHandle, int ReceiveStatus)
+{
+ struct oltr_softc *sc = (struct oltr_softc *)DriverHandle;
+ struct ifnet *ifp = sc->ifp;
+ struct mbuf *m0, *m1, *m;
+ int frame_len = ByteCount, i = (int)FragmentHandle, rc, s;
+ int mbuf_offset, mbuf_size, frag_offset, copy_length;
+ char *fragment = sc->rx_ring[RING_BUFFER(i)].data;
+
+ if (sc->state > OL_CLOSED) {
+ if (ReceiveStatus == TRLLD_RCV_OK) {
+ MGETHDR(m0, M_DONTWAIT, MT_DATA);
+ mbuf_size = MHLEN - 2;
+ if (!m0) {
+ ifp->if_ierrors++;
+ goto dropped;
+ }
+ if (ByteCount + 2 > MHLEN) {
+ MCLGET(m0, M_DONTWAIT);
+ mbuf_size = MCLBYTES - 2;
+ if (!(m0->m_flags & M_EXT)) {
+ m_freem(m0);
+ ifp->if_ierrors++;
+ goto dropped;
+ }
+ }
+ m0->m_pkthdr.rcvif = ifp;
+ m0->m_pkthdr.len = ByteCount;
+ m0->m_len = 0;
+ m0->m_data += 2;
+
+ m = m0;
+ mbuf_offset = 0;
+ frag_offset = 0;
+ while (frame_len) {
+ copy_length = MIN3(frame_len,
+ (RX_BUFFER_LEN - frag_offset),
+ (mbuf_size - mbuf_offset));
+ bcopy(fragment + frag_offset, mtod(m, char *) +
+ mbuf_offset, copy_length);
+ m->m_len += copy_length;
+ mbuf_offset += copy_length;
+ frag_offset += copy_length;
+ frame_len -= copy_length;
+
+ if (frag_offset == RX_BUFFER_LEN) {
+ fragment =
+ sc->rx_ring[RING_BUFFER(++i)].data;
+ frag_offset = 0;
+ }
+ if ((mbuf_offset == mbuf_size) && (frame_len > 0)) {
+ MGET(m1, M_DONTWAIT, MT_DATA);
+ mbuf_size = MHLEN;
+ if (!m1) {
+ ifp->if_ierrors++;
+ m_freem(m0);
+ goto dropped;
+ }
+ if (frame_len > MHLEN) {
+ MCLGET(m1, M_DONTWAIT);
+ mbuf_size = MCLBYTES;
+ if (!(m1->m_flags & M_EXT)) {
+ m_freem(m0);
+ m_freem(m1);
+ ifp->if_ierrors++;
+ goto dropped;
+ }
+ }
+ m->m_next = m1;
+ m = m1;
+ mbuf_offset = 0;
+ m->m_len = 0;
+ }
+ }
+ iso88025_input(ifp, m0);
+ } else { /* Receiver error */
+ if (ReceiveStatus != TRLLD_RCV_NO_DATA) {
+ printf("oltr%d: receive error %d\n", sc->unit,
+ ReceiveStatus);
+ ifp->if_ierrors++;
+ }
+ }
+
+dropped:
+ s = splimp();
+ i = (int)FragmentHandle;
+ while (FragmentCount--) {
+ rc = TRlldReceiveFragment(sc->TRlldAdapter,
+ (void *)sc->rx_ring[RING_BUFFER(i)].data,
+ sc->rx_ring[RING_BUFFER(i)].address,
+ RX_BUFFER_LEN, (void *)sc->rx_ring[RING_BUFFER(i)].index);
+ if (rc != TRLLD_RECEIVE_OK) {
+ printf("oltr%d: adapter refused receive fragment %d (rc = %d)\n", sc->unit, i, rc);
+ break;
+ }
+ i++;
+ }
+ (void)splx(s);
+ }
+}
+
+
+/*
+ * ---------------------------- PMW Glue -------------------------------
+ */
+
+#ifndef TRlldInlineIO
+
+static void
+DriverOutByte(unsigned short IOAddress, unsigned char value)
+{
+ outbv(IOAddress, value);
+}
+
+static void
+DriverOutWord(unsigned short IOAddress, unsigned short value)
+{
+ outw(IOAddress, value);
+}
+
+static void
+DriverOutDword(unsigned short IOAddress, unsigned long value)
+{
+ outl(IOAddress, value);
+}
+
+static void
+DriverRepOutByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount)
+{
+ outsb(IOAddress, (void *)DataPointer, ByteCount);
+}
+
+static void
+DriverRepOutWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount)
+{
+ outsw(IOAddress, (void *)DataPointer, WordCount);
+}
+
+static void
+DriverRepOutDword(unsigned short IOAddress, unsigned long *DataPointer, int DWordCount)
+{
+ outsl(IOAddress, (void *)DataPointer, DWordCount);
+}
+
+static unsigned char
+DriverInByte(unsigned short IOAddress)
+{
+ return(inbv(IOAddress));
+}
+
+static unsigned short
+DriverInWord(unsigned short IOAddress)
+{
+ return(inw(IOAddress));
+}
+
+static unsigned long
+DriverInDword(unsigned short IOAddress)
+{
+ return(inl(IOAddress));
+}
+
+static void
+DriverRepInByte(unsigned short IOAddress, unsigned char *DataPointer, int ByteCount)
+{
+ insb(IOAddress, (void *)DataPointer, ByteCount);
+}
+
+static void
+DriverRepInWord(unsigned short IOAddress, unsigned short *DataPointer, int WordCount)
+{
+ insw(IOAddress, (void *)DataPointer, WordCount);
+}
+static void
+DriverRepInDword( unsigned short IOAddress, unsigned long *DataPointer, int DWordCount)
+{
+ insl(IOAddress, (void *)DataPointer, DWordCount);
+}
+#endif /* TRlldInlineIO */
OpenPOWER on IntegriCloud