summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsanpei <sanpei@FreeBSD.org>2000-09-17 15:37:53 +0000
committersanpei <sanpei@FreeBSD.org>2000-09-17 15:37:53 +0000
commit62e0e10410c07cfb086acfffd093bbecd52cff35 (patch)
tree62261bcb4571e37f2fe5ce92ad2b845b3f212b9f
parentcb16f04f5df020842df077b1d1cbfe2b7352cf09 (diff)
downloadFreeBSD-src-62e0e10410c07cfb086acfffd093bbecd52cff35.zip
FreeBSD-src-62e0e10410c07cfb086acfffd093bbecd52cff35.tar.gz
add PIOCSRESOURCE(IOC_GET_RESOURCE_RANGE)
Now /usr/sbin/pccardd read free resource(io,irq) range with this ioctl. Original Idea from: PAO3
-rw-r--r--sys/pccard/cardinfo.h13
-rw-r--r--sys/pccard/pccard.c45
-rw-r--r--sys/pccard/pcic.h1
-rw-r--r--usr.sbin/pccard/pccardd/cardd.c41
4 files changed, 95 insertions, 5 deletions
diff --git a/sys/pccard/cardinfo.h b/sys/pccard/cardinfo.h
index f71cd6f..3f8ffce 100644
--- a/sys/pccard/cardinfo.h
+++ b/sys/pccard/cardinfo.h
@@ -49,6 +49,7 @@
#define PIOCSPOW _IOW('P', 9, struct power) /* Set power structure */
#define PIOCSVIR _IOW('P', 10, int) /* Virtual insert/remove */
#define PIOCSBEEP _IOW('P', 11, int) /* Select Beep */
+#define PIOCSRESOURCE _IOWR('P', 12, struct pccard_resource) /* get resource info */
/*
* Debug codes.
*/
@@ -137,6 +138,18 @@ struct power {
};
/*
+ * Th PC-Card resource IOC_GET_RESOURCE_RANGE
+ */
+struct pccard_resource {
+ int type;
+ u_long size;
+ u_long min;
+ u_long max;
+ u_long resource_addr;
+};
+
+
+/*
* Other system limits
*/
#define MAXSLOT 16
diff --git a/sys/pccard/pccard.c b/sys/pccard/pccard.c
index 97c2294..a59133a 100644
--- a/sys/pccard/pccard.c
+++ b/sys/pccard/pccard.c
@@ -460,7 +460,12 @@ crdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
struct slot *slt = pccard_slots[minor(dev)];
struct mem_desc *mp;
struct io_desc *ip;
+ struct pccard_resource *pr;
+ struct resource *r;
+ device_t pcicdev;
int s, err;
+ int rid = 1;
+ int i;
int pwval;
if (slt == 0 && cmd != PIOCRWMEM)
@@ -613,6 +618,46 @@ crdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
return EINVAL;
}
break;
+ case PIOCSRESOURCE:
+ pr = (struct pccard_resource *)data;
+ pr->resource_addr = ~0ul;
+ /*
+ * pccard_devclass does not have soft_c
+ * so we use pcic_devclass
+ */
+ pcicdev = devclass_get_device(pcic_devclass, 0);
+ switch(pr->type) {
+ default:
+ return EINVAL;
+ case SYS_RES_IOPORT:
+ case SYS_RES_MEMORY:
+ for (i = pr->min; i + pr->size <= pr->max; i++) {
+ err = bus_set_resource(pcicdev, pr->type, rid, i, pr->size);
+ if (!err) {
+ r = bus_alloc_resource(pcicdev, pr->type, &rid, 0ul, ~0ul, pr->size, 0);
+ if (r) {
+ pr->resource_addr = (u_long)rman_get_start(r);
+ bus_release_resource(pcicdev, pr->type, rid, r);
+ break;
+ }
+ }
+ }
+ break;
+ case SYS_RES_IRQ:
+ for (i = pr->min; i <= pr->max; i++) {
+ err = bus_set_resource(pcicdev, SYS_RES_IRQ, rid, i, 1);
+ if (!err) {
+ r = bus_alloc_resource(pcicdev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, 0);
+ if (r) {
+ pr->resource_addr = (u_long)rman_get_start(r);
+ bus_release_resource(pcicdev, SYS_RES_IRQ, rid, r);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ break;
}
return(0);
}
diff --git a/sys/pccard/pcic.h b/sys/pccard/pcic.h
index b8b6d23..c8a2457 100644
--- a/sys/pccard/pcic.h
+++ b/sys/pccard/pcic.h
@@ -41,3 +41,4 @@
#define PCIC_RF_MDF_WS1 (0x08 << 16)
#define PCIC_RF_MDF_ATTR (0x10 << 16)
#define PCIC_RF_MDF_WP (0x20 << 16)
+extern devclass_t pcic_devclass;
diff --git a/usr.sbin/pccard/pccardd/cardd.c b/usr.sbin/pccard/pccardd/cardd.c
index e68182a..3a7153d 100644
--- a/usr.sbin/pccard/pccardd/cardd.c
+++ b/usr.sbin/pccard/pccardd/cardd.c
@@ -37,6 +37,7 @@ static const char rcsid[] =
#include <fcntl.h>
#include <ctype.h>
#include <regex.h>
+#include <machine/resource.h>
#include <sys/ioctl.h>
#include "cardd.h"
@@ -486,13 +487,29 @@ assign_driver(struct card *cp)
}
/* Allocate a free IRQ if none has been specified */
if (conf->irq == 0) {
- int i;
- for (i = 1; i < 16; i++)
- if (pool_irq[i]) {
+ struct pccard_resource resource;
+ char name[128];
+ int i, fd;
+
+ sprintf(name, CARD_DEVICE, 0); /* XXX sanpei */
+ fd = open(name, O_RDWR);
+
+ resource.type = SYS_RES_IRQ;
+ resource.size = 1;
+ for (i = 1; i < 16; i++) {
+ resource.min = i;
+ resource.max = i;
+ if (ioctl(fd, PIOCSRESOURCE, &resource) < 0) {
+ perror("ioctl (PIOCSRESOURCE)");
+ exit(1);
+ }
+ if (pool_irq[i] && resource.resource_addr == i) {
conf->irq = i;
pool_irq[i] = 0;
break;
}
+ }
+ close(fd);
if (conf->irq == 0) {
logmsg("Failed to allocate IRQ for %s\n", cp->manuf);
return (NULL);
@@ -513,19 +530,33 @@ assign_card_index(struct cis * cis)
{
struct cis_config *cp;
struct cis_ioblk *cio;
- int i;
+ struct pccard_resource resource;
+ char name[128];
+ int i, fd;
+
+ sprintf(name, CARD_DEVICE, 0); /* XXX sanpei */
+ fd = open(name, O_RDWR);
+ resource.type = SYS_RES_IOPORT;
for (cp = cis->conf; cp; cp = cp->next) {
if (!cp->iospace || !cp->io)
continue;
for (cio = cp->io; cio; cio = cio->next) {
+ resource.size = cio->size;
for (i = cio->addr; i < cio->addr + cio->size - 1; i++)
- if (!bit_test(io_avail, i))
+ resource.min = i;
+ resource.max = resource.min + cio->size - 1;
+ if (ioctl(fd, PIOCSRESOURCE, &resource) < 0) {
+ perror("ioctl (PIOCSRESOURCE)");
+ exit(1);
+ }
+ if (!bit_test(io_avail, i) || resource.resource_addr != i)
goto next;
}
return cp; /* found */
next:
}
+ close(fd);
return cis->def_config;
}
OpenPOWER on IntegriCloud