315673e79a
This is only usable with some caution because these soundcards only allow to map IO port 0x20x for this, thus bypassing PCI address management. Very likely this will only work on primary PCI buses, and there is some potential for conflicts with ISA devices as well. (XXX cannot be detached because the "joy" driver doesn't support it yet)
125 lines
2.8 KiB
C
125 lines
2.8 KiB
C
/* $NetBSD: joy_eap.c,v 1.1 2004/07/08 19:39:00 drochner Exp $ */
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/device.h>
|
|
#include <sys/audioio.h>
|
|
#include <dev/audio_if.h>
|
|
#include <machine/bus.h>
|
|
|
|
#include <dev/pci/eapreg.h>
|
|
#include <dev/pci/eapvar.h>
|
|
#include <dev/ic/joyvar.h>
|
|
|
|
int joy_eap_match(struct device *, struct cfdata *, void *);
|
|
void joy_eap_attach(struct device *, struct device *, void *);
|
|
int joy_eap_detach(struct device *, int);
|
|
|
|
CFATTACH_DECL(joy_eap, sizeof (struct joy_softc),
|
|
joy_eap_match, joy_eap_attach, joy_eap_detach, NULL);
|
|
|
|
struct joy_eap_aa {
|
|
struct audio_attach_args aa_aaa;
|
|
bus_space_tag_t aa_iot;
|
|
bus_space_handle_t aa_ioh;
|
|
};
|
|
|
|
struct device *
|
|
eap_joy_attach(struct device *eapdev, struct eap_gameport_args *gpa)
|
|
{
|
|
int i;
|
|
bus_space_handle_t ioh;
|
|
u_int32_t icsc;
|
|
struct joy_eap_aa aa;
|
|
struct device *joydev;
|
|
|
|
/*
|
|
* There are 4 possible locations. Just try to map one of them.
|
|
* XXX This is questionable for 2 reasons:
|
|
* - We don't know whether these addresses are usable on our
|
|
* PCI bus (might be a secondary one).
|
|
* - PCI probing is early. ISA devices might conflict.
|
|
*/
|
|
for (i = 0; i < 4; i++) {
|
|
if (bus_space_map(gpa->gpa_iot, 0x200 + i * 8, 1,
|
|
0, &ioh) == 0)
|
|
break;
|
|
}
|
|
if (i == 4)
|
|
return (0);
|
|
|
|
printf("%s: enabling gameport at legacy io port 0x%x\n",
|
|
eapdev->dv_xname, 0x200 + i * 8);
|
|
|
|
/* enable gameport on eap */
|
|
icsc = bus_space_read_4(gpa->gpa_iot, gpa->gpa_ioh, EAP_ICSC);
|
|
icsc &= ~E1371_JOY_ASELBITS;
|
|
icsc |= EAP_JYSTK_EN | E1371_JOY_ASEL(i);
|
|
bus_space_write_4(gpa->gpa_iot, gpa->gpa_ioh, EAP_ICSC, icsc);
|
|
|
|
aa.aa_aaa.type = AUDIODEV_TYPE_AUX;
|
|
aa.aa_iot = gpa->gpa_iot;
|
|
aa.aa_ioh = ioh;
|
|
joydev = config_found(eapdev, &aa, 0);
|
|
/* this cannot fail */
|
|
KASSERT(joydev != NULL);
|
|
|
|
return (joydev);
|
|
}
|
|
|
|
int
|
|
eap_joy_detach(struct device *joydev, struct eap_gameport_args *gpa)
|
|
{
|
|
int res;
|
|
struct joy_softc *sc = (struct joy_softc *)joydev;
|
|
u_int32_t icsc;
|
|
|
|
res = config_detach(joydev, 0);
|
|
if (res)
|
|
return (res);
|
|
|
|
/* disable gameport on eap */
|
|
icsc = bus_space_read_4(gpa->gpa_iot, gpa->gpa_ioh, EAP_ICSC);
|
|
icsc &= ~EAP_JYSTK_EN;
|
|
bus_space_write_4(gpa->gpa_iot, gpa->gpa_ioh, EAP_ICSC, icsc);
|
|
|
|
bus_space_unmap(sc->sc_iot, sc->sc_ioh, 1);
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
joy_eap_match(struct device *parent, struct cfdata *match, void *aux)
|
|
{
|
|
struct joy_eap_aa *eaa = aux;
|
|
|
|
if (eaa->aa_aaa.type != AUDIODEV_TYPE_AUX)
|
|
return (0);
|
|
return (1);
|
|
}
|
|
|
|
void
|
|
joy_eap_attach(struct device *parent, struct device *self, void *aux)
|
|
{
|
|
struct joy_softc *sc = (struct joy_softc *)self;
|
|
struct joy_eap_aa *eaa = aux;
|
|
|
|
printf("\n");
|
|
|
|
sc->sc_iot = eaa->aa_iot;
|
|
sc->sc_ioh = eaa->aa_ioh;
|
|
|
|
joyattach(sc);
|
|
}
|
|
|
|
int
|
|
joy_eap_detach(struct device *self, int flags)
|
|
{
|
|
|
|
#ifdef notyet
|
|
return (joydetach((struct joy_softc *)self));
|
|
#else
|
|
return (EBUSY);
|
|
#endif
|
|
}
|