summaryrefslogtreecommitdiff
path: root/sys/arch/sgi/dev/owmac.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/sgi/dev/owmac.c')
-rw-r--r--sys/arch/sgi/dev/owmac.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/sys/arch/sgi/dev/owmac.c b/sys/arch/sgi/dev/owmac.c
new file mode 100644
index 00000000000..c178a3591aa
--- /dev/null
+++ b/sys/arch/sgi/dev/owmac.c
@@ -0,0 +1,186 @@
+/* $OpenBSD: owmac.c,v 1.1 2008/04/07 22:55:57 miod Exp $ */
+
+/*
+ * Copyright (c) 2008 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * DS1981/1982/2502 1-Wire Add-only memory driver, for SGI machines.
+ *
+ * SGI uses DS1981 (or compatibles) to store the Ethernet address
+ * on IOC boards.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+
+#include <dev/onewire/onewiredevs.h>
+#include <dev/onewire/onewirereg.h>
+#include <dev/onewire/onewirevar.h>
+
+#include <sgi/dev/owmem_subr.h>
+#include <sgi/dev/owmacvar.h>
+
+int owmac_match(struct device *, void *, void *);
+void owmac_attach(struct device *, struct device *, void *);
+
+struct cfattach owmac_ca = {
+ sizeof(struct owmac_softc), owmac_match, owmac_attach,
+};
+
+struct cfdriver owmac_cd = {
+ NULL, "owmac", DV_DULL
+};
+
+#define EEPROM_NPAGES 4
+
+static const struct onewire_matchfam owmac_fams[] = {
+ { ONEWIRE_FAMILY_DS1982 }
+};
+
+int owmac_read_page(struct owmac_softc *, int, uint8_t *);
+int owmac_read_redirect(struct owmac_softc *);
+
+void owmac_read_mac(struct owmac_softc *);
+
+int
+owmac_match(struct device *parent, void *match, void *aux)
+{
+ return (onewire_matchbyfam(aux, owmac_fams,
+ sizeof(owmac_fams) /sizeof(owmac_fams[0])));
+}
+
+void
+owmac_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct owmac_softc *sc = (struct owmac_softc *)self;
+ struct onewire_attach_args *oa = aux;
+
+ sc->sc_onewire = oa->oa_onewire;
+ sc->sc_rom = oa->oa_rom;
+
+ /*
+ * Read the redirection table.
+ */
+ if (owmac_read_redirect(sc) != 0) {
+ printf(": unable to read redirection data\n");
+ return;
+ }
+
+ printf("\n");
+
+ /*
+ * Read the data.
+ */
+ owmac_read_mac(sc);
+}
+
+int
+owmac_read_redirect(struct owmac_softc *sc)
+{
+ int rc = 0;
+ int status_offset;
+
+ status_offset = 0x0001; /* 1..4 */
+
+ onewire_lock(sc->sc_onewire, 0);
+ if ((rc = onewire_reset(sc->sc_onewire)) != 0)
+ goto unlock;
+
+ onewire_matchrom(sc->sc_onewire, sc->sc_rom);
+
+ /*
+ * Start reading the EEPROM status block, at the page redirection
+ * offset.
+ */
+ onewire_write_byte(sc->sc_onewire, ONEWIRE_CMD_READ_STATUS);
+ onewire_write_byte(sc->sc_onewire, status_offset & 0xff);
+ onewire_write_byte(sc->sc_onewire, status_offset >> 8);
+ /* XXX should verify this crc value */
+ (void)onewire_read_byte(sc->sc_onewire);
+
+ onewire_read_block(sc->sc_onewire, &sc->sc_redir, EEPROM_NPAGES);
+
+ onewire_reset(sc->sc_onewire);
+unlock:
+ onewire_unlock(sc->sc_onewire);
+
+ return rc;
+}
+
+int
+owmac_read_page(struct owmac_softc *sc, int page, uint8_t *buf)
+{
+ int rc = 0;
+ int pg;
+
+ /*
+ * Follow the redirection information.
+ */
+ if ((pg = owmem_redirect(sc->sc_redir, EEPROM_NPAGES, page)) < 0)
+ return EINVAL;
+
+ pg = page * EEPROM_PAGE_SIZE;
+
+ onewire_lock(sc->sc_onewire, 0);
+ if ((rc = onewire_reset(sc->sc_onewire)) != 0)
+ goto unlock;
+
+ onewire_matchrom(sc->sc_onewire, sc->sc_rom);
+
+ /*
+ * Start reading the EEPROM data.
+ */
+ onewire_write_byte(sc->sc_onewire, ONEWIRE_CMD_READ_MEMORY);
+ onewire_write_byte(sc->sc_onewire, pg & 0xff);
+ onewire_write_byte(sc->sc_onewire, 0);
+ /* XXX should verify this crc value */
+ (void)onewire_read_byte(sc->sc_onewire);
+
+ onewire_read_block(sc->sc_onewire, buf, EEPROM_PAGE_SIZE);
+
+ onewire_reset(sc->sc_onewire);
+unlock:
+ onewire_unlock(sc->sc_onewire);
+
+ return rc;
+}
+
+void
+owmac_read_mac(struct owmac_softc *sc)
+{
+ uint8_t buf[EEPROM_PAGE_SIZE];
+
+ if (owmac_read_page(sc, 0, buf) != 0)
+ return;
+
+ if (buf[0] != 0x0a)
+ return;
+
+ sc->sc_enaddr[0] = buf[10];
+ sc->sc_enaddr[1] = buf[9];
+ sc->sc_enaddr[2] = buf[0];
+ sc->sc_enaddr[3] = buf[7];
+ sc->sc_enaddr[4] = buf[6];
+ sc->sc_enaddr[5] = buf[5];
+
+ printf("%s: Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x\n",
+ sc->sc_dev.dv_xname,
+ sc->sc_enaddr[0], sc->sc_enaddr[1], sc->sc_enaddr[2],
+ sc->sc_enaddr[3], sc->sc_enaddr[4], sc->sc_enaddr[5]);
+}