summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/isa.c
diff options
context:
space:
mode:
authorkato <kato@FreeBSD.org>2000-03-29 03:15:22 +0000
committerkato <kato@FreeBSD.org>2000-03-29 03:15:22 +0000
commit7af5f89a60b2c01199275c6b9d0271c6bf342100 (patch)
tree5dc25460c10069bc1ccdfe095d12f26393bd7444 /sys/i386/isa/isa.c
parentbeae0af3f39d85f6aa06dc4e1d97ef7170c32883 (diff)
downloadFreeBSD-src-7af5f89a60b2c01199275c6b9d0271c6bf342100.zip
FreeBSD-src-7af5f89a60b2c01199275c6b9d0271c6bf342100.tar.gz
Added indirect pio into the bus space stuff for the NEC PC-98. bus.h
includes one of bus_at386.h and bus_pc98.h. Becuase only bus_pc98.h supports indirect pio and bus_at386.h is identical to old bus.h, there is no functional change in PC-AT's kernels. That is, it cannot cause performance loss. Submitted by: nyan Reviewed by: imp bde and luoqi provided useful comments for earlier version.
Diffstat (limited to 'sys/i386/isa/isa.c')
-rw-r--r--sys/i386/isa/isa.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c
index 5e9e69a..e9e8203 100644
--- a/sys/i386/isa/isa.c
+++ b/sys/i386/isa/isa.c
@@ -62,6 +62,7 @@
#include <sys/bus.h>
#include <sys/malloc.h>
#include <machine/bus.h>
+#include <sys/rman.h>
#include <machine/resource.h>
@@ -132,12 +133,113 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
start, end, count, flags);
}
+#ifdef PC98
+/*
+ * Indirection support. The type of bus_space_handle_t is
+ * defined in sys/i386/include/bus_pc98.h.
+ */
+struct resource *
+isa_alloc_resourcev(device_t child, int type, int *rid,
+ bus_addr_t *res, bus_size_t count, u_int flags)
+{
+ struct isa_device* idev = DEVTOISA(child);
+ struct resource_list *rl = &idev->id_resources;
+
+ device_t bus = device_get_parent(child);
+ bus_addr_t ioport;
+ struct resource *re;
+ struct resource **bsre;
+ int i, j, k, linear_cnt, ressz, bsrid;
+
+ ioport = bus_get_resource_start(child, SYS_RES_IOPORT, 0);
+
+ linear_cnt = count;
+ ressz = 1;
+ for (i = 1; i < count; ++i) {
+ if (res[i] > res[i - 1] + 1) {
+ if (i < linear_cnt)
+ linear_cnt = i;
+ ++ressz;
+ }
+ }
+
+ re = isa_alloc_resource(bus, child, type, rid, ioport + res[0],
+ ioport + res[linear_cnt - 1], linear_cnt, flags);
+ if (re == NULL)
+ return NULL;
+
+ bsre = malloc(sizeof (struct resource *) * ressz, M_DEVBUF, M_NOWAIT);
+ if (bsre == NULL) {
+ resource_list_release(rl, bus, child, type, *rid, re);
+ return NULL;
+ }
+ bsre[0] = re;
+
+ for (i = linear_cnt, k = 1; i < count; i = j, k++) {
+ for (j = i + 1; j < count; j++) {
+ if (res[j] > res[j - 1] + 1)
+ break;
+ }
+ bsrid = *rid + k;
+ bsre[k] = isa_alloc_resource(bus, child, type, &bsrid,
+ ioport + res[i], ioport + res[j - 1], j - i, flags);
+ if (bsre[k] == NULL) {
+ for (k--; k >= 0; k--)
+ resource_list_release(rl, bus, child, type,
+ *rid + k, bsre[k]);
+ free(bsre, M_DEVBUF);
+ return NULL;
+ }
+ }
+
+ re->r_bushandle.bsh_res = bsre;
+ re->r_bushandle.bsh_ressz = ressz;
+
+ return re;
+}
+
+int
+isa_load_resourcev(struct resource *re, bus_addr_t *res, bus_size_t count)
+{
+ bus_addr_t *addr;
+ int i;
+
+ addr = malloc(sizeof (bus_addr_t) * count, M_DEVBUF, M_NOWAIT);
+ if (addr == NULL)
+ return 1;
+
+ for (i = 0; i < count; i++)
+ addr[i] = rman_get_start(re) + res[i];
+
+ rman_set_bustag(re, I386_BUS_SPACE_IO_IND);
+ re->r_bushandle.bsh_iat = addr;
+ re->r_bushandle.bsh_iatsz = count;
+
+ return 0;
+}
+#endif /* PC98 */
+
int
isa_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
struct isa_device* idev = DEVTOISA(child);
struct resource_list *rl = &idev->id_resources;
+#ifdef PC98
+ /*
+ * Indirection support. The type of bus_space_handle_t is
+ * defined in sys/i386/include/bus_pc98.h.
+ */
+ int i;
+
+ for (i = 1; i < r->r_bushandle.bsh_ressz; i++)
+ resource_list_release(rl, bus, child, type, rid + i,
+ r->r_bushandle.bsh_res[i]);
+ if (r->r_bushandle.bsh_res != NULL)
+ free(r->r_bushandle.bsh_res, M_DEVBUF);
+ if (r->r_bushandle.bsh_iat != NULL)
+ free(r->r_bushandle.bsh_iat, M_DEVBUF);
+#endif
return resource_list_release(rl, bus, child, type, rid, r);
}
OpenPOWER on IntegriCloud