xref: /netbsd-src/sys/dev/pci/joy_eap.c (revision aaf4ece63a859a04e37cf3a7229b5fab0157cc06)
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