2 * Copyright (c) 1998, Larry Lile
5 * For latest sources and information on this driver, please
6 * go to http://anarchy.stdio.com.
8 * Questions, comments or suggestions should be directed to
9 * Larry Lile <lile@stdio.com>.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice unmodified, this list of conditions, and the following
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/param.h>
37 #include <sys/malloc.h>
38 #include <sys/kernel.h>
39 #include <sys/module.h>
40 #include <sys/socket.h>
43 #include <net/if_arp.h>
44 #include <net/iso88025.h>
45 #include <net/if_media.h>
48 #include <vm/vm.h> /* for vtophys */
49 #include <vm/pmap.h> /* for vtophys */
51 #include <machine/bus.h>
52 #include <machine/resource.h>
57 #if (__FreeBSD_version < 500000)
58 #include <pci/pcireg.h>
59 #include <pci/pcivar.h>
61 #include <dev/pci/pcireg.h>
62 #include <dev/pci/pcivar.h>
65 #include "contrib/dev/oltr/trlld.h"
66 #include "contrib/dev/oltr/if_oltrvar.h"
68 static int oltr_pci_probe __P((device_t));
69 static int oltr_pci_attach __P((device_t));
70 static int oltr_pci_detach __P((device_t));
71 static void oltr_pci_shutdown __P((device_t));
73 extern TRlldDriver_t LldDriver;
75 struct AdapterNameEntry {
79 static struct AdapterNameEntry AdapterNameList[] = {
80 { 10, "Olicom PCI 16/4 Adapter (OC-3136)" },
81 { 11, "Olicom PCI 16/4 Adapter (OC-3136)" },
82 { 12, "Olicom PCI/II 16/4 Adapter (OC-3137)" },
83 { 13, "Olicom PCI 16/4 Adapter (OC-3139)" },
84 { 14, "Olicom RapidFire 3140 16/4 PCI Adapter (OC-3140)" },
85 { 15, "Olicom RapidFire 3141 Fiber Adapter (OC-3141)" },
86 { 19, "Olicom RapidFire 3540 100/16/4 Adapter (OC-3540)" },
87 { 0, "Olicom Unsupported Adapter" }
90 static device_method_t oltr_methods[] = {
91 DEVMETHOD(device_probe, oltr_pci_probe),
92 DEVMETHOD(device_attach, oltr_pci_attach),
93 DEVMETHOD(device_detach, oltr_pci_detach),
94 DEVMETHOD(device_shutdown, oltr_pci_shutdown),
98 static driver_t oltr_driver = {
101 sizeof(struct oltr_softc)
104 static devclass_t oltr_devclass;
106 DRIVER_MODULE(oltr, pci, oltr_driver, oltr_devclass, 0, 0);
107 MODULE_DEPEND(oltr, pci, 1, 1, 1);
108 MODULE_DEPEND(oltr, iso88025, 1, 1, 1);
111 oltr_pci_probe(device_t dev)
114 char PCIConfigHeader[64];
115 TRlldAdapterConfig_t config;
116 struct AdapterNameEntry *list = AdapterNameList;
118 if ((pci_get_vendor(dev) == PCI_VENDOR_OLICOM) &&
119 ((pci_get_device(dev) == 0x0001) ||
120 (pci_get_device(dev) == 0x0004) ||
121 (pci_get_device(dev) == 0x0005) ||
122 (pci_get_device(dev) == 0x0007) ||
123 (pci_get_device(dev) == 0x0008))) {
125 for (i = 0; i < sizeof(PCIConfigHeader); i++)
126 PCIConfigHeader[i] = pci_read_config(dev, i, 1);
128 rc = TRlldPCIConfig(&LldDriver, &config, PCIConfigHeader);
129 if (rc == TRLLD_PCICONFIG_FAIL) {
130 device_printf(dev, "TRlldPciConfig failed!\n");
133 if (rc == TRLLD_PCICONFIG_VERSION) {
134 device_printf(dev, "wrong LLD version\n");
137 while (list->type != 0 && list->type != config.type)
139 device_set_desc(dev, list->name);
146 oltr_pci_attach(device_t dev)
148 int i, s, scratch_size;
150 char PCIConfigHeader[64];
151 struct oltr_softc *sc = device_get_softc(dev);
155 bzero(sc, sizeof(struct oltr_softc));
156 sc->unit = device_get_unit(dev);
157 sc->state = OL_UNKNOWN;
159 for (i = 0; i < sizeof(PCIConfigHeader); i++)
160 PCIConfigHeader[i] = pci_read_config(dev, i, 1);
162 switch(TRlldPCIConfig(&LldDriver, &sc->config, PCIConfigHeader)) {
163 case TRLLD_PCICONFIG_OK:
165 case TRLLD_PCICONFIG_SET_COMMAND:
166 device_printf(dev, "enabling bus master mode\n");
167 command = pci_read_config(dev, PCIR_COMMAND, 4);
168 pci_write_config(dev, PCIR_COMMAND,
169 (command | PCIM_CMD_BUSMASTEREN), 4);
170 command = pci_read_config(dev, PCIR_COMMAND, 4);
171 if (!(command & PCIM_CMD_BUSMASTEREN)) {
172 device_printf(dev, "failed to enable bus master mode\n");
176 case TRLLD_PCICONFIG_FAIL:
177 device_printf(dev, "TRlldPciConfig failed!\n");
180 case TRLLD_PCICONFIG_VERSION:
181 device_printf(dev, "wrong LLD version\n");
185 device_printf(dev, "MAC address %6D\n", sc->config.macaddress, ":");
187 scratch_size = TRlldAdapterSize();
189 device_printf(dev, "adapter memory block size %d bytes\n", scratch_size);
190 sc->TRlldAdapter = (TRlldAdapter_t)malloc(scratch_size, M_DEVBUF, M_NOWAIT);
191 if (sc->TRlldAdapter == NULL) {
192 device_printf(dev, "couldn't allocate scratch buffer (%d bytes)\n", scratch_size);
195 sc->TRlldAdapter_phys = vtophys(sc->TRlldAdapter);
198 * Allocate RX/TX Pools
200 for (i = 0; i < RING_BUFFER_LEN; i++) {
201 sc->rx_ring[i].index = i;
202 sc->rx_ring[i].data = (char *)malloc(RX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
203 sc->rx_ring[i].address = vtophys(sc->rx_ring[i].data);
204 sc->tx_ring[i].index = i;
205 sc->tx_ring[i].data = (char *)malloc(TX_BUFFER_LEN, M_DEVBUF, M_NOWAIT);
206 sc->tx_ring[i].address = vtophys(sc->tx_ring[i].data);
207 if ((!sc->rx_ring[i].data) || (!sc->tx_ring[i].data)) {
208 device_printf(dev, "unable to allocate ring buffers\n");
210 if (sc->rx_ring[i].data)
211 free(sc->rx_ring[i].data, M_DEVBUF);
212 if (sc->tx_ring[i].data)
213 free(sc->tx_ring[i].data, M_DEVBUF);
220 if (oltr_attach(dev) == -1)
233 oltr_pci_detach(device_t dev)
235 struct oltr_softc *sc = device_get_softc(dev);
236 struct ifnet *ifp = sc->ifp;
239 device_printf(dev, "driver unloading\n");
243 iso88025_ifdetach(ifp, ISO88025_BPF_SUPPORTED);
244 if (sc->state > OL_CLOSED)
247 untimeout(oltr_poll, (void *)sc, sc->oltr_poll_ch);
248 /*untimeout(oltr_stat, (void *)sc, sc->oltr_stat_ch);*/
250 bus_teardown_intr(dev, sc->irq_res, sc->oltr_intrhand);
251 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
255 /* Deallocate all dynamic memory regions */
256 for (i = 0; i < RING_BUFFER_LEN; i++) {
257 free(sc->rx_ring[i].data, M_DEVBUF);
258 free(sc->tx_ring[i].data, M_DEVBUF);
261 free(sc->work_memory, M_DEVBUF);
262 free(sc->TRlldAdapter, M_DEVBUF);
270 oltr_pci_shutdown(device_t dev)
272 struct oltr_softc *sc = device_get_softc(dev);
274 device_printf(dev, "oltr_pci_shutdown called\n");
276 if (sc->state > OL_CLOSED)