Implement /dev/cardbus%d.cis, same thing as /dev/pccard%d.cis. There
are some rough edges with this still, but it seems to work well enough to commit.
This commit is contained in:
parent
10c2623c78
commit
2d3e88cd9e
@ -489,6 +489,7 @@ dev/buslogic/bt_mca.c optional bt mca
|
||||
dev/buslogic/bt_pci.c optional bt pci
|
||||
dev/cardbus/cardbus.c optional cardbus
|
||||
dev/cardbus/cardbus_cis.c optional cardbus
|
||||
dev/cardbus/cardbus_device.c optional cardbus
|
||||
dev/ciss/ciss.c optional ciss
|
||||
dev/cm/smc90cx6.c optional cm
|
||||
dev/cnw/if_cnw.c optional cnw pccard
|
||||
|
@ -406,13 +406,20 @@ cardbus_probe(device_t cbdev)
|
||||
static int
|
||||
cardbus_attach(device_t cbdev)
|
||||
{
|
||||
struct cardbus_softc *sc = device_get_softc(cbdev);
|
||||
|
||||
sc->sc_dev = cbdev;
|
||||
cardbus_device_create(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_detach(device_t cbdev)
|
||||
{
|
||||
struct cardbus_softc *sc = device_get_softc(cbdev);
|
||||
|
||||
cardbus_detach_card(cbdev);
|
||||
cardbus_device_destroy(sc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -58,45 +58,33 @@ extern int cardbus_cis_debug;
|
||||
#define DPRINTF(a) if (cardbus_cis_debug) printf a
|
||||
#define DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
|
||||
|
||||
struct tuple_callbacks;
|
||||
|
||||
typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
|
||||
uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
|
||||
struct tuple_callbacks {
|
||||
int id;
|
||||
char *name;
|
||||
tuple_cb *func;
|
||||
};
|
||||
|
||||
static int decode_tuple_generic(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
static int decode_tuple_linktarget(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
static int decode_tuple_vers_1(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
static int decode_tuple_funcid(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
static int decode_tuple_manfid(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
static int decode_tuple_funce(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
static int decode_tuple_bar(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
static int decode_tuple_unhandled(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
static int decode_tuple_end(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info);
|
||||
struct tuple_callbacks *info, void *);
|
||||
|
||||
static int cardbus_read_tuple_conf(device_t cbdev, device_t child,
|
||||
uint32_t start, uint32_t *off, int *tupleid, int *len,
|
||||
@ -113,9 +101,8 @@ static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child,
|
||||
uint32_t *start, int *rid);
|
||||
static int decode_tuple(device_t cbdev, device_t child, int tupleid,
|
||||
int len, uint8_t *tupledata, uint32_t start,
|
||||
uint32_t *off, struct tuple_callbacks *callbacks);
|
||||
static int cardbus_parse_cis(device_t cbdev, device_t child,
|
||||
struct tuple_callbacks *callbacks);
|
||||
uint32_t *off, struct tuple_callbacks *callbacks,
|
||||
void *);
|
||||
|
||||
#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
|
||||
|
||||
@ -139,7 +126,7 @@ static char *funcnames[] = {
|
||||
static int
|
||||
decode_tuple_generic(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -162,7 +149,7 @@ decode_tuple_generic(device_t cbdev, device_t child, int id,
|
||||
static int
|
||||
decode_tuple_linktarget(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -180,7 +167,7 @@ decode_tuple_linktarget(device_t cbdev, device_t child, int id,
|
||||
tupledata[2] != 'S') {
|
||||
printf("Invalid data for CIS Link Target!\n");
|
||||
decode_tuple_generic(cbdev, child, id, len, tupledata,
|
||||
start, off, info);
|
||||
start, off, info, argp);
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
@ -189,7 +176,7 @@ decode_tuple_linktarget(device_t cbdev, device_t child, int id,
|
||||
static int
|
||||
decode_tuple_vers_1(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -212,7 +199,7 @@ decode_tuple_vers_1(device_t cbdev, device_t child, int id,
|
||||
static int
|
||||
decode_tuple_funcid(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
struct cardbus_devinfo *dinfo = device_get_ivars(child);
|
||||
int numnames = sizeof(funcnames) / sizeof(funcnames[0]);
|
||||
@ -225,7 +212,7 @@ decode_tuple_funcid(device_t cbdev, device_t child, int id,
|
||||
printf("%s", funcnames[tupledata[i]]);
|
||||
else
|
||||
printf("Unknown(%d)", tupledata[i]);
|
||||
if (i < len-1)
|
||||
if (i < len - 1)
|
||||
printf(", ");
|
||||
}
|
||||
printf("\n");
|
||||
@ -238,7 +225,7 @@ decode_tuple_funcid(device_t cbdev, device_t child, int id,
|
||||
static int
|
||||
decode_tuple_manfid(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
struct cardbus_devinfo *dinfo = device_get_ivars(child);
|
||||
int i;
|
||||
@ -260,7 +247,7 @@ decode_tuple_manfid(device_t cbdev, device_t child, int id,
|
||||
static int
|
||||
decode_tuple_funce(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
struct cardbus_devinfo *dinfo = device_get_ivars(child);
|
||||
int type, i;
|
||||
@ -295,7 +282,7 @@ decode_tuple_funce(device_t cbdev, device_t child, int id,
|
||||
static int
|
||||
decode_tuple_bar(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
struct cardbus_devinfo *dinfo = device_get_ivars(child);
|
||||
int type;
|
||||
@ -390,17 +377,17 @@ decode_tuple_bar(device_t cbdev, device_t child, int id,
|
||||
static int
|
||||
decode_tuple_unhandled(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
/* Make this message suck less XXX */
|
||||
printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
|
||||
return (-1);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static int
|
||||
decode_tuple_end(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info)
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
if (cardbus_cis_debug)
|
||||
printf("CIS reading done\n");
|
||||
@ -479,8 +466,9 @@ cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
|
||||
{
|
||||
if (res != (struct resource*)~0UL) {
|
||||
bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
|
||||
pci_write_config(child, rid, 0, 4);
|
||||
PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
|
||||
if (rid == PCIM_CIS_ASI_ROM)
|
||||
pci_write_config(child, rid, pci_read_config(child,
|
||||
rid, 4) & ~PCIR_BIOS, 4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -488,14 +476,14 @@ static struct resource *
|
||||
cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
|
||||
int *rid)
|
||||
{
|
||||
uint32_t testval;
|
||||
uint32_t size;
|
||||
struct resource *res;
|
||||
uint32_t space;
|
||||
|
||||
space = *start & PCIM_CIS_ASI_MASK;
|
||||
switch (space) {
|
||||
case PCIM_CIS_ASI_TUPLE:
|
||||
if (cardbus_cis_debug)
|
||||
device_printf(cbdev, "CIS in PCI config space\n");
|
||||
/* CIS in PCI config space need no initialization */
|
||||
return ((struct resource*)~0UL);
|
||||
case PCIM_CIS_ASI_BAR0:
|
||||
@ -505,9 +493,13 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
|
||||
case PCIM_CIS_ASI_BAR4:
|
||||
case PCIM_CIS_ASI_BAR5:
|
||||
*rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0);
|
||||
if (cardbus_cis_debug)
|
||||
device_printf(cbdev, "CIS in BAR %#x\n", *rid);
|
||||
break;
|
||||
case PCIM_CIS_ASI_ROM:
|
||||
*rid = PCIR_BIOS;
|
||||
if (cardbus_cis_debug)
|
||||
device_printf(cbdev, "CIS in option rom\n");
|
||||
break;
|
||||
default:
|
||||
device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
|
||||
@ -515,35 +507,19 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* figure out how much space we need */
|
||||
pci_write_config(child, *rid, 0xffffffff, 4);
|
||||
testval = pci_read_config(child, *rid, 4);
|
||||
|
||||
/*
|
||||
* This bit has a different meaning depending if we are dealing
|
||||
* with a normal BAR or an Option ROM BAR.
|
||||
*/
|
||||
if (((testval & 0x1) == 0x1) && (*rid != PCIR_BIOS)) {
|
||||
device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
size = CARDBUS_MAPREG_MEM_SIZE(testval);
|
||||
/* XXX Is this some kind of hack? */
|
||||
if (size < 4096)
|
||||
size = 4096;
|
||||
/* allocate the memory space to read CIS */
|
||||
res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
|
||||
rman_make_alignment_flags(size) | RF_ACTIVE);
|
||||
res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, 1,
|
||||
rman_make_alignment_flags(4096) | RF_ACTIVE);
|
||||
if (res == NULL) {
|
||||
device_printf(cbdev, "Unable to allocate resource "
|
||||
"to read CIS.\n");
|
||||
return (NULL);
|
||||
}
|
||||
pci_write_config(child, *rid,
|
||||
rman_get_start(res) | ((*rid == PCIR_BIOS) ? PCIM_BIOS_ENABLE : 0),
|
||||
4);
|
||||
PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
|
||||
pci_write_config(child, *rid, rman_get_start(res), 4);
|
||||
if (*rid == PCIR_BIOS)
|
||||
pci_write_config(child, *rid,
|
||||
rman_get_start(res) | PCIM_BIOS_ENABLE, 4);
|
||||
|
||||
/* Flip to the right ROM image if CIS is in ROM */
|
||||
if (space == PCIM_CIS_ASI_ROM) {
|
||||
@ -626,21 +602,21 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
|
||||
static int
|
||||
decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
|
||||
uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *callbacks)
|
||||
struct tuple_callbacks *callbacks, void *argp)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
|
||||
if (tupleid == callbacks[i].id)
|
||||
return (callbacks[i].func(cbdev, child, tupleid, len,
|
||||
tupledata, start, off, &callbacks[i]));
|
||||
tupledata, start, off, &callbacks[i], argp));
|
||||
}
|
||||
return (callbacks[i].func(cbdev, child, tupleid, len,
|
||||
tupledata, start, off, NULL));
|
||||
tupledata, start, off, NULL, argp));
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
cardbus_parse_cis(device_t cbdev, device_t child,
|
||||
struct tuple_callbacks *callbacks)
|
||||
struct tuple_callbacks *callbacks, void *argp)
|
||||
{
|
||||
uint8_t tupledata[MAXTUPLESIZE];
|
||||
int tupleid;
|
||||
@ -656,6 +632,8 @@ cardbus_parse_cis(device_t cbdev, device_t child,
|
||||
device_printf(cbdev, "CIS pointer is 0!\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (cardbus_cis_debug)
|
||||
device_printf(cbdev, "CIS pointer is %#x\n", start);
|
||||
off = 0;
|
||||
res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
|
||||
if (res == NULL) {
|
||||
@ -664,8 +642,8 @@ cardbus_parse_cis(device_t cbdev, device_t child,
|
||||
}
|
||||
|
||||
do {
|
||||
if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
|
||||
&tupleid, &len, tupledata)) {
|
||||
if (cardbus_read_tuple(cbdev, child, res, start, &off,
|
||||
&tupleid, &len, tupledata) != 0) {
|
||||
device_printf(cbdev, "Failed to read CIS.\n");
|
||||
cardbus_read_tuple_finish(cbdev, child, rid, res);
|
||||
return (ENXIO);
|
||||
@ -678,7 +656,7 @@ cardbus_parse_cis(device_t cbdev, device_t child,
|
||||
return (EINVAL);
|
||||
}
|
||||
expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
|
||||
tupledata, start, &off, callbacks);
|
||||
tupledata, start, &off, callbacks, argp);
|
||||
if (expect_linktarget != 0) {
|
||||
device_printf(cbdev, "Parsing failed with %d\n",
|
||||
expect_linktarget);
|
||||
@ -710,7 +688,7 @@ cardbus_do_cis(device_t cbdev, device_t child)
|
||||
MAKETUPLE(GENERIC, generic),
|
||||
};
|
||||
|
||||
ret = cardbus_parse_cis(cbdev, child, init_callbacks);
|
||||
ret = cardbus_parse_cis(cbdev, child, init_callbacks, NULL);
|
||||
if (ret < 0)
|
||||
return (ret);
|
||||
return 0;
|
||||
|
180
sys/dev/cardbus/cardbus_device.c
Normal file
180
sys/dev/cardbus/cardbus_device.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*-
|
||||
* Copyright (c) 2005, M. Warner Losh
|
||||
* 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 unmodified, 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <sys/pciio.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pci_private.h>
|
||||
|
||||
#include <dev/cardbus/cardbusreg.h>
|
||||
#include <dev/cardbus/cardbusvar.h>
|
||||
#include <dev/cardbus/cardbus_cis.h>
|
||||
#include <dev/pccard/pccard_cis.h>
|
||||
|
||||
static d_open_t cardbus_open;
|
||||
static d_close_t cardbus_close;
|
||||
static d_read_t cardbus_read;
|
||||
static d_ioctl_t cardbus_ioctl;
|
||||
|
||||
static struct cdevsw cardbus_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_open = cardbus_open,
|
||||
.d_close = cardbus_close,
|
||||
.d_read = cardbus_read,
|
||||
.d_ioctl = cardbus_ioctl,
|
||||
.d_name = "cardbus"
|
||||
};
|
||||
|
||||
int
|
||||
cardbus_device_create(struct cardbus_softc *sc)
|
||||
{
|
||||
uint32_t minor;
|
||||
|
||||
minor = device_get_unit(sc->sc_dev) << 16;
|
||||
sc->sc_cisdev = make_dev(&cardbus_cdevsw, minor, 0, 0, 0666,
|
||||
"cardbus%u.cis", device_get_unit(sc->sc_dev));
|
||||
sc->sc_cisdev->si_drv1 = sc;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cardbus_device_destroy(struct cardbus_softc *sc)
|
||||
{
|
||||
if (sc->sc_cisdev)
|
||||
destroy_dev(sc->sc_cisdev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_build_cis(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info, void *argp)
|
||||
{
|
||||
struct cis_buffer *cis;
|
||||
int i;
|
||||
|
||||
cis = (struct cis_buffer *)argp;
|
||||
/*
|
||||
* CISTPL_END is a special case, it has no length field.
|
||||
*/
|
||||
if (id == CISTPL_END) {
|
||||
if (cis->len + 1 > sizeof(cis->buffer))
|
||||
return (ENOSPC);
|
||||
cis->buffer[cis->len++] = id;
|
||||
return (0);
|
||||
}
|
||||
if (cis->len + 2 + len > sizeof(cis->buffer))
|
||||
return (ENOSPC);
|
||||
cis->buffer[cis->len++] = id;
|
||||
cis->buffer[cis->len++] = len;
|
||||
for (i = 0; i < len; i++)
|
||||
cis->buffer[cis->len++] = tupledata[i];
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||
{
|
||||
device_t parent, child;
|
||||
device_t *kids;
|
||||
int cnt, err;
|
||||
struct cardbus_softc *sc;
|
||||
struct tuple_callbacks cb[] = {
|
||||
{CISTPL_GENERIC, "GENERIC", cardbus_build_cis}
|
||||
};
|
||||
|
||||
sc = dev->si_drv1;
|
||||
if (sc->sc_cis_open)
|
||||
return (EBUSY);
|
||||
parent = sc->sc_dev;
|
||||
err = device_get_children(parent, &kids, &cnt);
|
||||
if (err)
|
||||
return err;
|
||||
if (cnt == 0) {
|
||||
free(kids, M_TEMP);
|
||||
sc->sc_cis_open++;
|
||||
sc->sc_cis = NULL;
|
||||
return (0);
|
||||
}
|
||||
child = kids[0];
|
||||
free(kids, M_TEMP);
|
||||
sc->sc_cis = malloc(sizeof(*sc->sc_cis), M_TEMP, M_ZERO | M_WAITOK);
|
||||
err = cardbus_parse_cis(parent, child, cb, sc->sc_cis);
|
||||
if (err) {
|
||||
free(sc->sc_cis, M_TEMP);
|
||||
sc->sc_cis = NULL;
|
||||
return (err);
|
||||
}
|
||||
sc->sc_cis_open++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_close(struct cdev *dev, int fflags, int devtype, struct thread *td)
|
||||
{
|
||||
struct cardbus_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
free(sc->sc_cis, M_TEMP);
|
||||
sc->sc_cis = NULL;
|
||||
sc->sc_cis_open = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
struct thread *td)
|
||||
{
|
||||
return (ENOTTY);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct cardbus_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
/* EOF */
|
||||
if (sc->sc_cis == NULL || uio->uio_offset > sc->sc_cis->len)
|
||||
return (0);
|
||||
return (uiomove(sc->sc_cis->buffer + uio->uio_offset,
|
||||
MIN(uio->uio_resid, sc->sc_cis->len - uio->uio_offset), uio));
|
||||
}
|
@ -46,3 +46,35 @@ struct cardbus_devinfo
|
||||
} funce;
|
||||
uint32_t fepresent; /* bit mask of funce values present */
|
||||
};
|
||||
|
||||
struct cis_buffer
|
||||
{
|
||||
size_t len; /* Actual length of the CIS */
|
||||
uint8_t buffer[2040]; /* small enough to be 2k */
|
||||
};
|
||||
|
||||
struct cardbus_softc
|
||||
{
|
||||
/* XXX need mutex XXX */
|
||||
device_t sc_dev;
|
||||
struct cdev *sc_cisdev;
|
||||
struct cis_buffer *sc_cis;
|
||||
int sc_cis_open;
|
||||
};
|
||||
|
||||
struct tuple_callbacks;
|
||||
|
||||
typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
|
||||
uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info, void *);
|
||||
|
||||
struct tuple_callbacks {
|
||||
int id;
|
||||
char *name;
|
||||
tuple_cb *func;
|
||||
};
|
||||
|
||||
int cardbus_device_create(struct cardbus_softc *);
|
||||
int cardbus_device_destroy(struct cardbus_softc *);
|
||||
int cardbus_parse_cis(device_t cbdev, device_t child,
|
||||
struct tuple_callbacks *callbacks, void *);
|
||||
|
@ -3,7 +3,7 @@
|
||||
.PATH: ${.CURDIR}/../../dev/cardbus
|
||||
|
||||
KMOD= cardbus
|
||||
SRCS= cardbus.c cardbus_cis.c \
|
||||
SRCS= cardbus.c cardbus_cis.c cardbus_device.c \
|
||||
device_if.h bus_if.h card_if.h power_if.h pci_if.h pcib_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
Loading…
x
Reference in New Issue
Block a user