joy_eap.c revision 1.5 1 /* $NetBSD: joy_eap.c,v 1.5 2006/10/12 01:31:31 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 __unused, struct cfdata *match __unused,
86 void *aux)
87 {
88 struct joy_eap_aa *eaa = aux;
89
90 if (eaa->aa_aaa.type != AUDIODEV_TYPE_AUX)
91 return (0);
92 return (1);
93 }
94
95 static void
96 joy_eap_attach(struct device *parent __unused, struct device *self, void *aux)
97 {
98 struct joy_softc *sc = (struct joy_softc *)self;
99 struct joy_eap_aa *eaa = aux;
100
101 printf("\n");
102
103 sc->sc_iot = eaa->aa_iot;
104 sc->sc_ioh = eaa->aa_ioh;
105
106 joyattach(sc);
107 }
108
109 static int
110 joy_eap_detach(struct device *self, int flags)
111 {
112
113 return (joydetach((struct joy_softc *)self, flags));
114 }
115
116 CFATTACH_DECL(joy_eap, sizeof (struct joy_softc),
117 joy_eap_match, joy_eap_attach, joy_eap_detach, NULL);
118