aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/arl/if_arl_isa.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/arl/if_arl_isa.c')
-rw-r--r--sys/dev/arl/if_arl_isa.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/sys/dev/arl/if_arl_isa.c b/sys/dev/arl/if_arl_isa.c
new file mode 100644
index 000000000000..434407d401d1
--- /dev/null
+++ b/sys/dev/arl/if_arl_isa.c
@@ -0,0 +1,354 @@
+/*
+ * $RISS: if_arl/dev/arl/if_arl_isa.c,v 1.4 2004/01/22 12:08:48 count Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_mib.h>
+
+#include <isa/isavar.h>
+#include <isa/pnpvar.h>
+#include <isa/isa_common.h>
+
+#include <machine/clock.h>
+#include <machine/md_var.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_param.h>
+
+#include <dev/arl/if_arlreg.h>
+
+static void arl_isa_identify(driver_t *, device_t);
+static int arl_isa_probe (device_t);
+static int arl_isa_attach (device_t);
+static int arl_isa_detach (device_t);
+static char* arl_make_desc (u_int8_t, u_int8_t);
+
+#define ARL_MAX_ATYPE_LEN 10
+static struct arl_type {
+ u_int8_t type;
+ char* desc;
+}
+arl_type_list[] = {
+ { 0, "450" },
+ { 1, "650" },
+ { 0xb, "670" },
+ { 0xc, "670E" },
+ { 0xd, "650E" },
+ { 0xe, "440LT" },
+ { 0x2e, "655" },
+ { 0x6b, "IC2200" },
+ { 0, 0 }
+};
+
+#define ARL_MAX_RTYPE_LEN 10
+struct radio_type {
+ u_int8_t type;
+ char* desc;
+} radio_type_list [] = {
+ { 1, "092/094" },
+ { 2, "020" },
+ { 3, "092A" },
+ { 4, "020B" },
+ { 5, "095" },
+ { 6, "024" },
+ { 7, "025B" },
+ { 8, "024B" },
+ { 9, "024C" },
+ {10, "025C" },
+ {11, "024-1A" },
+ {12, "025-1A" },
+};
+
+
+static char*
+arl_make_desc(hw_type, radio_mod)
+ u_int8_t hw_type;
+ u_int8_t radio_mod;
+{
+ static char desc[80];
+ char atype[ARL_MAX_ATYPE_LEN], rtype[ARL_MAX_RTYPE_LEN];
+ int i;
+
+ *atype = *rtype = 0;
+
+ /* arl type */
+ for(i = 0; arl_type_list[i].desc; i++) {
+ if (arl_type_list[i].type == hw_type)
+ break;
+ }
+
+ if (arl_type_list[i].desc)
+ strncpy(atype, arl_type_list[i].desc, ARL_MAX_ATYPE_LEN);
+ else
+ snprintf(atype, ARL_MAX_ATYPE_LEN, "(0x%x)", hw_type);
+
+ /* radio type */
+ for(i = 0; radio_type_list[i].desc; i++)
+ if (radio_type_list[i].type == radio_mod)
+ break;
+
+ if (radio_type_list[i].desc)
+ strncpy(rtype, radio_type_list[i].desc, ARL_MAX_RTYPE_LEN);
+ else
+ snprintf(rtype, ARL_MAX_RTYPE_LEN, "(0x%x)", radio_mod);
+
+ snprintf(desc, 80, "ArLan type %s, radio module %s", atype, rtype);
+
+ return desc;
+}
+
+#define ARL_ADDR2VEC(addr) (1 << ((addr - ARL_BASE_START) / ARL_BASE_STEP))
+
+static void
+arl_isa_identify (driver_t *driver, device_t parent)
+{
+ device_t child;
+ struct arl_softc *sc;
+ int chunk, found, i;
+ u_int16_t free_mem = 0xFFFF;
+
+ if (bootverbose)
+ printf("in identify\n");
+
+ /* Try avoid already added devices */
+ for (i = 0; (child = device_find_child(parent, "arl", i)) != NULL; i++) {
+ chunk = bus_get_resource_start(child, SYS_RES_MEMORY, 0);
+ if (bootverbose)
+ device_printf(child, "found at iomem = 0x%0x\n", chunk);
+ if (chunk >= ARL_BASE_START && chunk <= ARL_BASE_END)
+ free_mem ^= ARL_ADDR2VEC(chunk);
+ }
+
+ if (bootverbose)
+ printf("arl: free mem vector = 0x%x\n", free_mem);
+
+ for (chunk = ARL_BASE_START; chunk <= ARL_BASE_END; chunk += ARL_BASE_STEP) {
+ /* If device 'arl' with this chunk was found early - skip it */
+ if ( !(free_mem & ARL_ADDR2VEC(chunk)) )
+ continue;
+
+ found = 0;
+ child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "arl", -1);
+ device_set_driver(child, driver);
+ sc = device_get_softc(child);
+ bzero(sc, sizeof(*sc));
+
+ bus_set_resource(child, SYS_RES_MEMORY, sc->mem_rid, chunk,
+ ARL_BASE_STEP);
+
+ if (arl_alloc_memory(child, sc->mem_rid, ARL_BASE_STEP) == 0) {
+ ar = (struct arl_private *) rman_get_virtual(sc->mem_res);
+ if (!bcmp(ar->textRegion, ARLAN_SIGN, sizeof(ARLAN_SIGN) - 1))
+ found++;
+ }
+
+ if (bootverbose)
+ device_printf(child, "%sfound at 0x%x\n",
+ !found ? "not " : "", chunk);
+
+ arl_release_resources(child);
+ if (!found) {
+ bus_delete_resource(child, SYS_RES_MEMORY, sc->mem_rid);
+ device_delete_child(parent, child);
+ }
+
+ }
+}
+
+static int
+arl_isa_probe (device_t dev)
+{
+ struct arl_softc *sc = device_get_softc(dev);
+ int error;
+ u_char *ptr;
+ u_int8_t irq;
+
+ if (isa_get_vendorid(dev))
+ return (ENXIO);
+
+ if (bootverbose)
+ device_printf(dev, "in probe\n");
+
+ bzero(sc, sizeof(struct arl_softc));
+
+ sc->arl_unit = device_get_unit(dev);
+
+ error = arl_alloc_memory(dev, 0, ARL_BASE_STEP);
+ if (error) {
+ if (bootverbose)
+ device_printf(dev, "Error allocating memory (%d)\n", error);
+ return (error);
+ }
+
+ ar = (struct arl_private *) rman_get_virtual(sc->mem_res);
+ if (bcmp(ar->textRegion, ARLAN_SIGN, sizeof(ARLAN_SIGN) - 1)) {
+ if (bootverbose)
+ device_printf(dev, "not found\n");
+ error = ENOENT;
+ goto bad;
+ }
+
+ irq = ar->irqLevel;
+ if (irq == 2)
+ irq = 9;
+
+ error = bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
+ if (error)
+ goto bad;
+
+ error = arl_alloc_irq(dev, 0, 0);
+ if (error) {
+ if (bootverbose)
+ device_printf(dev, "Can't allocate IRQ %d\n", irq);
+ goto bad;
+ }
+
+ ar->controlRegister = 1; /* freeze board */
+
+ /* Memory test */
+ for (ptr = (u_char *) ar;
+ ptr < ((u_char *) ar + ARL_BASE_STEP - 1); ptr++) {
+ u_char c;
+
+ c = *ptr; *ptr = ~(*ptr);
+ if (*ptr != (u_char)~c) {
+ device_printf(dev, "board memory failed at [%lx]\n",
+ rman_get_start(sc->mem_res) + (ptr - (u_char *)ar));
+ break; /* skip memory test */
+ }
+ }
+
+ bzero((void *) ar, ARL_BASE_STEP - 1); /* clear board ram */
+
+ if (arl_wait_reset(sc, 100, ARDELAY)) {
+ error = ENXIO;
+ goto bad;
+ }
+
+ if (ar->diagnosticInfo == 0xFF) {
+ /* Copy arp to arpcom struct */
+ bcopy(ar->lanCardNodeId, sc->arpcom.ac_enaddr,
+ ETHER_ADDR_LEN);
+
+ /* copy values to local cache */
+ bzero(&arcfg, sizeof(arcfg));
+
+ bcopy(ar->lanCardNodeId, arcfg.lanCardNodeId,
+ sizeof(ar->lanCardNodeId));
+ bcopy(ar->specifiedRouter, arcfg.specifiedRouter,
+ sizeof(ar->specifiedRouter));
+
+ GET_ARL_PARAM(hardwareType);
+ GET_ARL_PARAM(majorHardwareVersion);
+ GET_ARL_PARAM(minorHardwareVersion);
+ GET_ARL_PARAM(radioModule);
+ GET_ARL_PARAM(channelSet);
+ if (!arcfg.channelSet)
+ arcfg.channelSet = ar->defaultChannelSet;
+ GET_ARL_PARAM(channelNumber);
+ GET_ARL_PARAM(registrationMode);
+ GET_ARL_PARAM(spreadingCode);
+ GET_ARL_PARAM(priority);
+ GET_ARL_PARAM(receiveMode);
+ arcfg.txRetry = 0; /* use default */
+
+ strncpy(arcfg.name, ar->name, ARLAN_NAME_SIZE);
+ bcopy(ar->systemId, arcfg.sid, 4 * sizeof(ar->systemId[0]));
+
+ device_set_desc_copy(dev, arl_make_desc(ar->hardwareType, ar->radioModule));
+ error = 0;
+ } else {
+ if (bootverbose)
+ device_printf(dev, "board self-test failed (0x%x)!\n",
+ ar->diagnosticInfo);
+ error = ENXIO;
+ }
+
+bad:
+ arl_release_resources(dev);
+
+ return (error);
+}
+
+static int
+arl_isa_attach (device_t dev)
+{
+ struct arl_softc *sc = device_get_softc(dev);
+ int error;
+
+ if (bootverbose)
+ device_printf(dev, "in attach\n");
+
+ arl_alloc_memory(dev, sc->mem_rid, ARL_BASE_STEP);
+ arl_alloc_irq(dev, sc->irq_rid, 0);
+
+ error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
+ arl_intr, sc, &sc->irq_handle);
+ if (error) {
+ arl_release_resources(dev);
+ return (error);
+ }
+
+#if __FreeBSD_version < 502108
+ device_printf(dev, "Ethernet address %6D\n", sc->arpcom.ac_enaddr, ":");
+#endif
+
+ return arl_attach(dev);
+}
+
+static int
+arl_isa_detach(device_t dev)
+{
+ struct arl_softc *sc = device_get_softc(dev);
+
+ arl_stop(sc);
+ /* ifmedia_removeall(&sc->an_ifmedia); */
+#if __FreeBSD_version < 500100
+ ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
+#else
+ ether_ifdetach(&sc->arpcom.ac_if);
+#endif
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
+ arl_release_resources(dev);
+
+ return (0);
+}
+
+static device_method_t arl_isa_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, arl_isa_identify),
+ DEVMETHOD(device_probe, arl_isa_probe),
+ DEVMETHOD(device_attach, arl_isa_attach),
+ DEVMETHOD(device_detach, arl_isa_detach),
+
+ { 0, 0 }
+};
+
+static driver_t arl_isa_driver = {
+ "arl",
+ arl_isa_methods,
+ sizeof(struct arl_softc)
+};
+
+extern devclass_t arl_devclass;
+
+DRIVER_MODULE(arl, isa, arl_isa_driver, arl_devclass, 0, 0);
+MODULE_DEPEND(arl, isa, 1, 1, 1);
+MODULE_DEPEND(arl, ether, 1, 1, 1);