if_pgt_cardbus.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /* $OpenBSD: if_pgt_cardbus.c,v 1.16 2015/03/14 03:38:47 jsg Exp $ */
  2. /*
  3. * Copyright (c) 2006 Marcus Glocker <mglocker@openbsd.org>
  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. * CardBus front-end for the PrismGT
  19. */
  20. #include "bpfilter.h"
  21. #include <sys/param.h>
  22. #include <sys/sockio.h>
  23. #include <sys/mbuf.h>
  24. #include <sys/kernel.h>
  25. #include <sys/socket.h>
  26. #include <sys/systm.h>
  27. #include <sys/malloc.h>
  28. #include <sys/timeout.h>
  29. #include <sys/device.h>
  30. #include <machine/bus.h>
  31. #include <net/if.h>
  32. #include <net/if_dl.h>
  33. #include <net/if_media.h>
  34. #include <netinet/in.h>
  35. #include <netinet/if_ether.h>
  36. #include <net80211/ieee80211_var.h>
  37. #include <net80211/ieee80211_radiotap.h>
  38. #include <dev/ic/pgtreg.h>
  39. #include <dev/ic/pgtvar.h>
  40. #include <dev/pci/pcireg.h>
  41. #include <dev/pci/pcivar.h>
  42. #include <dev/pci/pcidevs.h>
  43. #include <dev/cardbus/cardbusvar.h>
  44. struct pgt_cardbus_softc {
  45. struct pgt_softc sc_pgt;
  46. cardbus_devfunc_t sc_ct;
  47. pcitag_t sc_tag;
  48. int sc_intrline;
  49. void *sc_ih;
  50. bus_size_t sc_mapsize;
  51. pcireg_t sc_bar0_val;
  52. pci_chipset_tag_t sc_pc;
  53. };
  54. int pgt_cardbus_match(struct device *, void *, void *);
  55. void pgt_cardbus_attach(struct device *, struct device *, void *);
  56. int pgt_cardbus_detach(struct device *, int);
  57. int pgt_cardbus_enable(struct pgt_softc *);
  58. void pgt_cardbus_disable(struct pgt_softc *);
  59. void pgt_cardbus_power(struct pgt_softc *, int);
  60. void pgt_cardbus_setup(struct pgt_cardbus_softc *);
  61. struct cfattach pgt_cardbus_ca = {
  62. sizeof(struct pgt_cardbus_softc), pgt_cardbus_match, pgt_cardbus_attach,
  63. pgt_cardbus_detach
  64. };
  65. const struct pci_matchid pgt_cardbus_devices[] = {
  66. { PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_ISL3877 },
  67. { PCI_VENDOR_INTERSIL, PCI_PRODUCT_INTERSIL_ISL3890 },
  68. { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3CRWE154G72 }
  69. };
  70. int
  71. pgt_cardbus_match(struct device *parent, void *match, void *aux)
  72. {
  73. return (cardbus_matchbyid((struct cardbus_attach_args *)aux,
  74. pgt_cardbus_devices,
  75. sizeof(pgt_cardbus_devices) / sizeof(pgt_cardbus_devices[0])));
  76. }
  77. void
  78. pgt_cardbus_attach(struct device *parent, struct device *self, void *aux)
  79. {
  80. struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)self;
  81. struct pgt_softc *sc = &csc->sc_pgt;
  82. struct cardbus_attach_args *ca = aux;
  83. cardbus_devfunc_t ct = ca->ca_ct;
  84. bus_addr_t base;
  85. int error;
  86. sc->sc_dmat = ca->ca_dmat;
  87. csc->sc_ct = ct;
  88. csc->sc_tag = ca->ca_tag;
  89. csc->sc_intrline = ca->ca_intrline;
  90. csc->sc_pc = ca->ca_pc;
  91. /* power management hooks */
  92. sc->sc_enable = pgt_cardbus_enable;
  93. sc->sc_disable = pgt_cardbus_disable;
  94. sc->sc_power = pgt_cardbus_power;
  95. /* remember chipset */
  96. if (PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_INTERSIL_ISL3877)
  97. sc->sc_flags |= SC_ISL3877;
  98. /* map control / status registers */
  99. error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
  100. PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
  101. &sc->sc_iotag, &sc->sc_iohandle, &base, &csc->sc_mapsize);
  102. if (error != 0) {
  103. printf(": can't map mem space\n");
  104. return;
  105. }
  106. csc->sc_bar0_val = base | PCI_MAPREG_TYPE_MEM;
  107. /* disable all interrupts */
  108. bus_space_write_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN, 0);
  109. (void)bus_space_read_4(sc->sc_iotag, sc->sc_iohandle, PGT_REG_INT_EN);
  110. DELAY(PGT_WRITEIO_DELAY);
  111. /* set up the PCI configuration registers */
  112. pgt_cardbus_setup(csc);
  113. printf(": irq %d\n", csc->sc_intrline);
  114. if (rootvp == NULL)
  115. mountroothook_establish(pgt_attach, sc);
  116. else
  117. pgt_attach(sc);
  118. }
  119. int
  120. pgt_cardbus_detach(struct device *self, int flags)
  121. {
  122. struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)self;
  123. struct pgt_softc *sc = &csc->sc_pgt;
  124. cardbus_devfunc_t ct = csc->sc_ct;
  125. cardbus_chipset_tag_t cc = ct->ct_cc;
  126. cardbus_function_tag_t cf = ct->ct_cf;
  127. int error;
  128. error = pgt_detach(sc);
  129. if (error != 0)
  130. return (error);
  131. /* unhook the interrupt handler */
  132. if (csc->sc_ih != NULL) {
  133. cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  134. csc->sc_ih = NULL;
  135. }
  136. /* release bus space and close window */
  137. Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG,
  138. sc->sc_iotag, sc->sc_iohandle, csc->sc_mapsize);
  139. return (0);
  140. }
  141. int
  142. pgt_cardbus_enable(struct pgt_softc *sc)
  143. {
  144. struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)sc;
  145. cardbus_devfunc_t ct = csc->sc_ct;
  146. cardbus_chipset_tag_t cc = ct->ct_cc;
  147. cardbus_function_tag_t cf = ct->ct_cf;
  148. /* power on the socket */
  149. Cardbus_function_enable(ct);
  150. /* setup the PCI configuration registers */
  151. pgt_cardbus_setup(csc);
  152. /* map and establish the interrupt handler */
  153. csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
  154. pgt_intr, sc, sc->sc_dev.dv_xname);
  155. if (csc->sc_ih == NULL) {
  156. printf("%s: could not establish interrupt at %d\n",
  157. sc->sc_dev.dv_xname, csc->sc_intrline);
  158. Cardbus_function_disable(ct);
  159. return (1);
  160. }
  161. return (0);
  162. }
  163. void
  164. pgt_cardbus_disable(struct pgt_softc *sc)
  165. {
  166. struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)sc;
  167. cardbus_devfunc_t ct = csc->sc_ct;
  168. cardbus_chipset_tag_t cc = ct->ct_cc;
  169. cardbus_function_tag_t cf = ct->ct_cf;
  170. /* unhook the interrupt handler */
  171. cardbus_intr_disestablish(cc, cf, csc->sc_ih);
  172. csc->sc_ih = NULL;
  173. /* power down the socket */
  174. Cardbus_function_disable(ct);
  175. }
  176. void
  177. pgt_cardbus_power(struct pgt_softc *sc, int why)
  178. {
  179. if (why == DVACT_RESUME)
  180. if (sc->sc_enable != NULL)
  181. (*sc->sc_enable)(sc);
  182. if (why == DVACT_SUSPEND)
  183. if (sc->sc_disable != NULL)
  184. (*sc->sc_disable)(sc);
  185. }
  186. void
  187. pgt_cardbus_setup(struct pgt_cardbus_softc *csc)
  188. {
  189. cardbus_devfunc_t ct = csc->sc_ct;
  190. cardbus_chipset_tag_t cc = ct->ct_cc;
  191. pci_chipset_tag_t pc = csc->sc_pc;
  192. cardbus_function_tag_t cf = ct->ct_cf;
  193. pcireg_t reg;
  194. /* program the BAR */
  195. pci_conf_write(pc, csc->sc_tag, CARDBUS_BASE0_REG,
  196. csc->sc_bar0_val);
  197. /* make sure the right access type is on the cardbus bridge */
  198. (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
  199. (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);
  200. /* enable the appropriate bits in the PCI CSR */
  201. reg = pci_conf_read(pc, csc->sc_tag,
  202. PCI_COMMAND_STATUS_REG);
  203. reg |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE;
  204. pci_conf_write(pc, csc->sc_tag, PCI_COMMAND_STATUS_REG,
  205. reg);
  206. }