From 8a4a4d505beb22d5cd8cae09059aa84ac8541c08 Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Mon, 7 Apr 2008 22:55:58 +0000 Subject: SGI 1-Wire Number-In-a-Can drivers. These are regular Dallas/Maxim append-only EEPROM, with knowledge of how SGI formats their contents. They are needed by IOC to figure out the Ethernet address of its Ethernet subdevice (yes, verily). --- sys/arch/sgi/dev/owmac.c | 186 +++++++++++++++++++++++++++++++++++ sys/arch/sgi/dev/owmacvar.h | 35 +++++++ sys/arch/sgi/dev/owmem_subr.c | 46 +++++++++ sys/arch/sgi/dev/owmem_subr.h | 25 +++++ sys/arch/sgi/dev/owserial.c | 217 +++++++++++++++++++++++++++++++++++++++++ sys/arch/sgi/dev/owserialvar.h | 39 ++++++++ 6 files changed, 548 insertions(+) create mode 100644 sys/arch/sgi/dev/owmac.c create mode 100644 sys/arch/sgi/dev/owmacvar.h create mode 100644 sys/arch/sgi/dev/owmem_subr.c create mode 100644 sys/arch/sgi/dev/owmem_subr.h create mode 100644 sys/arch/sgi/dev/owserial.c create mode 100644 sys/arch/sgi/dev/owserialvar.h (limited to 'sys/arch/sgi') 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 +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +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]); +} diff --git a/sys/arch/sgi/dev/owmacvar.h b/sys/arch/sgi/dev/owmacvar.h new file mode 100644 index 00000000000..14b6456dcb5 --- /dev/null +++ b/sys/arch/sgi/dev/owmacvar.h @@ -0,0 +1,35 @@ +/* $OpenBSD: owmacvar.h,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. + */ + +struct owmac_softc { + struct device sc_dev; + + void *sc_onewire; + uint64_t sc_rom; + + uint8_t sc_redir[4]; /* redirection table */ + + uint8_t sc_enaddr[6]; +}; diff --git a/sys/arch/sgi/dev/owmem_subr.c b/sys/arch/sgi/dev/owmem_subr.c new file mode 100644 index 00000000000..3ae3ca89c52 --- /dev/null +++ b/sys/arch/sgi/dev/owmem_subr.c @@ -0,0 +1,46 @@ +/* $OpenBSD: owmem_subr.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. + */ + +/* + * Common routines to owmac and owserial drivers. + */ + +#include + +#include + +int +owmem_redirect(uint8_t *redir, u_int npages, u_int page) +{ + int skips = 0; + + /* + * Follow the redirecting table until we end up in our final + * position. We have to be careful not to loop if the table + * is wrong. + */ + while (redir[page] != 0xff) { + if (++skips >= npages) + return -1; + page = 0xff ^ redir[page]; + if (page >= npages) + return -1; + } + + return page; +} diff --git a/sys/arch/sgi/dev/owmem_subr.h b/sys/arch/sgi/dev/owmem_subr.h new file mode 100644 index 00000000000..2e955c89f25 --- /dev/null +++ b/sys/arch/sgi/dev/owmem_subr.h @@ -0,0 +1,25 @@ +/* $OpenBSD: owmem_subr.h,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. + */ + +/* + * Common routines to owmac and owserial drivers. + */ + +#define EEPROM_PAGE_SIZE (256 / NBBY) /* 256 bits per page */ + +int owmem_redirect(uint8_t *, u_int, u_int); diff --git a/sys/arch/sgi/dev/owserial.c b/sys/arch/sgi/dev/owserial.c new file mode 100644 index 00000000000..9fc26f9c6f1 --- /dev/null +++ b/sys/arch/sgi/dev/owserial.c @@ -0,0 +1,217 @@ +/* $OpenBSD: owserial.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. + */ + +/* + * DS2505 1-Wire Add-only memory driver, for SGI machines. + * + * SGI seems to use DS2505 (or compatibles) to store serial numbers. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +int owserial_match(struct device *, void *, void *); +void owserial_attach(struct device *, struct device *, void *); + +struct cfattach owserial_ca = { + sizeof(struct owserial_softc), owserial_match, owserial_attach, +}; + +struct cfdriver owserial_cd = { + NULL, "owserial", DV_DULL +}; + +#define EEPROM_PAGE_SIZE (256 / NBBY) /* 256 bits per page */ + +static const struct onewire_matchfam owserial_fams[] = { + { ONEWIRE_FAMILY_DS2505 }, + { ONEWIRE_FAMILY_DS2506 } +}; + +int owserial_read_page(struct owserial_softc *, int, uint8_t *); +int owserial_read_redirect(struct owserial_softc *); + +void owserial_read_serial(struct owserial_softc *); + +int +owserial_match(struct device *parent, void *match, void *aux) +{ + return (onewire_matchbyfam(aux, owserial_fams, + sizeof(owserial_fams) /sizeof(owserial_fams[0]))); +} + +void +owserial_attach(struct device *parent, struct device *self, void *aux) +{ + struct owserial_softc *sc = (struct owserial_softc *)self; + struct onewire_attach_args *oa = aux; + + sc->sc_onewire = oa->oa_onewire; + sc->sc_rom = oa->oa_rom; + + /* + * Decide how many pages of 256 bits we have. + */ + + if (ONEWIRE_ROM_FAMILY_TYPE(sc->sc_rom) == ONEWIRE_FAMILY_DS2506) + sc->sc_npages = 256; + else + sc->sc_npages = 64; + + /* + * Read the redirection table. + */ + if (owserial_read_redirect(sc) != 0) { + printf(": unable to read redirection data\n"); + return; + } + + printf("\n"); + + /* + * Read the data. + */ + owserial_read_serial(sc); +} + +int +owserial_read_redirect(struct owserial_softc *sc) +{ + int rc = 0; + int status_offset, pos; + + status_offset = 0x0100; /* 100..13f or 100..1ff */ + pos = 0; + + 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); + + for (pos = 0; pos < sc->sc_npages; pos += 8) { + onewire_read_block(sc->sc_onewire, sc->sc_redir + pos, 8); + /* XXX check crc */ + (void)onewire_read_byte(sc->sc_onewire); + (void)onewire_read_byte(sc->sc_onewire); + } + + onewire_reset(sc->sc_onewire); +unlock: + onewire_unlock(sc->sc_onewire); + + return rc; +} + +int +owserial_read_page(struct owserial_softc *sc, int page, uint8_t *buf) +{ + int rc = 0; + int pg; + + /* + * Follow the redirection information. + */ + if ((pg = owmem_redirect(sc->sc_redir, sc->sc_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, pg >> 8); + + onewire_read_block(sc->sc_onewire, buf, EEPROM_PAGE_SIZE); + + onewire_reset(sc->sc_onewire); +unlock: + onewire_unlock(sc->sc_onewire); + + return rc; +} + +void +owserial_read_serial(struct owserial_softc *sc) +{ + uint8_t buf[EEPROM_PAGE_SIZE * 2]; + char serial[1 + OWSERIAL_NAME_LEN]; + char descr[1 + OWSERIAL_SERIAL_LEN], *dptr; + int pg; + int i; + + pg = owmem_redirect(sc->sc_redir, sc->sc_npages, 0); + if (pg < 0 || owserial_read_page(sc, pg, buf) != 0) + return; + + pg = owmem_redirect(sc->sc_redir, sc->sc_npages, 1); + if (pg < 0 || owserial_read_page(sc, pg, buf + EEPROM_PAGE_SIZE) != 0) + return; + + /* minimal sanity check */ + if (buf[0] != 0x01) + return; + for (i = EEPROM_PAGE_SIZE + 10; i < EEPROM_PAGE_SIZE + 16; i++) + if (buf[i] != 0xff) + return; + + bcopy(buf + 21, serial, 9); + bcopy(buf + EEPROM_PAGE_SIZE + 3, serial + 9, 3); + serial[OWSERIAL_NAME_LEN] = '\0'; + for (i = 0; i < OWSERIAL_NAME_LEN; i++) + if (serial[i] != '-' && (serial[i] < '0' || serial[i] > '9')) + return; + + bcopy(buf + EEPROM_PAGE_SIZE + 16, descr, OWSERIAL_SERIAL_LEN); + descr[OWSERIAL_SERIAL_LEN] = '\0'; + for (i = 0; i < OWSERIAL_SERIAL_LEN; i++) + if (descr[i] < ' ' || descr[i] > '~') + return; + for (dptr = descr; *dptr == ' '; dptr++); + + strlcpy(sc->sc_name, dptr, sizeof sc->sc_name); + strlcpy(sc->sc_serial, serial, sizeof sc->sc_serial); + + printf("%s: \"%s\" serial %s\n", sc->sc_dev.dv_xname, dptr, serial); +} diff --git a/sys/arch/sgi/dev/owserialvar.h b/sys/arch/sgi/dev/owserialvar.h new file mode 100644 index 00000000000..acdfde41fe6 --- /dev/null +++ b/sys/arch/sgi/dev/owserialvar.h @@ -0,0 +1,39 @@ +/* $OpenBSD: owserialvar.h,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. + */ + +/* + * DS2505 1-Wire Add-only memory driver, for SGI machines. + * + * SGI seems to use DS2505 (or compatibles) to store serial numbers. + */ + +#define OWSERIAL_NAME_LEN 12 +#define OWSERIAL_SERIAL_LEN 14 + +struct owserial_softc { + struct device sc_dev; + + void *sc_onewire; + uint64_t sc_rom; + + int sc_npages; /* number of pages */ + uint8_t sc_redir[256]; /* redirection table */ + + char sc_name[1 + OWSERIAL_NAME_LEN]; + char sc_serial[1 + OWSERIAL_SERIAL_LEN]; +}; -- cgit v1.2.3