owmac.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* $OpenBSD: owmac.c,v 1.2 2009/04/13 21:14:41 miod Exp $ */
  2. /*
  3. * Copyright (c) 2008 Miodrag Vallat.
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /*
  18. * DS1981/1982/2502 1-Wire Add-only memory driver, for SGI machines.
  19. *
  20. * SGI uses DS1981 (or compatibles) to store the Ethernet address
  21. * on IOC boards.
  22. */
  23. #include <sys/param.h>
  24. #include <sys/systm.h>
  25. #include <sys/device.h>
  26. #include <sys/kernel.h>
  27. #include <sys/proc.h>
  28. #include <dev/onewire/onewiredevs.h>
  29. #include <dev/onewire/onewirereg.h>
  30. #include <dev/onewire/onewirevar.h>
  31. #include <sgi/dev/owmem_subr.h>
  32. #include <sgi/dev/owmacvar.h>
  33. int owmac_match(struct device *, void *, void *);
  34. void owmac_attach(struct device *, struct device *, void *);
  35. struct cfattach owmac_ca = {
  36. sizeof(struct owmac_softc), owmac_match, owmac_attach,
  37. };
  38. struct cfdriver owmac_cd = {
  39. NULL, "owmac", DV_DULL
  40. };
  41. #define EEPROM_NPAGES 4
  42. static const struct onewire_matchfam owmac_fams[] = {
  43. { ONEWIRE_FAMILY_DS1982 }
  44. };
  45. int owmac_read_page(struct owmac_softc *, int, uint8_t *);
  46. int owmac_read_redirect(struct owmac_softc *);
  47. void owmac_read_mac(struct owmac_softc *);
  48. int
  49. owmac_match(struct device *parent, void *match, void *aux)
  50. {
  51. struct onewire_attach_args *oa = aux;
  52. if (ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom) == ONEWIRE_FAMILY_DS1982)
  53. return 1;
  54. /*
  55. * Also match on UniqueWare devices with specific 0x91 family code.
  56. */
  57. if ((ONEWIRE_ROM_SN(oa->oa_rom) >> (48 - 12)) == 0x5e7 &&
  58. ONEWIRE_ROM_FAMILY_CUSTOM(oa->oa_rom) &&
  59. ONEWIRE_ROM_FAMILY(oa->oa_rom) == 0x91)
  60. return 1;
  61. return 0;
  62. }
  63. void
  64. owmac_attach(struct device *parent, struct device *self, void *aux)
  65. {
  66. struct owmac_softc *sc = (struct owmac_softc *)self;
  67. struct onewire_attach_args *oa = aux;
  68. sc->sc_onewire = oa->oa_onewire;
  69. sc->sc_rom = oa->oa_rom;
  70. /*
  71. * Read the redirection table.
  72. */
  73. if (owmac_read_redirect(sc) != 0) {
  74. printf(": unable to read redirection data\n");
  75. return;
  76. }
  77. printf("\n");
  78. /*
  79. * Read the data.
  80. */
  81. owmac_read_mac(sc);
  82. }
  83. int
  84. owmac_read_redirect(struct owmac_softc *sc)
  85. {
  86. int rc = 0;
  87. int status_offset;
  88. status_offset = 0x0001; /* 1..4 */
  89. onewire_lock(sc->sc_onewire, 0);
  90. if ((rc = onewire_reset(sc->sc_onewire)) != 0)
  91. goto unlock;
  92. onewire_matchrom(sc->sc_onewire, sc->sc_rom);
  93. /*
  94. * Start reading the EEPROM status block, at the page redirection
  95. * offset.
  96. */
  97. onewire_write_byte(sc->sc_onewire, ONEWIRE_CMD_READ_STATUS);
  98. onewire_write_byte(sc->sc_onewire, status_offset & 0xff);
  99. onewire_write_byte(sc->sc_onewire, status_offset >> 8);
  100. /* XXX should verify this crc value */
  101. (void)onewire_read_byte(sc->sc_onewire);
  102. onewire_read_block(sc->sc_onewire, &sc->sc_redir, EEPROM_NPAGES);
  103. onewire_reset(sc->sc_onewire);
  104. unlock:
  105. onewire_unlock(sc->sc_onewire);
  106. return rc;
  107. }
  108. int
  109. owmac_read_page(struct owmac_softc *sc, int page, uint8_t *buf)
  110. {
  111. int rc = 0;
  112. int pg;
  113. /*
  114. * Follow the redirection information.
  115. */
  116. if ((pg = owmem_redirect(sc->sc_redir, EEPROM_NPAGES, page)) < 0)
  117. return EINVAL;
  118. pg = page * EEPROM_PAGE_SIZE;
  119. onewire_lock(sc->sc_onewire, 0);
  120. if ((rc = onewire_reset(sc->sc_onewire)) != 0)
  121. goto unlock;
  122. onewire_matchrom(sc->sc_onewire, sc->sc_rom);
  123. /*
  124. * Start reading the EEPROM data.
  125. */
  126. onewire_write_byte(sc->sc_onewire, ONEWIRE_CMD_READ_MEMORY);
  127. onewire_write_byte(sc->sc_onewire, pg & 0xff);
  128. onewire_write_byte(sc->sc_onewire, 0);
  129. /* XXX should verify this crc value */
  130. (void)onewire_read_byte(sc->sc_onewire);
  131. onewire_read_block(sc->sc_onewire, buf, EEPROM_PAGE_SIZE);
  132. onewire_reset(sc->sc_onewire);
  133. unlock:
  134. onewire_unlock(sc->sc_onewire);
  135. return rc;
  136. }
  137. void
  138. owmac_read_mac(struct owmac_softc *sc)
  139. {
  140. uint8_t buf[EEPROM_PAGE_SIZE];
  141. if (owmac_read_page(sc, 0, buf) != 0)
  142. return;
  143. if (buf[0] != 0x0a)
  144. return;
  145. sc->sc_enaddr[0] = buf[10];
  146. sc->sc_enaddr[1] = buf[9];
  147. sc->sc_enaddr[2] = buf[8];
  148. sc->sc_enaddr[3] = buf[7];
  149. sc->sc_enaddr[4] = buf[6];
  150. sc->sc_enaddr[5] = buf[5];
  151. printf("%s: Ethernet Address %02x:%02x:%02x:%02x:%02x:%02x\n",
  152. sc->sc_dev.dv_xname,
  153. sc->sc_enaddr[0], sc->sc_enaddr[1], sc->sc_enaddr[2],
  154. sc->sc_enaddr[3], sc->sc_enaddr[4], sc->sc_enaddr[5]);
  155. }