isa.c revision 294883
1250079Scarl/*-
2250079Scarl * Copyright (c) 1998 Doug Rabson
3289542Scem * All rights reserved.
4250079Scarl *
5250079Scarl * Redistribution and use in source and binary forms, with or without
6250079Scarl * modification, are permitted provided that the following conditions
7250079Scarl * are met:
8250079Scarl * 1. Redistributions of source code must retain the above copyright
9250079Scarl *    notice, this list of conditions and the following disclaimer.
10250079Scarl * 2. Redistributions in binary form must reproduce the above copyright
11250079Scarl *    notice, this list of conditions and the following disclaimer in the
12250079Scarl *    documentation and/or other materials provided with the distribution.
13250079Scarl *
14250079Scarl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15250079Scarl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16250079Scarl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17250079Scarl * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18250079Scarl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19250079Scarl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20250079Scarl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21250079Scarl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22250079Scarl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23250079Scarl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24250079Scarl * SUCH DAMAGE.
25250079Scarl */
26250079Scarl
27250079Scarl#include <sys/cdefs.h>
28250079Scarl__FBSDID("$FreeBSD: head/sys/x86/isa/isa.c 294883 2016-01-27 02:23:54Z jhibbits $");
29250079Scarl
30250079Scarl/*-
31250079Scarl * Modifications for Intel architecture by Garrett A. Wollman.
32250079Scarl * Copyright 1998 Massachusetts Institute of Technology
33250079Scarl *
34250079Scarl * Permission to use, copy, modify, and distribute this software and
35289774Scem * its documentation for any purpose and without fee is hereby
36250079Scarl * granted, provided that both the above copyright notice and this
37250079Scarl * permission notice appear in all copies, that both the above
38250079Scarl * copyright notice and this permission notice appear in all
39250079Scarl * supporting documentation, and that the name of M.I.T. not be used
40289774Scem * in advertising or publicity pertaining to distribution of the
41289207Scem * software without specific, written prior permission.  M.I.T. makes
42250079Scarl * no representations about the suitability of this software for any
43250079Scarl * purpose.  It is provided "as is" without express or implied
44250079Scarl * warranty.
45250079Scarl *
46250079Scarl * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
47250079Scarl * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
48250079Scarl * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
49250079Scarl * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
50250079Scarl * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51250079Scarl * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
52250079Scarl * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
53250079Scarl * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
54250079Scarl * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
55250079Scarl * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
56250079Scarl * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57250079Scarl * SUCH DAMAGE.
58250079Scarl */
59250079Scarl
60250079Scarl#include <sys/param.h>
61250079Scarl#include <sys/bus.h>
62250079Scarl#include <sys/kernel.h>
63250079Scarl#include <sys/malloc.h>
64250079Scarl#include <sys/module.h>
65289648Scem#include <machine/bus.h>
66250079Scarl#include <sys/rman.h>
67289539Scem#ifdef PC98
68289648Scem#include <sys/systm.h>
69291032Scem#endif
70250079Scarl
71250079Scarl#include <machine/resource.h>
72250079Scarl
73250079Scarl#include <isa/isavar.h>
74250079Scarl#include <isa/isa_common.h>
75289648Scem
76250079Scarlvoid
77250079Scarlisa_init(device_t dev)
78289610Scem{
79289610Scem}
80289610Scem
81289610Scem/*
82289610Scem * This implementation simply passes the request up to the parent
83289610Scem * bus, which in our case is the special i386 nexus, substituting any
84289610Scem * configured values if the caller defaulted.  We can get away with
85289610Scem * this because there is no special mapping for ISA resources on an Intel
86289610Scem * platform.  When porting this code to another architecture, it may be
87289610Scem * necessary to interpose a mapping layer here.
88289610Scem */
89289610Scemstruct resource *
90289539Scemisa_alloc_resource(device_t bus, device_t child, int type, int *rid,
91289539Scem		   rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
92289539Scem{
93289539Scem	/*
94289539Scem	 * Consider adding a resource definition.
95289539Scem	 */
96289539Scem	int passthrough = (device_get_parent(child) != bus);
97289539Scem	int isdefault = (start == 0UL && end == ~0UL);
98255274Scarl	struct isa_device* idev = DEVTOISA(child);
99255274Scarl	struct resource_list *rl = &idev->id_resources;
100255274Scarl	struct resource_list_entry *rle;
101255274Scarl
102250079Scarl	if (!passthrough && !isdefault) {
103250079Scarl		rle = resource_list_find(rl, type, *rid);
104255274Scarl		if (!rle) {
105250079Scarl			if (*rid < 0)
106289397Scem				return 0;
107250079Scarl			switch (type) {
108250079Scarl			case SYS_RES_IRQ:
109250079Scarl				if (*rid >= ISA_NIRQ)
110250079Scarl					return 0;
111250079Scarl				break;
112250079Scarl			case SYS_RES_DRQ:
113250079Scarl				if (*rid >= ISA_NDRQ)
114250079Scarl					return 0;
115290679Scem				break;
116290679Scem			case SYS_RES_MEMORY:
117291280Scem				if (*rid >= ISA_NMEM)
118289543Scem					return 0;
119289543Scem				break;
120289543Scem			case SYS_RES_IOPORT:
121289543Scem				if (*rid >= ISA_NPORT)
122289543Scem					return 0;
123250079Scarl				break;
124250079Scarl			default:
125250079Scarl				return 0;
126250079Scarl			}
127250079Scarl			resource_list_add(rl, type, *rid, start, end, count);
128250079Scarl		}
129250079Scarl	}
130250079Scarl
131289546Scem	return resource_list_alloc(rl, bus, child, type, rid,
132250079Scarl				   start, end, count, flags);
133289546Scem}
134250079Scarl
135250079Scarl#ifdef PC98
136289542Scem/*
137289542Scem * Indirection support.  The type of bus_space_handle_t is
138289542Scem * defined in sys/i386/include/bus_pc98.h.
139289542Scem */
140289542Scemstruct resource *
141289542Scemisa_alloc_resourcev(device_t child, int type, int *rid,
142289542Scem		    bus_addr_t *res, bus_size_t count, u_int flags)
143289542Scem{
144289542Scem	struct isa_device* idev = DEVTOISA(child);
145289542Scem	struct resource_list *rl = &idev->id_resources;
146289542Scem
147289542Scem	device_t	bus = device_get_parent(child);
148289542Scem	bus_addr_t	start;
149289542Scem	bus_space_handle_t bh;
150289546Scem	struct resource *re;
151289546Scem	struct resource	**bsre;
152289546Scem	int		i, j, k, linear_cnt, ressz, bsrid;
153289546Scem
154289546Scem	start = bus_get_resource_start(child, type, *rid);
155289546Scem
156289546Scem	linear_cnt = count;
157289546Scem	ressz = 1;
158289546Scem	for (i = 1; i < count; ++i) {
159289546Scem		if (res[i] != res[i - 1] + 1) {
160289546Scem			if (i < linear_cnt)
161289546Scem				linear_cnt = i;
162289542Scem			++ressz;
163289542Scem		}
164289542Scem	}
165289542Scem
166289542Scem	re = isa_alloc_resource(bus, child, type, rid,
167289542Scem				start + res[0], start + res[linear_cnt - 1],
168289542Scem				linear_cnt, flags);
169289542Scem	if (re == NULL)
170289542Scem		return NULL;
171289542Scem
172250079Scarl	bsre = malloc(sizeof (struct resource *) * ressz, M_DEVBUF, M_NOWAIT);
173250079Scarl	if (bsre == NULL) {
174250079Scarl		resource_list_release(rl, bus, child, type, *rid, re);
175289774Scem		return NULL;
176250079Scarl	}
177250079Scarl	bsre[0] = re;
178250079Scarl
179250079Scarl	for (i = linear_cnt, k = 1; i < count; i = j, k++) {
180250079Scarl		for (j = i + 1; j < count; j++) {
181250079Scarl			if (res[j] != res[j - 1] + 1)
182250079Scarl				break;
183250079Scarl		}
184289546Scem		bsrid = *rid + k;
185289546Scem		bsre[k] = isa_alloc_resource(bus, child, type, &bsrid,
186289546Scem			start + res[i], start + res[j - 1], j - i, flags);
187290683Scem		if (bsre[k] == NULL) {
188290683Scem			for (k--; k >= 0; k--)
189289546Scem				resource_list_release(rl, bus, child, type,
190289546Scem						      *rid + k, bsre[k]);
191250079Scarl			free(bsre, M_DEVBUF);
192289610Scem			return NULL;
193289610Scem		}
194289610Scem	}
195289539Scem
196289542Scem	bh = rman_get_bushandle(re);
197289542Scem	bh->bsh_res = bsre;
198289542Scem	bh->bsh_ressz = ressz;
199289543Scem
200289542Scem	return re;
201289542Scem}
202289539Scem
203289539Scemint
204289539Scemisa_load_resourcev(struct resource *re, bus_addr_t *res, bus_size_t count)
205289539Scem{
206289539Scem
207289542Scem	return bus_space_map_load(rman_get_bustag(re), rman_get_bushandle(re),
208289546Scem				  count, res, 0);
209289546Scem}
210289546Scem#endif	/* PC98 */
211289546Scem
212289542Scemint
213289542Scemisa_release_resource(device_t bus, device_t child, int type, int rid,
214290686Scem		     struct resource *r)
215290686Scem{
216289542Scem	struct isa_device* idev = DEVTOISA(child);
217289542Scem	struct resource_list *rl = &idev->id_resources;
218289542Scem#ifdef PC98
219289546Scem	/*
220289542Scem	 * Indirection support.  The type of bus_space_handle_t is
221289542Scem	 * defined in sys/i386/include/bus_pc98.h.
222289542Scem	 */
223289542Scem	int	i;
224289542Scem	bus_space_handle_t bh;
225289542Scem
226289542Scem	if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
227250079Scarl		bh = rman_get_bushandle(r);
228250079Scarl		if (bh != NULL) {
229289234Scem			for (i = 1; i < bh->bsh_ressz; i++)
230289234Scem				resource_list_release(rl, bus, child, type,
231289234Scem						      rid + i, bh->bsh_res[i]);
232289234Scem			if (bh->bsh_res != NULL)
233289234Scem				free(bh->bsh_res, M_DEVBUF);
234289234Scem		}
235289234Scem	}
236289234Scem#endif
237289234Scem	return resource_list_release(rl, bus, child, type, rid, r);
238289234Scem}
239289234Scem
240289234Scem/*
241289234Scem * On this platform, isa can also attach to the legacy bus.
242289234Scem */
243289234ScemDRIVER_MODULE(isa, legacy, isa_driver, isa_devclass, 0, 0);
244289234Scem
245289234Scem/*
246289234Scem * Attach the ISA bus to the xenpv bus in order to get syscons.
247289234Scem */
248289234ScemDRIVER_MODULE(isa, xenpv, isa_driver, isa_devclass, 0, 0);
249255279Scarl