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