add PIOCSRESOURCE(IOC_GET_RESOURCE_RANGE)

Now /usr/sbin/pccardd read free resource(io,irq) range with
this ioctl.

Original Idea from:	PAO3
This commit is contained in:
MIHIRA Sanpei Yoshiro 2000-09-17 15:37:53 +00:00
parent df6bd679e7
commit 5935ef4c44
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=65991
4 changed files with 95 additions and 5 deletions

View File

@ -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.
*/
@ -136,6 +137,18 @@ struct power {
int vpp;
};
/*
* 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
*/

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}