Plug and Play support.
This commit is contained in:
parent
5714664cf5
commit
cf455412fc
|
@ -0,0 +1,22 @@
|
|||
# $NetBSD: files.isapnp,v 1.1 1997/01/16 22:00:57 christos Exp $
|
||||
#
|
||||
# Config.new file and device description for machine-independent ISAPnP code.
|
||||
# Included by ports that need it.
|
||||
|
||||
# XXX: We don't use locators currenly...
|
||||
|
||||
device isapnp {[port = -1], [size = 0],
|
||||
[iomem = -1], [iosiz = 0],
|
||||
[irq = -1], [drq = -1]}
|
||||
attach isapnp at isa
|
||||
file dev/isapnp/isapnp.c isapnp
|
||||
file dev/isapnp/isapnpdebug.c isapnp
|
||||
file dev/isapnp/isapnpres.c isapnp
|
||||
|
||||
#
|
||||
# ISAPnP Sound hardware
|
||||
#
|
||||
|
||||
# SoundBlaster family
|
||||
attach sb at isapnp with sb_isapnp
|
||||
file dev/isapnp/sb_isapnp.c sb_isapnp
|
|
@ -0,0 +1,819 @@
|
|||
/* $NetBSD: isapnp.c,v 1.1 1997/01/16 22:00:59 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christos Zoulas.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ISA PnP bus autoconfiguration.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
|
||||
#include <dev/isapnp/isapnpreg.h>
|
||||
#include <dev/isapnp/isapnpvar.h>
|
||||
|
||||
static void isapnp_init __P((struct isapnp_softc *));
|
||||
static __inline u_char isapnp_shift_bit __P((struct isapnp_softc *));
|
||||
static int isapnp_findcard __P((struct isapnp_softc *));
|
||||
static void isapnp_free_region __P((bus_space_tag_t, struct isapnp_region *));
|
||||
static int isapnp_alloc_region __P((bus_space_tag_t, struct isapnp_region *));
|
||||
static int isapnp_alloc_pin __P((struct isapnp_pin *));
|
||||
static int isapnp_testconfig __P((bus_space_tag_t, bus_space_tag_t,
|
||||
struct isapnp_attach_args *, int));
|
||||
static struct isapnp_attach_args *isapnp_bestconfig __P((struct isapnp_softc *,
|
||||
struct isapnp_attach_args **));
|
||||
static void isapnp_print_region __P((const char *, struct isapnp_region *,
|
||||
size_t));
|
||||
static void isapnp_configure __P((struct isapnp_softc *,
|
||||
const struct isapnp_attach_args *));
|
||||
static void isapnp_print_pin __P((const char *, struct isapnp_pin *, size_t));
|
||||
static int isapnp_print __P((void *, const char *));
|
||||
static int isapnp_submatch __P((struct device *, void *, void *));
|
||||
static int isapnp_find __P((struct isapnp_softc *));
|
||||
static int isapnp_match __P((struct device *, void *, void *));
|
||||
static void isapnp_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfattach isapnp_ca = {
|
||||
sizeof(struct isapnp_softc), isapnp_match, isapnp_attach
|
||||
};
|
||||
|
||||
struct cfdriver isapnp_cd = {
|
||||
NULL, "isapnp", DV_DULL
|
||||
};
|
||||
|
||||
|
||||
/* isapnp_init():
|
||||
* Write the PNP initiation key to wake up the cards...
|
||||
*/
|
||||
static void
|
||||
isapnp_init(sc)
|
||||
struct isapnp_softc *sc;
|
||||
{
|
||||
int i;
|
||||
u_char v = ISAPNP_LFSR_INIT;
|
||||
|
||||
/* First write 0's twice to enter the Wait for Key state */
|
||||
ISAPNP_WRITE_ADDR(sc, 0);
|
||||
ISAPNP_WRITE_ADDR(sc, 0);
|
||||
|
||||
/* Send the 32 byte sequence to awake the logic */
|
||||
for (i = 0; i < 32; i++) {
|
||||
ISAPNP_WRITE_ADDR(sc, v);
|
||||
v = ISAPNP_LFSR_NEXT(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_shift_bit():
|
||||
* Read a bit at a time from the config card.
|
||||
*/
|
||||
static __inline u_char
|
||||
isapnp_shift_bit(sc)
|
||||
struct isapnp_softc *sc;
|
||||
{
|
||||
u_char c1, c2;
|
||||
|
||||
DELAY(250);
|
||||
c1 = ISAPNP_READ_DATA(sc);
|
||||
DELAY(250);
|
||||
c2 = ISAPNP_READ_DATA(sc);
|
||||
|
||||
if (c1 == 0x55 && c2 == 0xAA)
|
||||
return 0x80;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_findcard():
|
||||
* Attempt to read the vendor/serial/checksum for a card
|
||||
* If a card is found [the checksum matches], assign the
|
||||
* next card number to it and return 1
|
||||
*/
|
||||
static int
|
||||
isapnp_findcard(sc)
|
||||
struct isapnp_softc *sc;
|
||||
{
|
||||
u_char v = ISAPNP_LFSR_INIT, csum = 0, w;
|
||||
int i, b;
|
||||
|
||||
if (sc->sc_ncards == ISAPNP_MAX_CARDS) {
|
||||
printf("%s: Too many pnp cards\n", sc->sc_dev.dv_xname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the read port */
|
||||
isapnp_write_reg(sc, ISAPNP_WAKE, 0);
|
||||
isapnp_write_reg(sc, ISAPNP_SET_RD_PORT, sc->sc_read_port >> 2);
|
||||
sc->sc_read_port |= 3;
|
||||
DELAY(1000);
|
||||
|
||||
ISAPNP_WRITE_ADDR(sc, ISAPNP_SERIAL_ISOLATION);
|
||||
DELAY(1000);
|
||||
|
||||
/* Read the 8 bytes of the Vendor ID and Serial Number */
|
||||
for(i = 0; i < 8; i++) {
|
||||
/* Read each bit separately */
|
||||
for (w = 0, b = 0; b < 8; b++) {
|
||||
u_char neg = isapnp_shift_bit(sc);
|
||||
|
||||
w >>= 1;
|
||||
w |= neg;
|
||||
v = ISAPNP_LFSR_NEXT(v) ^ neg;
|
||||
}
|
||||
sc->sc_id[sc->sc_ncards][i] = w;
|
||||
}
|
||||
|
||||
/* Read the remaining checksum byte */
|
||||
for (b = 0; b < 8; b++) {
|
||||
u_char neg = isapnp_shift_bit(sc);
|
||||
|
||||
csum >>= 1;
|
||||
csum |= neg;
|
||||
sc->sc_id[sc->sc_ncards][9] = w;
|
||||
}
|
||||
|
||||
if (csum == v) {
|
||||
sc->sc_ncards++;
|
||||
isapnp_write_reg(sc, ISAPNP_CARD_SELECT_NUM, sc->sc_ncards);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_free_region():
|
||||
* Free a region
|
||||
*/
|
||||
static void
|
||||
isapnp_free_region(t, r)
|
||||
bus_space_tag_t t;
|
||||
struct isapnp_region *r;
|
||||
{
|
||||
bus_space_unmap(t, r->h, r->length);
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_alloc_region():
|
||||
* Allocate a single region if possible
|
||||
*/
|
||||
static int
|
||||
isapnp_alloc_region(t, r)
|
||||
bus_space_tag_t t;
|
||||
struct isapnp_region *r;
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
for (r->base = r->minbase; r->base <= r->maxbase; r->base += r->align) {
|
||||
error = bus_space_map(t, r->base, r->length, 0, &r->h);
|
||||
if (error == 0)
|
||||
return 0;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_alloc_pin():
|
||||
* Allocate an irq/drq
|
||||
* XXX: No resource conflict checks!
|
||||
*/
|
||||
static int
|
||||
isapnp_alloc_pin(i)
|
||||
struct isapnp_pin *i;
|
||||
{
|
||||
int b;
|
||||
|
||||
if (i->bits == 0)
|
||||
i->num = 0;
|
||||
else
|
||||
for (b = 0; b < 16; b++)
|
||||
if (i->bits & (1 << b))
|
||||
i->num = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_testconfig():
|
||||
* Test/Allocate the regions used
|
||||
*/
|
||||
static int
|
||||
isapnp_testconfig(iot, memt, ipa, alloc)
|
||||
bus_space_tag_t iot, memt;
|
||||
struct isapnp_attach_args *ipa;
|
||||
int alloc;
|
||||
{
|
||||
int nio = 0, nmem = 0, nmem32 = 0, nirq = 0, ndrq = 0;
|
||||
int error = 0;
|
||||
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_attach(ipa);
|
||||
#endif
|
||||
|
||||
for (; nio < ipa->ipa_nio; nio++) {
|
||||
error = isapnp_alloc_region(iot, &ipa->ipa_io[nio]);
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (; nmem < ipa->ipa_nmem; nmem++) {
|
||||
error = isapnp_alloc_region(memt, &ipa->ipa_mem[nmem]);
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (; nmem32 < ipa->ipa_nmem32; nmem32++) {
|
||||
error = isapnp_alloc_region(memt, &ipa->ipa_mem32[nmem32]);
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (; nirq < ipa->ipa_nirq; nirq++) {
|
||||
error = isapnp_alloc_pin(&ipa->ipa_irq[nirq]);
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
for (; ndrq < ipa->ipa_ndrq; ndrq++) {
|
||||
error = isapnp_alloc_pin(&ipa->ipa_drq[ndrq]);
|
||||
if (error)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (alloc)
|
||||
return error;
|
||||
|
||||
bad:
|
||||
#ifdef notyet
|
||||
for (ndrq--; ndrq >= 0; ndrq--)
|
||||
isapnp_free_pin(&ipa->ipa_drq[ndrq]);
|
||||
|
||||
for (nirq--; nirq >= 0; nirq--)
|
||||
isapnp_free_pin(&ipa->ipa_irq[nirq]);
|
||||
#endif
|
||||
|
||||
for (nmem32--; nmem32 >= 0; nmem32--)
|
||||
isapnp_free_region(memt, &ipa->ipa_mem32[nmem32]);
|
||||
|
||||
for (nmem--; nmem >= 0; nmem--)
|
||||
isapnp_free_region(memt, &ipa->ipa_mem[nmem]);
|
||||
|
||||
for (nio--; nio >= 0; nio--)
|
||||
isapnp_free_region(iot, &ipa->ipa_io[nio]);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_config():
|
||||
* Test/Allocate the regions used
|
||||
*/
|
||||
int
|
||||
isapnp_config(iot, memt, ipa)
|
||||
bus_space_tag_t iot, memt;
|
||||
struct isapnp_attach_args *ipa;
|
||||
{
|
||||
return isapnp_testconfig(iot, memt, ipa, 1);
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_unconfig():
|
||||
* Free the regions used
|
||||
*/
|
||||
void
|
||||
isapnp_unconfig(iot, memt, ipa)
|
||||
bus_space_tag_t iot, memt;
|
||||
struct isapnp_attach_args *ipa;
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef notyet
|
||||
for (i = 0; i < ipa->ipa_ndrq; i++)
|
||||
isapnp_free_pin(&ipa->ipa_drq[i]);
|
||||
|
||||
for (i = 0; i < ipa->ipa_nirq; i++)
|
||||
isapnp_free_pin(&ipa->ipa_irq[i]);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ipa->ipa_nmem32; i++)
|
||||
isapnp_free_region(memt, &ipa->ipa_mem32[i]);
|
||||
|
||||
for (i = 0; i < ipa->ipa_nmem; i++)
|
||||
isapnp_free_region(memt, &ipa->ipa_mem[i]);
|
||||
|
||||
for (i = 0; i < ipa->ipa_nio; i++)
|
||||
isapnp_free_region(iot, &ipa->ipa_io[i]);
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_bestconfig():
|
||||
* Return the best configuration for each logical device, remove and
|
||||
* free all other configurations.
|
||||
*/
|
||||
static struct isapnp_attach_args *
|
||||
isapnp_bestconfig(sc, ipa)
|
||||
struct isapnp_softc *sc;
|
||||
struct isapnp_attach_args **ipa;
|
||||
{
|
||||
struct isapnp_attach_args *c, *best, *f = *ipa;
|
||||
int error;
|
||||
|
||||
for (;;) {
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
|
||||
#define SAMEDEV(a, b) (strcmp((a)->ipa_devlogic, (b)->ipa_devlogic) == 0)
|
||||
|
||||
/* Find the best config */
|
||||
for (best = c = f; c != NULL; c = c->ipa_next) {
|
||||
if (!SAMEDEV(c, f))
|
||||
continue;
|
||||
if (c->ipa_pref < best->ipa_pref)
|
||||
best = c;
|
||||
}
|
||||
|
||||
/* Test the best config */
|
||||
error = isapnp_testconfig(sc->sc_iot, sc->sc_memt, best, 0);
|
||||
|
||||
/* Remove this config from the list */
|
||||
if (best == f)
|
||||
f = f->ipa_next;
|
||||
else {
|
||||
for (c = f; c->ipa_next != best; c = c->ipa_next)
|
||||
continue;
|
||||
c->ipa_next = best->ipa_next;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
best->ipa_pref = ISAPNP_DEP_CONFLICTING;
|
||||
|
||||
for (c = f; c != NULL; c = c->ipa_next)
|
||||
if (c != best && SAMEDEV(c, best))
|
||||
break;
|
||||
/* Last config for this logical device is conflicting */
|
||||
if (c == NULL) {
|
||||
*ipa = f;
|
||||
return best;
|
||||
}
|
||||
|
||||
ISAPNP_FREE(best);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
/* Remove all other configs for this device */
|
||||
struct isapnp_attach_args *l = NULL, *n = NULL, *d;
|
||||
|
||||
for (c = f; c; ) {
|
||||
if (c == best)
|
||||
continue;
|
||||
d = c->ipa_next;
|
||||
if (SAMEDEV(c, best))
|
||||
ISAPNP_FREE(c);
|
||||
else {
|
||||
if (n)
|
||||
n->ipa_next = c;
|
||||
|
||||
else
|
||||
l = c;
|
||||
n = c;
|
||||
c->ipa_next = NULL;
|
||||
}
|
||||
c = d;
|
||||
}
|
||||
f = l;
|
||||
}
|
||||
*ipa = f;
|
||||
return best;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_id_to_vendor():
|
||||
* Convert a pnp ``compressed ascii'' vendor id to a string
|
||||
*/
|
||||
char *
|
||||
isapnp_id_to_vendor(v, id)
|
||||
char *v;
|
||||
const u_char *id;
|
||||
{
|
||||
static const char hex[] = "0123456789ABCDEF";
|
||||
char *p = v;
|
||||
|
||||
*p++ = 'A' + (id[0] >> 2) - 1;
|
||||
*p++ = 'A' + ((id[0] & 3) << 3) + (id[1] >> 5) - 1;
|
||||
*p++ = 'A' + (id[1] & 0x1f) - 1;
|
||||
*p++ = hex[id[2] >> 4];
|
||||
*p++ = hex[id[2] & 0x0f];
|
||||
*p++ = hex[id[3] >> 4];
|
||||
*p++ = hex[id[3] & 0x0f];
|
||||
*p = '\0';
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_print_region():
|
||||
* Print a region allocation
|
||||
*/
|
||||
static void
|
||||
isapnp_print_region(str, r, n)
|
||||
const char *str;
|
||||
struct isapnp_region *r;
|
||||
size_t n;
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
printf(" %s ", str);
|
||||
for (i = 0; i < n; i++, r++) {
|
||||
printf("0x%x", r->base);
|
||||
if (r->length)
|
||||
printf("/%d", r->length);
|
||||
if (i != n - 1)
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_print_pin():
|
||||
* Print an irq/drq assignment
|
||||
*/
|
||||
static void
|
||||
isapnp_print_pin(str, p, n)
|
||||
const char *str;
|
||||
struct isapnp_pin *p;
|
||||
size_t n;
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
printf(" %s ", str);
|
||||
for (i = 0; i < n; i++, p++) {
|
||||
printf("%d", p->num);
|
||||
if (i != n - 1)
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_print():
|
||||
* Print the configuration line for an ISA PnP card.
|
||||
*/
|
||||
static int
|
||||
isapnp_print(aux, str)
|
||||
void *aux;
|
||||
const char *str;
|
||||
{
|
||||
struct isapnp_attach_args *ipa = aux;
|
||||
|
||||
if (str != NULL)
|
||||
printf("%s: <%s, %s, %s>",
|
||||
str, ipa->ipa_devident, ipa->ipa_devlogic,
|
||||
ipa->ipa_devclass);
|
||||
|
||||
isapnp_print_region("port", ipa->ipa_io, ipa->ipa_nio);
|
||||
isapnp_print_region("mem", ipa->ipa_mem, ipa->ipa_nmem);
|
||||
isapnp_print_region("mem32", ipa->ipa_mem32, ipa->ipa_nmem32);
|
||||
isapnp_print_pin("irq", ipa->ipa_irq, ipa->ipa_nirq);
|
||||
isapnp_print_pin("drq", ipa->ipa_drq, ipa->ipa_ndrq);
|
||||
|
||||
return UNCONF;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_submatch():
|
||||
* Probe the card...
|
||||
*/
|
||||
static int
|
||||
isapnp_submatch(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
struct cfdata *cf = match;
|
||||
return ((*cf->cf_attach->ca_match)(parent, match, aux));
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_find():
|
||||
* Probe and add cards
|
||||
*/
|
||||
static int
|
||||
isapnp_find(sc)
|
||||
struct isapnp_softc *sc;
|
||||
{
|
||||
int p;
|
||||
|
||||
isapnp_init(sc);
|
||||
|
||||
isapnp_write_reg(sc, ISAPNP_CONFIG_CONTROL, ISAPNP_CC_RESET_DRV);
|
||||
DELAY(2000);
|
||||
|
||||
isapnp_init(sc);
|
||||
DELAY(2000);
|
||||
|
||||
for (p = ISAPNP_RDDATA_MIN; p <= ISAPNP_RDDATA_MAX; p += 4) {
|
||||
sc->sc_read_port = p;
|
||||
if (isapnp_map_readport(sc))
|
||||
continue;
|
||||
DPRINTF(("%s: Trying port %x\n", sc->sc_dev.dv_xname, p));
|
||||
if (isapnp_findcard(sc))
|
||||
break;
|
||||
isapnp_unmap_readport(sc);
|
||||
}
|
||||
|
||||
if (p > ISAPNP_RDDATA_MAX) {
|
||||
sc->sc_read_port = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (isapnp_findcard(sc))
|
||||
continue;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_configure():
|
||||
* Configure a PnP card
|
||||
* XXX: The memory configuration code is wrong. We need to check the
|
||||
* range/length bit an do appropriate sets.
|
||||
*/
|
||||
static void
|
||||
isapnp_configure(sc, ipa)
|
||||
struct isapnp_softc *sc;
|
||||
const struct isapnp_attach_args *ipa;
|
||||
{
|
||||
int i;
|
||||
static u_char isapnp_mem_range[] = ISAPNP_MEM_DESC;
|
||||
static u_char isapnp_io_range[] = ISAPNP_IO_DESC;
|
||||
static u_char isapnp_irq_range[] = ISAPNP_IRQ_DESC;
|
||||
static u_char isapnp_drq_range[] = ISAPNP_DRQ_DESC;
|
||||
static u_char isapnp_mem32_range[] = ISAPNP_MEM32_DESC;
|
||||
const struct isapnp_region *r;
|
||||
const struct isapnp_pin *p;
|
||||
struct isapnp_region rz;
|
||||
struct isapnp_pin pz;
|
||||
|
||||
memset(&pz, 0, sizeof(pz));
|
||||
memset(&rz, 0, sizeof(rz));
|
||||
|
||||
#define B0(a) ((a) & 0xff)
|
||||
#define B1(a) (((a) >> 8) & 0xff)
|
||||
#define B2(a) (((a) >> 16) & 0xff)
|
||||
#define B3(a) (((a) >> 24) & 0xff)
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_io_range); i++) {
|
||||
if (i < ipa->ipa_nio)
|
||||
r = &ipa->ipa_io[i];
|
||||
else
|
||||
r = &rz;
|
||||
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_io_range[i] + ISAPNP_IO_BASE_15_8, B1(r->base));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_io_range[i] + ISAPNP_IO_BASE_7_0, B0(r->base));
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_mem_range); i++) {
|
||||
if (i < ipa->ipa_nmem)
|
||||
r = &ipa->ipa_mem[i];
|
||||
else
|
||||
r = &rz;
|
||||
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_BASE_23_16, B2(r->base));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_BASE_15_8, B1(r->base));
|
||||
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_23_16,
|
||||
B2(r->length));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_15_8,
|
||||
B1(r->length));
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_irq_range); i++) {
|
||||
u_char v;
|
||||
|
||||
if (i < ipa->ipa_nirq)
|
||||
p = &ipa->ipa_irq[i];
|
||||
else
|
||||
p = &pz;
|
||||
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_irq_range[i] + ISAPNP_IRQ_NUMBER, p->num);
|
||||
|
||||
switch (p->flags) {
|
||||
case ISAPNP_IRQTYPE_LEVEL_PLUS:
|
||||
v = ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH;
|
||||
break;
|
||||
|
||||
case ISAPNP_IRQTYPE_EDGE_PLUS:
|
||||
v = ISAPNP_IRQ_HIGH;
|
||||
break;
|
||||
|
||||
case ISAPNP_IRQTYPE_LEVEL_MINUS:
|
||||
v = ISAPNP_IRQ_LEVEL;
|
||||
break;
|
||||
|
||||
default:
|
||||
case ISAPNP_IRQTYPE_EDGE_MINUS:
|
||||
v = 0;
|
||||
break;
|
||||
}
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_irq_range[i] + ISAPNP_IRQ_CONTROL, v);
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_drq_range); i++) {
|
||||
u_char v;
|
||||
|
||||
if (i < ipa->ipa_ndrq)
|
||||
v = ipa->ipa_drq[i].num;
|
||||
else
|
||||
v = 4;
|
||||
|
||||
isapnp_write_reg(sc, isapnp_drq_range[i], v);
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_mem32_range); i++) {
|
||||
if (i < ipa->ipa_nmem32)
|
||||
r = &ipa->ipa_mem32[i];
|
||||
else
|
||||
r = &rz;
|
||||
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_31_24,
|
||||
B3(r->base));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_23_16,
|
||||
B2(r->base));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_15_8,
|
||||
B1(r->base));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_7_0,
|
||||
B0(r->base));
|
||||
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_31_24,
|
||||
B3(r->length));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_23_16,
|
||||
B2(r->length));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_15_8,
|
||||
B1(r->length));
|
||||
isapnp_write_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_7_0,
|
||||
B0(r->length));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_match():
|
||||
* Probe routine
|
||||
*/
|
||||
static int
|
||||
isapnp_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
int rv;
|
||||
struct isapnp_softc sc;
|
||||
struct isa_attach_args *ia = aux;
|
||||
|
||||
sc.sc_iot = ia->ia_iot;
|
||||
ia->ia_iobase = ISAPNP_ADDR;
|
||||
ia->ia_iosize = 1;
|
||||
(void) strcpy(sc.sc_dev.dv_xname, "(isapnp probe)");
|
||||
|
||||
if (isapnp_map(&sc))
|
||||
return 0;
|
||||
|
||||
rv = isapnp_find(&sc);
|
||||
|
||||
isapnp_unmap(&sc);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_attach
|
||||
* Find and attach PnP cards.
|
||||
*/
|
||||
static void
|
||||
isapnp_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct isapnp_softc *sc = (struct isapnp_softc *) self;
|
||||
struct isa_attach_args *ia = aux;
|
||||
int c, d;
|
||||
|
||||
sc->sc_iot = ia->ia_iot;
|
||||
sc->sc_memt = ia->ia_memt;
|
||||
sc->sc_ncards = 0;
|
||||
|
||||
if (isapnp_map(sc))
|
||||
panic("%s: bus map failed\n", sc->sc_dev.dv_xname);
|
||||
|
||||
if (!isapnp_find(sc))
|
||||
panic("%s: no devices found\n", sc->sc_dev.dv_xname);
|
||||
|
||||
printf(": read port 0x%x\n", sc->sc_read_port);
|
||||
|
||||
for (c = 0; c < sc->sc_ncards; c++) {
|
||||
struct isapnp_attach_args *ipa, *lpa;
|
||||
|
||||
/* Good morning card c */
|
||||
isapnp_write_reg(sc, ISAPNP_WAKE, c + 1);
|
||||
|
||||
if ((ipa = isapnp_get_resource(sc, c)) == NULL)
|
||||
continue;
|
||||
|
||||
|
||||
DPRINTF(("Selecting attachments\n"));
|
||||
for (d = 0; (lpa = isapnp_bestconfig(sc, &ipa)) != NULL; d++) {
|
||||
isapnp_write_reg(sc, ISAPNP_LOGICAL_DEV_NUM, d);
|
||||
isapnp_configure(sc, lpa);
|
||||
#ifdef DEBUG_ISAPNP
|
||||
{
|
||||
struct isapnp_attach_args pa;
|
||||
isapnp_get_config(sc, &pa);
|
||||
isapnp_print_config(&pa);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/* XXX do we even really need this? --thorpej */
|
||||
printf("%s: configuring <%s, %s, %s>\n",
|
||||
sc->sc_dev.dv_xname,
|
||||
lpa->ipa_devident, lpa->ipa_devlogic,
|
||||
lpa->ipa_devclass);
|
||||
#endif
|
||||
|
||||
if (lpa->ipa_pref == ISAPNP_DEP_CONFLICTING) {
|
||||
printf("%s: <%s, %s, %s> ignored; %s\n",
|
||||
sc->sc_dev.dv_xname,
|
||||
lpa->ipa_devident, lpa->ipa_devlogic,
|
||||
lpa->ipa_devclass, "resource conflict");
|
||||
ISAPNP_FREE(lpa);
|
||||
continue;
|
||||
}
|
||||
|
||||
lpa->ipa_ic = ia->ia_ic;
|
||||
lpa->ipa_iot = ia->ia_iot;
|
||||
lpa->ipa_memt = ia->ia_memt;
|
||||
|
||||
isapnp_write_reg(sc, ISAPNP_ACTIVATE, 1);
|
||||
#ifdef _KERNEL
|
||||
if(config_found_sm(self, lpa, isapnp_print,
|
||||
isapnp_submatch) == NULL)
|
||||
isapnp_write_reg(sc, ISAPNP_ACTIVATE, 0);
|
||||
#else
|
||||
isapnp_print(lpa, NULL);
|
||||
printf("\n");
|
||||
#endif
|
||||
ISAPNP_FREE(lpa);
|
||||
}
|
||||
isapnp_write_reg(sc, ISAPNP_WAKE, 0); /* Good night cards */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,410 @@
|
|||
/* $NetBSD: isapnpdebug.c,v 1.1 1997/01/16 22:01:00 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christos Zoulas.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_ISAPNP
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
|
||||
#include <dev/isapnp/isapnpreg.h>
|
||||
#include <dev/isapnp/isapnpvar.h>
|
||||
|
||||
/* isapnp_print_mem():
|
||||
* Print a memory tag
|
||||
*/
|
||||
void
|
||||
isapnp_print_mem(str, mem)
|
||||
const char *str;
|
||||
const struct isapnp_region *mem;
|
||||
{
|
||||
printf("%s, Memory: %s,%sshadowable,decode-%s,%scacheable,%s", str,
|
||||
(mem->flags & ISAPNP_MEMATTR_ROM) ? "ROM," : "RAM,",
|
||||
(mem->flags & ISAPNP_MEMATTR_SHADOWABLE) ? "" : "non-",
|
||||
(mem->flags & ISAPNP_MEMATTR_HIGH_ADDR) ?
|
||||
"high-addr," : "range-len,",
|
||||
(mem->flags & ISAPNP_MEMATTR_CACHEABLE) ? "" : "non-",
|
||||
(mem->flags & ISAPNP_MEMATTR_WRITEABLE) ?
|
||||
"writeable," : "read-only,");
|
||||
|
||||
switch (mem->flags & ISAPNP_MEMWIDTH_MASK) {
|
||||
case ISAPNP_MEMWIDTH_8:
|
||||
printf("8-bit ");
|
||||
break;
|
||||
case ISAPNP_MEMWIDTH_16:
|
||||
printf("16-bit ");
|
||||
break;
|
||||
case ISAPNP_MEMWIDTH_8_16:
|
||||
printf("8/16-bit ");
|
||||
break;
|
||||
case ISAPNP_MEMWIDTH_32:
|
||||
printf("32-bit ");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("min 0x%x, max 0x%x, ", mem->minbase, mem->maxbase);
|
||||
printf("align 0x%x, length 0x%x\n", mem->align, mem->length);
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_print_io():
|
||||
* Print an io tag
|
||||
*/
|
||||
void
|
||||
isapnp_print_io(str, io)
|
||||
const char *str;
|
||||
const struct isapnp_region *io;
|
||||
{
|
||||
printf("%d %s IO Ports: %d address bits, alignment %d ",
|
||||
io->length, str, (io->flags & ISAPNP_IOFLAGS_16) ? 16 : 10,
|
||||
io->align);
|
||||
|
||||
printf("min 0x%x, max 0x%x\n", io->minbase, io->maxbase);
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_print_irq():
|
||||
* Print an irq tag
|
||||
*/
|
||||
void
|
||||
isapnp_print_irq(str, irq)
|
||||
const char *str;
|
||||
const struct isapnp_pin *irq;
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("%sIRQ's supported: ", str);
|
||||
for (i = 0; i < 16; i++)
|
||||
if (irq->bits & (1 << i))
|
||||
printf("%d ", i);
|
||||
|
||||
if (irq->flags & ISAPNP_IRQTYPE_EDGE_PLUS)
|
||||
printf("E+");
|
||||
if (irq->flags & ISAPNP_IRQTYPE_EDGE_MINUS)
|
||||
printf("E-");
|
||||
if (irq->flags & ISAPNP_IRQTYPE_LEVEL_PLUS)
|
||||
printf("L+");
|
||||
if (irq->flags & ISAPNP_IRQTYPE_LEVEL_MINUS)
|
||||
printf("L-");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* isapnp_print_drq():
|
||||
* Print a drq tag
|
||||
*/
|
||||
void
|
||||
isapnp_print_drq(str, drq)
|
||||
const char *str;
|
||||
const struct isapnp_pin *drq;
|
||||
{
|
||||
int i;
|
||||
u_char flags = drq->flags;
|
||||
|
||||
printf("%sDRQ's supported: ", str);
|
||||
for (i = 0; i < 8; i++)
|
||||
if (drq->bits & (1 << i))
|
||||
printf("%d ", i);
|
||||
|
||||
printf("Width: ");
|
||||
switch (flags & ISAPNP_DMAWIDTH_MASK) {
|
||||
case ISAPNP_DMAWIDTH_8:
|
||||
printf("8-bit ");
|
||||
break;
|
||||
case ISAPNP_DMAWIDTH_8_16:
|
||||
printf("8/16-bit ");
|
||||
break;
|
||||
case ISAPNP_DMAWIDTH_16:
|
||||
printf("16-bit ");
|
||||
break;
|
||||
case ISAPNP_DMAWIDTH_RESERVED:
|
||||
printf("Reserved ");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Speed: ");
|
||||
switch (flags & ISAPNP_DMASPEED_MASK) {
|
||||
case ISAPNP_DMASPEED_COMPAT:
|
||||
printf("compat ");
|
||||
break;
|
||||
case ISAPNP_DMASPEED_A:
|
||||
printf("A ");
|
||||
break;
|
||||
case ISAPNP_DMASPEED_B:
|
||||
printf("B ");
|
||||
break;
|
||||
case ISAPNP_DMASPEED_F:
|
||||
printf("F ");
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & ISAPNP_DMAATTR_MASK)
|
||||
printf("Attributes: %s%s%s",
|
||||
(flags & ISAPNP_DMAATTR_BUS_MASTER) ? "bus master " : "",
|
||||
(flags & ISAPNP_DMAATTR_INCR_8) ? "incr 8 " : "",
|
||||
(flags & ISAPNP_DMAATTR_INCR_16) ? "incr 16 " : "");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_print_dep_start():
|
||||
* Print a start dependencies tag
|
||||
*/
|
||||
void
|
||||
isapnp_print_dep_start(str, pref)
|
||||
const char *str;
|
||||
const u_char pref;
|
||||
{
|
||||
|
||||
printf("%sconfig: ", str);
|
||||
switch (pref) {
|
||||
case ISAPNP_DEP_PREFERRED:
|
||||
printf("preferred\n");
|
||||
break;
|
||||
|
||||
case ISAPNP_DEP_ACCEPTABLE:
|
||||
printf("acceptable\n");
|
||||
break;
|
||||
|
||||
case ISAPNP_DEP_FUNCTIONAL:
|
||||
printf("functional\n");
|
||||
break;
|
||||
|
||||
case ISAPNP_DEP_UNSET: /* Used internally */
|
||||
printf("unset\n");
|
||||
break;
|
||||
|
||||
case ISAPNP_DEP_CONFLICTING: /* Used internally */
|
||||
printf("conflicting\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("invalid\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isapnp_print_attach(pa)
|
||||
const struct isapnp_attach_args *pa;
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Found %s %s %s ", pa->ipa_devident,
|
||||
pa->ipa_devlogic, pa->ipa_devclass);
|
||||
isapnp_print_dep_start("", pa->ipa_pref);
|
||||
|
||||
for (i = 0; i < pa->ipa_nio; i++)
|
||||
isapnp_print_io("", &pa->ipa_io[i]);
|
||||
|
||||
for (i = 0; i < pa->ipa_nmem; i++)
|
||||
isapnp_print_mem("", &pa->ipa_mem[i]);
|
||||
|
||||
for (i = 0; i < pa->ipa_nirq; i++)
|
||||
isapnp_print_irq("", &pa->ipa_irq[i]);
|
||||
|
||||
for (i = 0; i < pa->ipa_ndrq; i++)
|
||||
isapnp_print_drq("", &pa->ipa_drq[i]);
|
||||
|
||||
for (i = 0; i < pa->ipa_nmem32; i++)
|
||||
isapnp_print_mem("", &pa->ipa_mem32[i]);
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_get_config():
|
||||
* Get the current configuration of the card
|
||||
*/
|
||||
void
|
||||
isapnp_get_config(sc, pa)
|
||||
struct isapnp_softc *sc;
|
||||
struct isapnp_attach_args *pa;
|
||||
{
|
||||
int i;
|
||||
u_char v0, v1, v2, v3;
|
||||
static u_char isapnp_mem_range[] = ISAPNP_MEM_DESC;
|
||||
static u_char isapnp_io_range[] = ISAPNP_IO_DESC;
|
||||
static u_char isapnp_irq_range[] = ISAPNP_IRQ_DESC;
|
||||
static u_char isapnp_drq_range[] = ISAPNP_DRQ_DESC;
|
||||
static u_char isapnp_mem32_range[] = ISAPNP_MEM32_DESC;
|
||||
struct isapnp_region *r;
|
||||
struct isapnp_pin *p;
|
||||
|
||||
memset(pa, 0, sizeof(*pa));
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_io_range); i++) {
|
||||
r = &pa->ipa_io[i];
|
||||
v0 = isapnp_read_reg(sc,
|
||||
isapnp_io_range[i] + ISAPNP_IO_BASE_15_8);
|
||||
v1 = isapnp_read_reg(sc,
|
||||
isapnp_io_range[i] + ISAPNP_IO_BASE_7_0);
|
||||
r->base = (v0 << 8) | v1;
|
||||
if (r->base == 0)
|
||||
break;
|
||||
}
|
||||
pa->ipa_nio = i;
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_mem_range); i++) {
|
||||
r = &pa->ipa_mem[i];
|
||||
v0 = isapnp_read_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_BASE_23_16);
|
||||
v1 = isapnp_read_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_BASE_15_8);
|
||||
r->base = (v0 << 16) | (v1 << 8);
|
||||
if (r->base == 0)
|
||||
break;
|
||||
|
||||
v0 = isapnp_read_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_23_16);
|
||||
v1 = isapnp_read_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_15_8);
|
||||
r->length = (v0 << 16) | (v1 << 8);
|
||||
v0 = isapnp_read_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_CONTROL);
|
||||
r->flags = 0;
|
||||
if (v0 & ISAPNP_MEM_CONTROL_LIMIT)
|
||||
r->flags |= ISAPNP_MEMATTR_HIGH_ADDR;
|
||||
if (v0 & ISAPNP_MEM_CONTROL_16)
|
||||
r->flags |= ISAPNP_MEMWIDTH_16;
|
||||
}
|
||||
pa->ipa_nmem = i;
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_irq_range); i++) {
|
||||
v0 = isapnp_read_reg(sc,
|
||||
isapnp_irq_range[i] + ISAPNP_IRQ_NUMBER);
|
||||
p = &pa->ipa_irq[i];
|
||||
p->num = v0 & 0xf;
|
||||
if (p->num == 0)
|
||||
break;
|
||||
|
||||
switch (v0 & (ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH)) {
|
||||
case ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH:
|
||||
p->flags = ISAPNP_IRQTYPE_LEVEL_PLUS;
|
||||
break;
|
||||
case ISAPNP_IRQ_HIGH:
|
||||
p->flags = ISAPNP_IRQTYPE_EDGE_PLUS;
|
||||
break;
|
||||
case ISAPNP_IRQ_LEVEL:
|
||||
p->flags = ISAPNP_IRQTYPE_LEVEL_MINUS;
|
||||
break;
|
||||
default:
|
||||
p->flags = ISAPNP_IRQTYPE_EDGE_MINUS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pa->ipa_nirq = i;
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_drq_range); i++) {
|
||||
v0 = isapnp_read_reg(sc, isapnp_drq_range[i]);
|
||||
p = &pa->ipa_drq[i];
|
||||
p->num = v0 & 0xf;
|
||||
if (p->num == 4)
|
||||
break;
|
||||
}
|
||||
pa->ipa_ndrq = i;
|
||||
|
||||
for (i = 0; i < sizeof(isapnp_mem32_range); i++) {
|
||||
r = &pa->ipa_mem32[i];
|
||||
v0 = isapnp_read_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_31_24);
|
||||
v1 = isapnp_read_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_23_16);
|
||||
v2 = isapnp_read_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_15_8);
|
||||
v3 = isapnp_read_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_7_0);
|
||||
r->base = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
|
||||
if (r->base == 0)
|
||||
break;
|
||||
|
||||
v0 = isapnp_read_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_31_24);
|
||||
v1 = isapnp_read_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_23_16);
|
||||
v2 = isapnp_read_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_15_8);
|
||||
v3 = isapnp_read_reg(sc,
|
||||
isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_7_0);
|
||||
r->length = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
|
||||
v0 = isapnp_read_reg(sc,
|
||||
isapnp_mem_range[i] + ISAPNP_MEM_CONTROL);
|
||||
r->flags = v0;
|
||||
}
|
||||
pa->ipa_nmem32 = i;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_print_config():
|
||||
* Print the current configuration of the card
|
||||
*/
|
||||
void
|
||||
isapnp_print_config(pa)
|
||||
const struct isapnp_attach_args *pa;
|
||||
{
|
||||
int i;
|
||||
const struct isapnp_region *r;
|
||||
const struct isapnp_pin *p;
|
||||
|
||||
printf("Register configuration:\n");
|
||||
if (pa->ipa_nio)
|
||||
for (i = 0; i < pa->ipa_nio; i++) {
|
||||
r = &pa->ipa_io[i];
|
||||
printf("io[%d]: 0x%x/%d\n", i, r->base, r->length);
|
||||
}
|
||||
|
||||
if (pa->ipa_nmem)
|
||||
for (i = 0; i < pa->ipa_nmem; i++) {
|
||||
r = &pa->ipa_mem[i];
|
||||
printf("mem[%d]: 0x%x/%d\n", i, r->base, r->length);
|
||||
}
|
||||
|
||||
if (pa->ipa_nirq)
|
||||
for (i = 0; i < pa->ipa_nirq; i++) {
|
||||
p = &pa->ipa_irq[i];
|
||||
printf("irq[%d]: %d\n", i, p->num);
|
||||
}
|
||||
|
||||
if (pa->ipa_nirq)
|
||||
for (i = 0; i < pa->ipa_ndrq; i++) {
|
||||
p = &pa->ipa_drq[i];
|
||||
printf("drq[%d]: %d\n", i, p->num);
|
||||
}
|
||||
|
||||
if (pa->ipa_nmem32)
|
||||
for (i = 0; i < pa->ipa_nmem32; i++) {
|
||||
r = &pa->ipa_mem32[i];
|
||||
printf("mem32[%d]: 0x%x/%d\n", i, r->base, r->length);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,171 @@
|
|||
/* $NetBSD: isapnpreg.h,v 1.1 1997/01/16 22:01:02 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christos Zoulas.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ISA Plug and Play register definitions;
|
||||
* From Plug and Play ISA Specification V1.0a, May 5 1994
|
||||
*/
|
||||
|
||||
#define ISAPNP_MAX_CARDS 8
|
||||
#define ISAPNP_MAX_IDENT 32
|
||||
#define ISAPNP_MAX_DEVCLASS 8
|
||||
#define ISAPNP_SERIAL_SIZE 9
|
||||
#define ISAPNP_MAX_TAGSIZE 256
|
||||
|
||||
#define ISAPNP_ADDR 0x279 /* Write only */
|
||||
#define ISAPNP_WRDATA 0xa79 /* Write only */
|
||||
|
||||
/* The read port is in range 0x203 to 0x3ff */
|
||||
#define ISAPNP_RDDATA_MIN 0x203 /* Read only */
|
||||
#define ISAPNP_RDDATA_MAX 0x3ff
|
||||
|
||||
#define ISAPNP_LFSR_INIT 0x6A /* Initial value of LFSR sequence */
|
||||
/* Formula to compute the next value */
|
||||
#define ISAPNP_LFSR_NEXT(v) (((v) >> 1) | (((v) & 1) ^ (((v) & 2) >> 1)) << 7)
|
||||
|
||||
#define ISAPNP_SET_RD_PORT 0x00
|
||||
#define ISAPNP_SERIAL_ISOLATION 0x01
|
||||
#define ISAPNP_CONFIG_CONTROL 0x02
|
||||
#define ISAPNP_CC_RESET 0x01
|
||||
#define ISAPNP_CC_WAIT_FOR KEY 0x02
|
||||
#define ISAPNP_CC_RESET_CSN 0x04
|
||||
#define ISAPNP_CC_RESET_DRV 0x07
|
||||
#define ISAPNP_WAKE 0x03
|
||||
#define ISAPNP_RESOURCE_DATA 0x04
|
||||
#define ISAPNP_STATUS 0x05
|
||||
#define ISAPNP_CARD_SELECT_NUM 0x06
|
||||
#define ISAPNP_LOGICAL_DEV_NUM 0x07
|
||||
|
||||
#define ISAPNP_ACTIVATE 0x30
|
||||
#define ISAPNP_IO_RANGE_CHECK 0x31
|
||||
|
||||
#define ISAPNP_NUM_MEM 4
|
||||
#define ISAPNP_MEM_DESC { 0x40, 0x48, 0x50, 0x58 }
|
||||
#define ISAPNP_MEM_BASE_23_16 0x0
|
||||
#define ISAPNP_MEM_BASE_15_8 0x1
|
||||
#define ISAPNP_MEM_CONTROL 0x2
|
||||
#define ISAPNP_MEM_CONTROL_LIMIT 1
|
||||
#define ISAPNP_MEM_CONTROL_16 2
|
||||
#define ISAPNP_MEM_LRANGE_23_16 0x3
|
||||
#define ISAPNP_MEM_LRANGE_15_8 0x4
|
||||
|
||||
#define ISAPNP_NUM_IO 8
|
||||
#define ISAPNP_IO_DESC { 0x60, 0x62, 0x64, 0x68, 0x6a, 0x6c, 0x6e }
|
||||
#define ISAPNP_IO_BASE_15_8 0x0
|
||||
#define ISAPNP_IO_BASE_7_0 0x1
|
||||
|
||||
#define ISAPNP_NUM_IRQ 16
|
||||
#define ISAPNP_IRQ_DESC { 0x70, 0x72 }
|
||||
#define ISAPNP_IRQ_NUMBER 0x0
|
||||
#define ISAPNP_IRQ_CONTROL 0x1
|
||||
#define ISAPNP_IRQ_LEVEL 1
|
||||
#define ISAPNP_IRQ_HIGH 2
|
||||
|
||||
#define ISAPNP_NUM_DRQ 8
|
||||
#define ISAPNP_DRQ_DESC { 0x74, 0x72 }
|
||||
|
||||
#define ISAPNP_NUM_MEM32 4
|
||||
#define ISAPNP_MEM32_DESC { 0x76, 0x80, 0x90, 0xa0 }
|
||||
#define ISAPNP_MEM32_BASE_31_24 0x0
|
||||
#define ISAPNP_MEM32_BASE_23_16 0x1
|
||||
#define ISAPNP_MEM32_BASE_15_8 0x2
|
||||
#define ISAPNP_MEM32_BASE_7_0 0x3
|
||||
#define ISAPNP_MEM32_CONTROL 0x4
|
||||
#define ISAPNP_MEM32_CONTROL_LIMIT 1
|
||||
#define ISAPNP_MEM32_CONTROL_16 2
|
||||
#define ISAPNP_MEM32_CONTROL_32 6
|
||||
#define ISAPNP_MEM32_LRANGE_31_24 0x5
|
||||
#define ISAPNP_MEM32_LRANGE_23_16 0x6
|
||||
#define ISAPNP_MEM32_LRANGE_15_8 0x7
|
||||
#define ISAPNP_MEM32_LRANGE_7_0 0x8
|
||||
|
||||
/* Small Tags */
|
||||
#define ISAPNP_TAG_VERSION_NUM 0x1
|
||||
#define ISAPNP_TAG_LOGICAL_DEV_ID 0x2
|
||||
#define ISAPNP_TAG_COMPAT_DEV_ID 0x3
|
||||
#define ISAPNP_TAG_IRQ_FORMAT 0x4
|
||||
#define ISAPNP_IRQTYPE_EDGE_PLUS 1
|
||||
#define ISAPNP_IRQTYPE_EDGE_MINUS 2
|
||||
#define ISAPNP_IRQTYPE_LEVEL_PLUS 4
|
||||
#define ISAPNP_IRQTYPE_LEVEL_MINUS 8
|
||||
#define ISAPNP_TAG_DMA_FORMAT 0x5
|
||||
#define ISAPNP_DMAWIDTH_8 0x00
|
||||
#define ISAPNP_DMAWIDTH_8_16 0x01
|
||||
#define ISAPNP_DMAWIDTH_16 0x02
|
||||
#define ISAPNP_DMAWIDTH_RESERVED 0x03
|
||||
#define ISAPNP_DMAWIDTH_MASK 0x03
|
||||
#define ISAPNP_DMAATTR_BUS_MASTER 0x04
|
||||
#define ISAPNP_DMAATTR_INCR_8 0x08
|
||||
#define ISAPNP_DMAATTR_INCR_16 0x10
|
||||
#define ISAPNP_DMAATTR_MASK 0x1c
|
||||
#define ISAPNP_DMASPEED_COMPAT 0x00
|
||||
#define ISAPNP_DMASPEED_A 0x20
|
||||
#define ISAPNP_DMASPEED_B 0x40
|
||||
#define ISAPNP_DMASPEED_F 0x60
|
||||
#define ISAPNP_DMASPEED_MASK 0x60
|
||||
#define ISAPNP_TAG_DEP_START 0x6
|
||||
#define ISAPNP_DEP_PREFERRED 0x0
|
||||
#define ISAPNP_DEP_ACCEPTABLE 0x1
|
||||
#define ISAPNP_DEP_FUNCTIONAL 0x2
|
||||
#define ISAPNP_DEP_RESERVED 0x3
|
||||
#define ISAPNP_DEP_MASK 0x3
|
||||
#define ISAPNP_DEP_UNSET 0x80 /* Internal */
|
||||
#define ISAPNP_DEP_CONFLICTING 0x81 /* Internal */
|
||||
#define ISAPNP_TAG_DEP_END 0x7
|
||||
#define ISAPNP_TAG_IO_PORT_DESC 0x8
|
||||
#define ISAPNP_IOFLAGS_16 0x1
|
||||
#define ISAPNP_TAG_FIXED_IO_PORT_DESC 0x9
|
||||
#define ISAPNP_TAG_RESERVED1 0xa
|
||||
#define ISAPNP_TAG_RESERVED2 0xb
|
||||
#define ISAPNP_TAG_RESERVED3 0xc
|
||||
#define ISAPNP_TAG_RESERVED4 0xd
|
||||
#define ISAPNP_TAG_VENDOR_DEF 0xe
|
||||
#define ISAPNP_TAG_END 0xf
|
||||
|
||||
/* Large Tags */
|
||||
#define ISAPNP_LARGE_TAG 0x80
|
||||
#define ISAPNP_TAG_MEM_RANGE_DESC 0x81
|
||||
#define ISAPNP_MEMATTR_WRITEABLE 0x01
|
||||
#define ISAPNP_MEMATTR_CACHEABLE 0x02
|
||||
#define ISAPNP_MEMATTR_HIGH_ADDR 0x04
|
||||
#define ISAPNP_MEMATTR_SHADOWABLE 0x20
|
||||
#define ISAPNP_MEMATTR_ROM 0x40
|
||||
#define ISAPNP_MEMATTR_MASK 0x67
|
||||
#define ISAPNP_MEMWIDTH_8 0x00
|
||||
#define ISAPNP_MEMWIDTH_16 0x08
|
||||
#define ISAPNP_MEMWIDTH_8_16 0x10
|
||||
#define ISAPNP_MEMWIDTH_32 0x18
|
||||
#define ISAPNP_MEMWIDTH_MASK 0x18
|
||||
#define ISAPNP_TAG_ANSI_IDENT_STRING 0x82
|
||||
#define ISAPNP_TAG_UNICODE_IDENT_STRING 0x83
|
||||
#define ISAPNP_TAG_VENDOR_DEFINED 0x84
|
||||
#define ISAPNP_TAG_MEM32_RANGE_DESC 0x85
|
||||
#define ISAPNP_TAG_FIXED_MEM32_RANGE_DESC 0x86
|
|
@ -0,0 +1,355 @@
|
|||
/* $NetBSD: isapnpres.c,v 1.1 1997/01/16 22:01:03 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christos Zoulas.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Resource parser for Plug and Play cards.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
|
||||
#include <dev/isapnp/isapnpreg.h>
|
||||
#include <dev/isapnp/isapnpvar.h>
|
||||
|
||||
|
||||
static int isapnp_wait_status __P((struct isapnp_softc *));
|
||||
static struct isapnp_attach_args *isapnp_process_tag __P((u_char, u_char,
|
||||
u_char *, struct isapnp_attach_args *));
|
||||
|
||||
|
||||
/* isapnp_wait_status():
|
||||
* Wait for the next byte of resource data to become available
|
||||
*/
|
||||
static int
|
||||
isapnp_wait_status(sc)
|
||||
struct isapnp_softc *sc;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (isapnp_read_reg(sc, ISAPNP_STATUS) & 1)
|
||||
return 0;
|
||||
DELAY(10);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* isapnp_process_tag():
|
||||
* Process a resource tag
|
||||
*/
|
||||
static struct isapnp_attach_args *
|
||||
isapnp_process_tag(tag, len, buf, pa)
|
||||
u_char tag, len, *buf;
|
||||
struct isapnp_attach_args *pa;
|
||||
{
|
||||
struct isapnp_attach_args *npa;
|
||||
char str[64];
|
||||
struct isapnp_region *r;
|
||||
struct isapnp_pin *p;
|
||||
|
||||
#define COPY(a, b) strncpy((a), (b), sizeof(a)), (a)[sizeof(a) - 1] = '\0'
|
||||
|
||||
switch (tag) {
|
||||
case ISAPNP_TAG_VERSION_NUM:
|
||||
DPRINTF(("PnP version %d.%d, Vendor version %d.%d\n",
|
||||
buf[0] >> 4, buf[0] & 0xf, buf[1] >> 4, buf[1] & 0xf));
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_LOGICAL_DEV_ID:
|
||||
(void) isapnp_id_to_vendor(str, buf);
|
||||
DPRINTF(("Logical device id %s\n", str));
|
||||
COPY(pa->ipa_devlogic, str);
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_COMPAT_DEV_ID:
|
||||
(void) isapnp_id_to_vendor(str, buf);
|
||||
DPRINTF(("Compatible device id %s\n", str));
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_IRQ_FORMAT:
|
||||
if (len < 2)
|
||||
break;
|
||||
|
||||
if (len != 3)
|
||||
buf[2] = ISAPNP_IRQTYPE_EDGE_PLUS;
|
||||
|
||||
p = &pa->ipa_irq[pa->ipa_nirq++];
|
||||
p->bits = buf[0] | (buf[1] << 8);
|
||||
p->flags = buf[2];
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_irq("", p);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_DMA_FORMAT:
|
||||
if (buf[0] == 0)
|
||||
break;
|
||||
|
||||
p = &pa->ipa_drq[pa->ipa_ndrq++];
|
||||
p->bits = buf[0];
|
||||
p->flags = buf[1];
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_drq("", p);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_DEP_START:
|
||||
if (len == 0)
|
||||
buf[0] = ISAPNP_DEP_ACCEPTABLE;
|
||||
if (pa->ipa_pref != ISAPNP_DEP_UNSET) {
|
||||
npa = ISAPNP_MALLOC(sizeof(*npa));
|
||||
memset(npa, 0, sizeof(*npa));
|
||||
memcpy(npa->ipa_devident, pa->ipa_devident,
|
||||
sizeof(pa->ipa_devident));
|
||||
memcpy(npa->ipa_devlogic, pa->ipa_devlogic,
|
||||
sizeof(pa->ipa_devlogic));
|
||||
memcpy(npa->ipa_devclass, pa->ipa_devclass,
|
||||
sizeof(pa->ipa_devclass));
|
||||
pa->ipa_next = npa;
|
||||
pa = npa;
|
||||
}
|
||||
pa->ipa_pref = buf[0];
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_dep_start(">>> Start dependent functions ",
|
||||
pa->ipa_pref);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_DEP_END:
|
||||
DPRINTF(("<<<End dependend functions\n"));
|
||||
npa = ISAPNP_MALLOC(sizeof(*npa));
|
||||
memset(npa, 0, sizeof(*npa));
|
||||
npa->ipa_pref = ISAPNP_DEP_UNSET;
|
||||
memcpy(npa->ipa_devident, pa->ipa_devident,
|
||||
sizeof(pa->ipa_devident));
|
||||
|
||||
pa->ipa_next = npa;
|
||||
pa = npa;
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_IO_PORT_DESC:
|
||||
r = &pa->ipa_io[pa->ipa_nio++];
|
||||
r->flags = buf[0];
|
||||
r->minbase = (buf[2] << 8) | buf[1];
|
||||
r->maxbase = (buf[4] << 8) | buf[3];
|
||||
r->align = buf[5];
|
||||
r->length = buf[6];
|
||||
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_io("", r);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_FIXED_IO_PORT_DESC:
|
||||
r = &pa->ipa_io[pa->ipa_nio++];
|
||||
r->flags = 0;
|
||||
r->minbase = (buf[2] << 8) | buf[1];
|
||||
r->maxbase = r->minbase;
|
||||
r->align = 1;
|
||||
r->length = buf[3];
|
||||
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_io("FIXED", r);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_RESERVED1:
|
||||
case ISAPNP_TAG_RESERVED2:
|
||||
case ISAPNP_TAG_RESERVED3:
|
||||
case ISAPNP_TAG_RESERVED4:
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_VENDOR_DEF:
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_END:
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_MEM_RANGE_DESC:
|
||||
r = &pa->ipa_mem[pa->ipa_nmem++];
|
||||
r->minbase = (buf[2] << 8) | buf[1];
|
||||
r->maxbase = (buf[4] << 8) | buf[3];
|
||||
r->align = (buf[6] << 8) | buf[5];
|
||||
r->length = (buf[8] << 8) | buf[7];
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_mem("16 bit", r);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_ANSI_IDENT_STRING:
|
||||
buf[len] = '\0';
|
||||
DPRINTF(("ANSI Ident: %s\n", buf));
|
||||
if (pa->ipa_devident[0] == '\0')
|
||||
COPY(pa->ipa_devident, buf);
|
||||
else
|
||||
COPY(pa->ipa_devclass, buf);
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_UNICODE_IDENT_STRING:
|
||||
buf[len] = '\0';
|
||||
DPRINTF(("Unicode Ident: %s\n", buf));
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_VENDOR_DEFINED:
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_MEM32_RANGE_DESC:
|
||||
r = &pa->ipa_mem32[pa->ipa_nmem32++];
|
||||
r->flags = buf[0];
|
||||
r->minbase = (buf[4] << 24) | (buf[3] << 16) |
|
||||
(buf[2] << 8) | buf[1];
|
||||
r->maxbase = (buf[8] << 24) | (buf[7] << 16) |
|
||||
(buf[6] << 8) | buf[5];
|
||||
r->align = (buf[12] << 24) | (buf[11] << 16) |
|
||||
(buf[10] << 8) | buf[9];
|
||||
r->length = (buf[16] << 24) | (buf[15] << 16) |
|
||||
(buf[14] << 8) | buf[13];
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_mem("32 bit", r);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ISAPNP_TAG_FIXED_MEM32_RANGE_DESC:
|
||||
r = &pa->ipa_mem32[pa->ipa_nmem32++];
|
||||
r->flags = buf[0];
|
||||
r->minbase = (buf[4] << 24) | (buf[3] << 16) |
|
||||
(buf[2] << 8) | buf[1];
|
||||
r->maxbase = r->minbase;
|
||||
r->align = 1;
|
||||
r->length = (buf[8] << 24) | (buf[7] << 16) |
|
||||
(buf[6] << 8) | buf[5];
|
||||
#ifdef DEBUG_ISAPNP
|
||||
isapnp_print_mem("FIXED 32 bit", r);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG_ISAPNP
|
||||
{
|
||||
int i;
|
||||
printf("tag %.2x, len %d: ", tag, len);
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%.2x ", buf[i]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return pa;
|
||||
}
|
||||
|
||||
|
||||
/* isapnp_get_resource():
|
||||
* Read the resources for card c
|
||||
*/
|
||||
struct isapnp_attach_args *
|
||||
isapnp_get_resource(sc, c)
|
||||
struct isapnp_softc *sc;
|
||||
int c;
|
||||
{
|
||||
u_char d, tag;
|
||||
u_short len;
|
||||
int i;
|
||||
struct isapnp_attach_args *ipa, *pa;
|
||||
|
||||
pa = ipa = ISAPNP_MALLOC(sizeof(*ipa));
|
||||
memset(ipa, 0, sizeof(*ipa));
|
||||
pa->ipa_pref = ISAPNP_DEP_UNSET;
|
||||
|
||||
for (i = 0; i < ISAPNP_SERIAL_SIZE; i++) {
|
||||
if (isapnp_wait_status(sc))
|
||||
goto bad;
|
||||
|
||||
d = isapnp_read_reg(sc, ISAPNP_RESOURCE_DATA);
|
||||
|
||||
if (d != sc->sc_id[c][i] && i != ISAPNP_SERIAL_SIZE - 1) {
|
||||
printf("isapnp: card %d violates PnP spec; byte %d\n",
|
||||
c + 1, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
u_char buf[ISAPNP_MAX_TAGSIZE], *p;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
#define NEXT_BYTE \
|
||||
if (isapnp_wait_status(sc)) \
|
||||
goto bad; \
|
||||
d = isapnp_read_reg(sc, ISAPNP_RESOURCE_DATA);
|
||||
|
||||
NEXT_BYTE;
|
||||
|
||||
if (d & ISAPNP_LARGE_TAG) {
|
||||
tag = d;
|
||||
NEXT_BYTE;
|
||||
buf[0] = d;
|
||||
NEXT_BYTE;
|
||||
buf[1] = d;
|
||||
len = (buf[1] << 8) | buf[0];
|
||||
}
|
||||
else {
|
||||
tag = (d >> 3) & 0xf;
|
||||
len = d & 0x7;
|
||||
}
|
||||
|
||||
for (p = buf, i = 0; i < len; i++) {
|
||||
NEXT_BYTE;
|
||||
if (i < ISAPNP_MAX_TAGSIZE)
|
||||
*p++ = d;
|
||||
}
|
||||
|
||||
if (len >= ISAPNP_MAX_TAGSIZE) {
|
||||
printf("isapnp: Maximum tag size exceeded, card %d\n",
|
||||
c + 1);
|
||||
len = ISAPNP_MAX_TAGSIZE;
|
||||
}
|
||||
|
||||
pa = isapnp_process_tag(tag, len, buf, pa);
|
||||
}
|
||||
while (tag != ISAPNP_TAG_END);
|
||||
return ipa;
|
||||
bad:
|
||||
while (ipa) {
|
||||
pa = ipa->ipa_next;
|
||||
ISAPNP_FREE(ipa);
|
||||
ipa = pa;
|
||||
}
|
||||
printf("isapnp: Resource timeout, card %d\n", c + 1);
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/* $NetBSD: isapnpvar.h,v 1.1 1997/01/16 22:01:05 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 Christos Zoulas. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christos Zoulas.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _DEV_ISAPNP_ISAPNPVAR_H_
|
||||
#define _DEV_ISAPNP_ISAPNPVAR_H_
|
||||
|
||||
/*
|
||||
* ISA Plug and Play register definitions;
|
||||
* From Plug and Play ISA Specification V1.0a, May 5 1994
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structures and definitions needed by the machine-dependent header.
|
||||
*/
|
||||
struct isapnp_softc;
|
||||
|
||||
#if (i386 != 1)
|
||||
ERROR: COMPILING FOR UNSUPPORTED MACHINE, OR MORE THAN ONE.
|
||||
#endif
|
||||
#if i386
|
||||
#include <i386/isa/isapnp_machdep.h>
|
||||
#endif
|
||||
|
||||
#ifndef _KERNEL
|
||||
|
||||
# include <string.h>
|
||||
# include <unistd.h>
|
||||
# include <stdlib.h>
|
||||
|
||||
# define ISAPNP_WRITE_ADDR(sc, v) outb(ISAPNP_ADDR, v)
|
||||
# define ISAPNP_WRITE_DATA(sc, v) outb(ISAPNP_WRDATA, v)
|
||||
# define ISAPNP_READ_DATA(sc) inb(sc->sc_read_port)
|
||||
|
||||
# define DELAY(us) usleep(us)
|
||||
# define ISAPNP_MALLOC(a) malloc(a)
|
||||
# define ISAPNP_FREE(a) free(a)
|
||||
|
||||
# define bus_space_map(a, b, c, d, e) 0
|
||||
# define bus_space_unmap(a, b, c)
|
||||
# define panic printf
|
||||
|
||||
#else
|
||||
|
||||
/* XXX */
|
||||
# define memset(a, b, c) bzero(a, c)
|
||||
|
||||
# define ISAPNP_WRITE_ADDR(sc, v) \
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_addr_ioh, 0, v)
|
||||
#define ISAPNP_WRITE_DATA(sc, v) \
|
||||
bus_space_write_1(sc->sc_iot, sc->sc_wrdata_ioh, 0, v)
|
||||
#define ISAPNP_READ_DATA(sc) \
|
||||
bus_space_read_1(sc->sc_iot, sc->sc_read_ioh, 0)
|
||||
|
||||
#define ISAPNP_MALLOC(a) malloc(a, M_DEVBUF, M_WAITOK)
|
||||
#define ISAPNP_FREE(a) free(a, M_DEVBUF)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ISAPNP
|
||||
# define DPRINTF(a) printf a
|
||||
#else
|
||||
# define DPRINTF(a)
|
||||
#endif
|
||||
|
||||
struct isapnp_softc {
|
||||
struct device sc_dev;
|
||||
int sc_read_port;
|
||||
bus_space_tag_t sc_iot;
|
||||
bus_space_tag_t sc_memt;
|
||||
bus_space_handle_t sc_addr_ioh;
|
||||
bus_space_handle_t sc_wrdata_ioh;
|
||||
bus_space_handle_t sc_read_ioh;
|
||||
bus_space_handle_t sc_memh;
|
||||
u_int8_t sc_ncards;
|
||||
u_int8_t sc_id[ISAPNP_MAX_CARDS][ISAPNP_SERIAL_SIZE];
|
||||
};
|
||||
|
||||
struct isapnp_region {
|
||||
bus_space_handle_t h;
|
||||
u_int32_t base;
|
||||
|
||||
u_int32_t minbase;
|
||||
u_int32_t maxbase;
|
||||
u_int32_t length;
|
||||
u_int32_t align;
|
||||
u_int8_t flags;
|
||||
};
|
||||
|
||||
struct isapnp_pin {
|
||||
u_int8_t num;
|
||||
|
||||
u_int16_t bits;
|
||||
u_int8_t flags;
|
||||
};
|
||||
|
||||
struct isapnp_attach_args {
|
||||
bus_space_tag_t ipa_iot; /* isa i/o space tag */
|
||||
bus_space_tag_t ipa_memt; /* isa mem space tag */
|
||||
|
||||
isa_chipset_tag_t ipa_ic;
|
||||
|
||||
struct isapnp_attach_args *ipa_next;
|
||||
|
||||
char ipa_devident[ISAPNP_MAX_IDENT];
|
||||
char ipa_devlogic[ISAPNP_MAX_DEVCLASS];
|
||||
char ipa_devclass[ISAPNP_MAX_DEVCLASS];
|
||||
|
||||
u_char ipa_pref;
|
||||
u_char ipa_devnum;
|
||||
|
||||
u_char ipa_nio;
|
||||
u_char ipa_nirq;
|
||||
u_char ipa_ndrq;
|
||||
u_char ipa_nmem;
|
||||
u_char ipa_nmem32;
|
||||
|
||||
struct isapnp_region ipa_io[ISAPNP_NUM_IO];
|
||||
struct isapnp_region ipa_mem[ISAPNP_NUM_MEM];
|
||||
struct isapnp_region ipa_mem32[ISAPNP_NUM_MEM32];
|
||||
struct isapnp_pin ipa_irq[ISAPNP_NUM_IRQ];
|
||||
struct isapnp_pin ipa_drq[ISAPNP_NUM_DRQ];
|
||||
};
|
||||
|
||||
static __inline void isapnp_write_reg __P((struct isapnp_softc *, int, u_char));
|
||||
static __inline u_char isapnp_read_reg __P((struct isapnp_softc *, int));
|
||||
|
||||
static __inline void
|
||||
isapnp_write_reg(sc, r, v)
|
||||
struct isapnp_softc *sc;
|
||||
int r;
|
||||
u_char v;
|
||||
{
|
||||
ISAPNP_WRITE_ADDR(sc, r);
|
||||
ISAPNP_WRITE_DATA(sc, v);
|
||||
}
|
||||
|
||||
static __inline u_char
|
||||
isapnp_read_reg(sc, r)
|
||||
struct isapnp_softc *sc;
|
||||
{
|
||||
ISAPNP_WRITE_ADDR(sc, r);
|
||||
return ISAPNP_READ_DATA(sc);
|
||||
}
|
||||
|
||||
struct isapnp_attach_args *
|
||||
isapnp_get_resource __P((struct isapnp_softc *, int));
|
||||
char *isapnp_id_to_vendor __P((char *, const u_char *));
|
||||
|
||||
int isapnp_config __P((bus_space_tag_t, bus_space_tag_t,
|
||||
struct isapnp_attach_args *));
|
||||
void isapnp_unconfig __P((bus_space_tag_t, bus_space_tag_t,
|
||||
struct isapnp_attach_args *));
|
||||
|
||||
#ifdef DEBUG_ISAPNP
|
||||
void isapnp_print_mem __P((const char *, const struct isapnp_region *));
|
||||
void isapnp_print_io __P((const char *, const struct isapnp_region *));
|
||||
void isapnp_print_irq __P((const char *, const struct isapnp_pin *));
|
||||
void isapnp_print_drq __P((const char *, const struct isapnp_pin *));
|
||||
void isapnp_print_dep_start __P((const char *, const u_char));
|
||||
void isapnp_print_attach __P((const struct isapnp_attach_args *));
|
||||
void isapnp_get_config __P((struct isapnp_softc *,
|
||||
struct isapnp_attach_args *));
|
||||
void isapnp_print_config __P((const struct isapnp_attach_args *));
|
||||
#endif
|
||||
|
||||
#endif /* ! _DEV_ISAPNP_ISAPNPVAR_H_ */
|
|
@ -0,0 +1,126 @@
|
|||
/* $NetBSD: sb_isapnp.c,v 1.1 1997/01/16 22:01:08 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991-1993 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the Computer Systems
|
||||
* Engineering Group at Lawrence Berkeley Laboratory.
|
||||
* 4. Neither the name of the University nor of the Laboratory may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <sys/audioio.h>
|
||||
#include <dev/audio_if.h>
|
||||
#include <dev/mulaw.h>
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/isa/isadmavar.h>
|
||||
|
||||
#include <dev/isapnp/isapnpreg.h>
|
||||
#include <dev/isapnp/isapnpvar.h>
|
||||
|
||||
#include <dev/isa/sbreg.h>
|
||||
#include <dev/isa/sbvar.h>
|
||||
#include <dev/isa/sbdspvar.h>
|
||||
|
||||
int sb_isapnp_match __P((struct device *, void *, void *));
|
||||
void sb_isapnp_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfattach sb_isapnp_ca = {
|
||||
sizeof(struct sbdsp_softc), sb_isapnp_match, sb_isapnp_attach
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Probe / attach routines.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Probe for the soundblaster hardware.
|
||||
*/
|
||||
int
|
||||
sb_isapnp_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
struct isapnp_attach_args *ipa = aux;
|
||||
|
||||
return strcmp(ipa->ipa_devlogic, "CTL0001") == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Attach hardware to driver, attach hardware driver to audio
|
||||
* pseudo-device driver.
|
||||
*/
|
||||
void
|
||||
sb_isapnp_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct sbdsp_softc *sc = (struct sbdsp_softc *)self;
|
||||
struct isapnp_attach_args *ipa = aux;
|
||||
|
||||
sc->sc_ic = ipa->ipa_ic;
|
||||
|
||||
sc->sc_iot = ipa->ipa_iot;
|
||||
sc->sc_iobase = ipa->ipa_io[0].base;
|
||||
sc->sc_ioh = ipa->ipa_io[0].h;
|
||||
|
||||
sc->sc_irq = ipa->ipa_irq[0].num;
|
||||
sc->sc_drq = ipa->ipa_drq[0].num;
|
||||
sc->sc_drq16 = ipa->ipa_drq[1].num;
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (isapnp_config(ipa->ipa_iot, ipa->ipa_memt, ipa)) {
|
||||
printf("%s: error in region allocation\n", sc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sbmatch(sc)) {
|
||||
printf("%s: sbmatch failed\n", sc->sc_dev.dv_xname);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s: %s %s", sc->sc_dev.dv_xname, ipa->ipa_devident,
|
||||
ipa->ipa_devclass);
|
||||
|
||||
sbattach(sc);
|
||||
}
|
Loading…
Reference in New Issue