diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2008-04-07 22:55:58 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2008-04-07 22:55:58 +0000 |
commit | 8a4a4d505beb22d5cd8cae09059aa84ac8541c08 (patch) | |
tree | 017437f264435bb8ab338be19ec7e00f225e6326 /sys/arch/sgi | |
parent | c786dcaf684d111bd92d6d6b0cfe1c56ba3de552 (diff) |
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).
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r-- | sys/arch/sgi/dev/owmac.c | 186 | ||||
-rw-r--r-- | sys/arch/sgi/dev/owmacvar.h | 35 | ||||
-rw-r--r-- | sys/arch/sgi/dev/owmem_subr.c | 46 | ||||
-rw-r--r-- | sys/arch/sgi/dev/owmem_subr.h | 25 | ||||
-rw-r--r-- | sys/arch/sgi/dev/owserial.c | 217 | ||||
-rw-r--r-- | sys/arch/sgi/dev/owserialvar.h | 39 |
6 files changed, 548 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]); +} 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 <sys/param.h> + +#include <sgi/dev/owmem_subr.h> + +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 <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/owserialvar.h> + +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]; +}; |