1 /* $NetBSD: joy_eap.c,v 1.4 2005/12/11 12:22:50 christos Exp $ */ 2 3 #include <sys/param.h> 4 #include <sys/systm.h> 5 #include <sys/kernel.h> 6 #include <sys/device.h> 7 #include <sys/audioio.h> 8 #include <dev/audio_if.h> 9 #include <machine/bus.h> 10 11 #include <dev/pci/eapreg.h> 12 #include <dev/pci/eapvar.h> 13 #include <dev/ic/joyvar.h> 14 15 struct joy_eap_aa { 16 struct audio_attach_args aa_aaa; 17 bus_space_tag_t aa_iot; 18 bus_space_handle_t aa_ioh; 19 }; 20 21 struct device * 22 eap_joy_attach(struct device *eapdev, struct eap_gameport_args *gpa) 23 { 24 int i; 25 bus_space_handle_t ioh; 26 u_int32_t icsc; 27 struct joy_eap_aa aa; 28 struct device *joydev; 29 30 /* 31 * There are 4 possible locations. Just try to map one of them. 32 * XXX This is questionable for 2 reasons: 33 * - We don't know whether these addresses are usable on our 34 * PCI bus (might be a secondary one). 35 * - PCI probing is early. ISA devices might conflict. 36 */ 37 for (i = 0; i < 4; i++) { 38 if (bus_space_map(gpa->gpa_iot, 0x200 + i * 8, 1, 39 0, &ioh) == 0) 40 break; 41 } 42 if (i == 4) 43 return (0); 44 45 printf("%s: enabling gameport at legacy io port 0x%x\n", 46 eapdev->dv_xname, 0x200 + i * 8); 47 48 /* enable gameport on eap */ 49 icsc = bus_space_read_4(gpa->gpa_iot, gpa->gpa_ioh, EAP_ICSC); 50 icsc &= ~E1371_JOY_ASELBITS; 51 icsc |= EAP_JYSTK_EN | E1371_JOY_ASEL(i); 52 bus_space_write_4(gpa->gpa_iot, gpa->gpa_ioh, EAP_ICSC, icsc); 53 54 aa.aa_aaa.type = AUDIODEV_TYPE_AUX; 55 aa.aa_iot = gpa->gpa_iot; 56 aa.aa_ioh = ioh; 57 joydev = config_found(eapdev, &aa, 0); 58 /* this cannot fail */ 59 KASSERT(joydev != NULL); 60 61 return (joydev); 62 } 63 64 int 65 eap_joy_detach(struct device *joydev, struct eap_gameport_args *gpa) 66 { 67 int res; 68 struct joy_softc *sc = (struct joy_softc *)joydev; 69 u_int32_t icsc; 70 71 res = config_detach(joydev, 0); 72 if (res) 73 return (res); 74 75 /* disable gameport on eap */ 76 icsc = bus_space_read_4(gpa->gpa_iot, gpa->gpa_ioh, EAP_ICSC); 77 icsc &= ~EAP_JYSTK_EN; 78 bus_space_write_4(gpa->gpa_iot, gpa->gpa_ioh, EAP_ICSC, icsc); 79 80 bus_space_unmap(sc->sc_iot, sc->sc_ioh, 1); 81 return (0); 82 } 83 84 static int 85 joy_eap_match(struct device *parent, struct cfdata *match, void *aux) 86 { 87 struct joy_eap_aa *eaa = aux; 88 89 if (eaa->aa_aaa.type != AUDIODEV_TYPE_AUX) 90 return (0); 91 return (1); 92 } 93 94 static void 95 joy_eap_attach(struct device *parent, struct device *self, void *aux) 96 { 97 struct joy_softc *sc = (struct joy_softc *)self; 98 struct joy_eap_aa *eaa = aux; 99 100 printf("\n"); 101 102 sc->sc_iot = eaa->aa_iot; 103 sc->sc_ioh = eaa->aa_ioh; 104 105 joyattach(sc); 106 } 107 108 static int 109 joy_eap_detach(struct device *self, int flags) 110 { 111 112 return (joydetach((struct joy_softc *)self, flags)); 113 } 114 115 CFATTACH_DECL(joy_eap, sizeof (struct joy_softc), 116 joy_eap_match, joy_eap_attach, joy_eap_detach, NULL); 117