eisaconf.c revision 20450
1243791Sdim/*
2243791Sdim * EISA bus probe and attach routines
3243791Sdim *
4243791Sdim * Copyright (c) 1995, 1996 Justin T. Gibbs.
5243791Sdim * All rights reserved.
6243791Sdim *
7243791Sdim * Redistribution and use in source and binary forms, with or without
8243791Sdim * modification, are permitted provided that the following conditions
9243791Sdim * are met:
10243791Sdim * 1. Redistributions of source code must retain the above copyright
11243791Sdim *    notice immediately at the beginning of the file, without modification,
12243791Sdim *    this list of conditions, and the following disclaimer.
13243791Sdim * 2. Redistributions in binary form must reproduce the above copyright
14243791Sdim *    notice, this list of conditions and the following disclaimer in the
15249423Sdim *    documentation and/or other materials provided with the distribution.
16249423Sdim * 3. The name of the author may not be used to endorse or promote products
17243791Sdim *    derived from this software without specific prior written permission.
18249423Sdim *
19243791Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20249423Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21243791Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22243791Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23243791Sdim * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24243791Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25243791Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26243791Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27243791Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28243791Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29243791Sdim * SUCH DAMAGE.
30243791Sdim *
31243791Sdim *	$Id: eisaconf.c,v 1.23 1996/09/08 10:43:42 phk Exp $
32243791Sdim */
33243791Sdim#include <sys/param.h>
34243791Sdim#include <sys/systm.h>
35243791Sdim#include <sys/kernel.h>
36243791Sdim#include <sys/sysctl.h>
37243791Sdim#include <sys/conf.h>
38243791Sdim#include <sys/malloc.h>
39243791Sdim
40243791Sdim#include <i386/eisa/eisaconf.h>
41243791Sdim
42243791Sdim#include <i386/isa/icu.h>	 /* Hmmm.  Interrupt stuff? */
43243791Sdim
44243791Sdimstruct eisa_device_node{
45243791Sdim	struct	eisa_device dev;
46243791Sdim	struct	eisa_device_node *next;
47243791Sdim};
48243791Sdim
49243791Sdim/*
50243791Sdim * This should probably be a list of "struct device" once it exists.
51243791Sdim * A struct device will incorperate ioconf and driver entry point data
52243791Sdim * regardless of how its attached to the system (via unions) as well
53243791Sdim * as more generic information that all device types should support (unit
54243791Sdim * number, if its installed, etc).
55243791Sdim */
56243791Sdimstatic struct eisa_device_node *eisa_dev_list;
57243791Sdimstatic struct eisa_device_node **eisa_dev_list_tail = &eisa_dev_list;
58243791Sdimstatic u_long eisa_unit;
59243791Sdim
60243791Sdimstatic struct eisa_driver mainboard_drv = {
61243791Sdim				     "eisa",
62243791Sdim				     NULL,
63243791Sdim				     NULL,
64243791Sdim				     NULL,
65243791Sdim				     &eisa_unit
66243791Sdim				   };
67243791Sdim
68243791Sdim/*
69243791Sdim * Add the mainboard_drv to the eisa driver linkerset so that it is
70243791Sdim * defined even if no EISA drivers are linked into the kernel.
71243791Sdim */
72243791SdimDATA_SET (eisadriver_set, mainboard_drv);
73243791Sdim
74243791Sdim/*
75243791Sdim * Local function declarations and static variables
76243791Sdim */
77243791Sdimvoid eisa_reg_print __P((struct eisa_device *e_dev, char *string,
78243791Sdim			 char *separator));
79243791Sdimstatic int eisa_add_resvaddr __P((struct eisa_device *e_dev,
80243791Sdim				  struct resvlist *head, u_long	base,
81243791Sdim				  u_long size, int flags));
82243791Sdimstatic int eisa_reg_resvaddr __P((struct eisa_device *e_dev,
83243791Sdim				  struct resvlist *head, resvaddr_t *resvaddr,
84243791Sdim				  int *reg_count));
85243791Sdim
86243791Sdim/*
87243791Sdim * Keep some state about what we've printed so far
88243791Sdim * to make probe output pretty.
89243791Sdim */
90243791Sdimstatic struct {
91243791Sdim	int	in_registration;/* reg_start has been called */
92243791Sdim	int	num_interrupts;
93243791Sdim	int	num_ioaddrs;
94243791Sdim	int	num_maddrs;
95243791Sdim	int	column;		/* How much we have output so far. */
96243791Sdim#define	MAX_COL 80
97243791Sdim} reg_state;
98243791Sdim
99243791Sdim/* XXX Global variable, so UserConfig can change it. */
100243791Sdimint num_eisa_slots = EISA_SLOTS;
101243791Sdim
102243791Sdim/*
103243791Sdim** probe for EISA devices
104243791Sdim*/
105243791Sdimvoid
106243791Sdimeisa_configure()
107243791Sdim{
108243791Sdim	int i,slot;
109243791Sdim	char *id_string;
110243791Sdim	struct eisa_device_node *dev_node;
111243791Sdim	struct eisa_driver **e_drvp;
112243791Sdim	struct eisa_driver *e_drv;
113243791Sdim	struct eisa_device *e_dev;
114243791Sdim	int eisaBase = 0xc80;
115243791Sdim	eisa_id_t eisa_id;
116243791Sdim
117243791Sdim	e_drvp = (struct eisa_driver**)eisadriver_set.ls_items;
118243791Sdim
119243791Sdim	for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) {
120243791Sdim		int id_size = sizeof(eisa_id);
121243791Sdim		eisa_id = 0;
122243791Sdim    		for( i = 0; i < id_size; i++ ) {
123243791Sdim			outb(eisaBase,0x80 + i); /*Some cards require priming*/
124243791Sdim			eisa_id |= inb(eisaBase+i) << ((id_size-i-1)*CHAR_BIT);
125243791Sdim		}
126243791Sdim		if (eisa_id & 0x80000000)
127243791Sdim			continue;  /* no EISA card in slot */
128243791Sdim
129243791Sdim		/* Prepare an eisa_device_node for this slot */
130243791Sdim		dev_node = (struct eisa_device_node *)malloc(sizeof(*dev_node),
131243791Sdim							    M_DEVBUF, M_NOWAIT);
132243791Sdim		if (!dev_node) {
133243791Sdim			printf("eisa0: cannot malloc eisa_device_node");
134243791Sdim			break; /* Try to attach what we have already */
135243791Sdim		}
136243791Sdim		bzero(dev_node, sizeof(*dev_node));
137243791Sdim		e_dev = &(dev_node->dev);
138243791Sdim
139243791Sdim		e_dev->id = eisa_id;
140243791Sdim		/*
141243791Sdim		 * Add an EISA ID based descriptive name incase we don't
142243791Sdim		 * have a driver for it.  We do this now instead of after all
143243791Sdim		 * probes because in the future, the eisa module will only
144243791Sdim		 * be responsible for creating the list of devices in the system
145243791Sdim		 * for the configuration manager to use.
146243791Sdim		 */
147243791Sdim		e_dev->full_name = (char *)malloc(8*sizeof(char),
148243791Sdim						  M_DEVBUF, M_NOWAIT);
149243791Sdim		if (!e_dev->full_name) {
150243791Sdim			panic("Eisa probe unable to malloc");
151243791Sdim		}
152243791Sdim		sprintf(e_dev->full_name, "%c%c%c%x%x",
153243791Sdim			EISA_MFCTR_CHAR0(e_dev->id),
154243791Sdim			EISA_MFCTR_CHAR1(e_dev->id),
155243791Sdim			EISA_MFCTR_CHAR2(e_dev->id),
156243791Sdim			EISA_PRODUCT_ID(e_dev->id),
157243791Sdim			EISA_REVISION_ID(e_dev->id));
158243791Sdim
159243791Sdim		e_dev->ioconf.slot = slot;
160243791Sdim
161243791Sdim		/* Initialize our lists of reserved addresses */
162243791Sdim		LIST_INIT(&(e_dev->ioconf.ioaddrs));
163243791Sdim		LIST_INIT(&(e_dev->ioconf.maddrs));
164243791Sdim
165243791Sdim		*eisa_dev_list_tail = dev_node;
166243791Sdim		eisa_dev_list_tail = &dev_node->next;
167263508Sdim	}
168243791Sdim
169243791Sdim	dev_node = eisa_dev_list;
170243791Sdim
171243791Sdim	/*
172243791Sdim	 * "Attach" the system board
173243791Sdim	 */
174243791Sdim
175243791Sdim	/* The first will be the motherboard in a true EISA system */
176243791Sdim	if (dev_node && (dev_node->dev.ioconf.slot == 0)) {
177243791Sdim		e_dev = &dev_node->dev;
178243791Sdim		e_dev->driver = &mainboard_drv;
179243791Sdim		e_dev->unit = (*e_dev->driver->unit)++;
180243791Sdim		id_string = e_dev->full_name;
181243791Sdim		e_dev->full_name = (char *)malloc(strlen(e_dev->full_name)
182243791Sdim						  + sizeof(" (System Board)")
183243791Sdim						  + 1, M_DEVBUF, M_NOWAIT);
184243791Sdim		if (!e_dev->full_name) {
185243791Sdim			panic("Eisa probe unable to malloc");
186243791Sdim		}
187243791Sdim		sprintf(e_dev->full_name, "%s (System Board)", id_string);
188243791Sdim		free(id_string, M_DEVBUF);
189243791Sdim
190243791Sdim		printf("%s%ld: <%s>\n",
191243791Sdim		       e_dev->driver->name,
192243791Sdim		       e_dev->unit,
193243791Sdim		       e_dev->full_name);
194243791Sdim
195243791Sdim		/* Should set the iosize, but I don't have a spec handy */
196243791Sdim		printf("Probing for devices on the EISA bus\n");
197243791Sdim		dev_node = dev_node->next;
198243791Sdim	}
199243791Sdim
200243791Sdim	if (!eisa_dev_list) {
201243791Sdim		/*
202243791Sdim		 * No devices.
203243791Sdim		 */
204243791Sdim		return;
205243791Sdim    	}
206243791Sdim	/*
207243791Sdim	 * See what devices we recognize.
208243791Sdim	 */
209243791Sdim	while((e_drv = *e_drvp++)) {
210243791Sdim		if (e_drv->probe)
211243791Sdim			(*e_drv->probe)();
212243791Sdim	}
213243791Sdim
214243791Sdim	/*
215243791Sdim	 * Attach the devices we found in slot order
216243791Sdim	 */
217243791Sdim	for (; dev_node; dev_node=dev_node->next) {
218243791Sdim		e_dev = &dev_node->dev;
219243791Sdim		e_drv = e_dev->driver;
220243791Sdim
221243791Sdim		if (e_drv) {
222243791Sdim			/*
223243791Sdim			 * Determine the proper unit number for this device.
224243791Sdim			 * Here we should look in the device table generated
225243791Sdim			 * by config to see if this type of device is enabled
226243791Sdim			 * either generically or for this particular address
227243791Sdim			 * as well as determine if a reserved unit number
228243791Sdim			 * should be used.  We should also ensure that the
229243791Sdim			 * "next availible unit number" skips over "wired" unit
230243791Sdim			 * numbers. This will be done after config is fixed or
231243791Sdim			 * some other configuration method is chosen.
232243791Sdim			 */
233243791Sdim			e_dev->unit = (*e_drv->unit)++;
234243791Sdim			if ((*e_drv->attach)(e_dev) < 0) {
235243791Sdim				/* Ensure registration has ended */
236243791Sdim				reg_state.in_registration = 0;
237243791Sdim				printf("\n%s0:%d <%s> attach failed\n",
238243791Sdim					mainboard_drv.name,
239243791Sdim					e_dev->ioconf.slot,
240243791Sdim					e_dev->full_name);
241243791Sdim				continue;
242243791Sdim			}
243243791Sdim			/* Ensure registration has ended */
244243791Sdim			reg_state.in_registration = 0;
245243791Sdim		}
246243791Sdim		else {
247243791Sdim			/* Announce unattached device */
248243791Sdim			printf("%s0:%d <%s=0x%x> unknown device\n",
249243791Sdim				mainboard_drv.name,
250243791Sdim				e_dev->ioconf.slot,
251243791Sdim				e_dev->full_name,
252243791Sdim				e_dev->id);
253243791Sdim		}
254243791Sdim	}
255243791Sdim}
256243791Sdim
257243791Sdimstruct eisa_device *
258243791Sdimeisa_match_dev(e_dev, match_func)
259243791Sdim	struct eisa_device *e_dev;
260243791Sdim	char* (*match_func)(eisa_id_t);
261243791Sdim{
262243791Sdim	struct eisa_device_node *e_node = eisa_dev_list;
263243791Sdim
264243791Sdim	if (e_dev) {
265243791Sdim		/* Start our search from the last successful match */
266243791Sdim		e_node = ((struct eisa_device_node *)e_dev)->next;
267243791Sdim	}
268243791Sdim
269243791Sdim	for(; e_node; e_node = e_node->next) {
270243791Sdim		char *result;
271243791Sdim		if (e_node->dev.driver) {
272243791Sdim			/* Already claimed */
273243791Sdim			continue;
274243791Sdim		}
275243791Sdim		result = (*match_func)(e_node->dev.id);
276243791Sdim		if (result) {
277243791Sdim			free(e_node->dev.full_name, M_DEVBUF);
278243791Sdim			e_node->dev.full_name = result;
279243791Sdim			return (&(e_node->dev));
280243791Sdim		}
281243791Sdim	}
282243791Sdim	return NULL;
283243791Sdim}
284243791Sdim
285243791Sdim/* Interrupt and I/O space registration facitlities */
286243791Sdimvoid
287243791Sdimeisa_reg_start(e_dev)
288243791Sdim	struct eisa_device *e_dev;
289243791Sdim{
290243791Sdim	/*
291243791Sdim	 * Announce the device.
292243791Sdim	 */
293243791Sdim	char *string;
294243791Sdim
295243791Sdim	reg_state.in_registration = 1;
296243791Sdim	reg_state.num_interrupts = 0;
297243791Sdim	reg_state.num_ioaddrs = 0;
298243791Sdim	reg_state.num_maddrs = 0;
299243791Sdim	reg_state.column = 0;
300243791Sdim
301243791Sdim	string = malloc(strlen(e_dev->full_name) + sizeof(" <>") + /*NULL*/1,
302243791Sdim			M_TEMP, M_NOWAIT);
303243791Sdim	if(!string) {
304243791Sdim		printf("eisa0: cannot malloc device description string\n");
305243791Sdim		return;
306243791Sdim	}
307243791Sdim	sprintf(string, " <%s>", e_dev->full_name);
308243791Sdim	eisa_reg_print(e_dev, string, /*separator=*/NULL);
309243791Sdim	free(string, M_TEMP);
310243791Sdim}
311243791Sdim
312243791Sdim/*
313243791Sdim * Output registration information mindfull of screen wrap.
314243791Sdim * Output an optional character separator before the string
315243791Sdim * if the line does not wrap.
316243791Sdim */
317243791Sdimvoid
318243791Sdimeisa_reg_print(e_dev, string, separator)
319243791Sdim	struct eisa_device *e_dev;
320243791Sdim	char *string;
321243791Sdim	char *separator;
322243791Sdim{
323243791Sdim	int len = strlen(string);
324243791Sdim
325243791Sdim	if(separator)
326243791Sdim		len++;
327243791Sdim
328243791Sdim	if(reg_state.column + len > MAX_COL) {
329243791Sdim		printf("\n");
330243791Sdim		reg_state.column = 0;
331243791Sdim	}
332243791Sdim	else if(separator) {
333243791Sdim		printf("%c", *separator);
334243791Sdim		reg_state.column++;
335243791Sdim	}
336243791Sdim
337243791Sdim	if(reg_state.column == 0)
338243791Sdim		reg_state.column += printf("%s%ld:%s",
339243791Sdim					   e_dev->driver->name,
340243791Sdim					   e_dev->unit,
341243791Sdim					   string);
342243791Sdim	else
343243791Sdim		reg_state.column += printf("%s", string);
344243791Sdim}
345243791Sdim
346243791Sdim/* Interrupt and I/O space registration facitlities */
347243791Sdimvoid
348243791Sdimeisa_reg_end(e_dev)
349243791Sdim	struct eisa_device *e_dev;
350243791Sdim{
351243791Sdim	if( reg_state.in_registration )
352243791Sdim	{
353243791Sdim		char string[25];
354243791Sdim
355243791Sdim		sprintf(string, " on %s0 slot %d",
356243791Sdim			mainboard_drv.name,
357243791Sdim			e_dev->ioconf.slot);
358243791Sdim		eisa_reg_print(e_dev, string, NULL);
359243791Sdim		printf("\n");
360243791Sdim		reg_state.in_registration = 0;
361243791Sdim	}
362243791Sdim	else
363263508Sdim		printf("eisa_reg_end called outside of a "
364243791Sdim		       "registration session\n");
365243791Sdim}
366243791Sdim
367243791Sdimint
368243791Sdimeisa_add_intr(e_dev, irq)
369243791Sdim	struct eisa_device *e_dev;
370243791Sdim	int irq;
371243791Sdim{
372243791Sdim	e_dev->ioconf.irq |= 1ul << irq;
373243791Sdim	return 0;
374243791Sdim}
375243791Sdim
376243791Sdimint
377243791Sdimeisa_reg_intr(e_dev, irq, func, arg, maskptr, shared)
378243791Sdim	struct eisa_device *e_dev;
379243791Sdim	int   irq;
380243791Sdim	void  (*func)(void *);
381243791Sdim	void  *arg;
382243791Sdim	u_int *maskptr;
383243791Sdim	int   shared;
384243791Sdim{
385243791Sdim	int result;
386243791Sdim	int s;
387243791Sdim	char string[25];
388243791Sdim	char separator = ',';
389243791Sdim
390243791Sdim#if NOT_YET
391243791Sdim	/*
392243791Sdim	 * Punt on conflict detection for the moment.
393243791Sdim	 * I want to develop a generic routine to do
394243791Sdim	 * this for all device types.
395243791Sdim	 */
396243791Sdim	int checkthese = CC_IRQ;
397243791Sdim	if (haveseen_dev(dev, checkthese))
398243791Sdim        	return 1;
399243791Sdim#endif
400243791Sdim	if (reg_state.in_registration) {
401243791Sdim		s = splhigh();
402243791Sdim		/*
403243791Sdim		 * This should really go to a routine that can optionally
404243791Sdim		 * handle shared interrupts.
405243791Sdim		 */
406243791Sdim		result = register_intr(irq,		   /* isa irq	   */
407243791Sdim				       0,		   /* deviced??    */
408243791Sdim				       0,		   /* flags?       */
409243791Sdim				       (inthand2_t*) func, /* handler      */
410243791Sdim				       maskptr,		   /* mask pointer */
411243791Sdim				       (int)arg);	   /* handler arg  */
412243791Sdim
413243791Sdim		if (result) {
414243791Sdim			printf ("\neisa_reg_int: result=%d\n", result);
415243791Sdim			splx(s);
416243791Sdim			return (result);
417243791Sdim		};
418243791Sdim		update_intr_masks();
419243791Sdim		splx(s);
420243791Sdim	}
421243791Sdim	else
422243791Sdim		return EPERM;
423243791Sdim
424243791Sdim	e_dev->ioconf.irq |= 1ul << irq;
425243791Sdim	sprintf(string, " irq %d", irq);
426243791Sdim	eisa_reg_print(e_dev, string, reg_state.num_interrupts ?
427243791Sdim				      &separator : NULL);
428243791Sdim	reg_state.num_interrupts++;
429243791Sdim	return (0);
430243791Sdim}
431243791Sdim
432243791Sdimint
433243791Sdimeisa_release_intr(e_dev, irq, func)
434243791Sdim	struct eisa_device *e_dev;
435243791Sdim	int   irq;
436243791Sdim	void  (*func)(void *);
437243791Sdim{
438243791Sdim	int result;
439243791Sdim	int s;
440243791Sdim
441243791Sdim	if (!(e_dev->ioconf.irq & (1ul << irq))) {
442243791Sdim		printf("%s%ld: Attempted to release an interrupt (%d) "
443243791Sdim		       "it doesn't own\n", e_dev->driver->name,
444243791Sdim			e_dev->unit, irq);
445243791Sdim		return (-1);
446243791Sdim	}
447243791Sdim
448243791Sdim	s = splhigh();
449243791Sdim	INTRDIS ((1ul<<irq));
450243791Sdim
451243791Sdim	result = unregister_intr (irq, (inthand2_t*)func);
452243791Sdim
453243791Sdim	if (result)
454243791Sdim		printf ("eisa_release_intr: result=%d\n", result);
455243791Sdim
456243791Sdim	update_intr_masks();
457243791Sdim
458243791Sdim	splx(s);
459243791Sdim	return (result);
460243791Sdim}
461243791Sdim
462243791Sdimint
463243791Sdimeisa_enable_intr(e_dev, irq)
464243791Sdim	struct eisa_device *e_dev;
465243791Sdim	int irq;
466243791Sdim{
467243791Sdim	int s;
468243791Sdim
469243791Sdim	if (!(e_dev->ioconf.irq & (1ul << irq))) {
470243791Sdim		printf("%s%ld: Attempted to enable an interrupt (%d) "
471243791Sdim		       "it doesn't own\n", e_dev->driver->name,
472243791Sdim			e_dev->unit, irq);
473243791Sdim		return (-1);
474243791Sdim	}
475243791Sdim	s = splhigh();
476243791Sdim	INTREN((1ul << irq));
477243791Sdim	splx(s);
478243791Sdim	return 0;
479243791Sdim}
480243791Sdim
481243791Sdimstatic int
482243791Sdimeisa_add_resvaddr(e_dev, head, base, size, flags)
483243791Sdim	struct eisa_device *e_dev;
484243791Sdim	struct resvlist *head;
485243791Sdim	u_long	base;
486243791Sdim	u_long	size;
487243791Sdim	int	flags;
488243791Sdim{
489243791Sdim	resvaddr_t *reservation;
490243791Sdim
491243791Sdim	reservation = (resvaddr_t *)malloc(sizeof(resvaddr_t),
492243791Sdim					   M_DEVBUF, M_NOWAIT);
493243791Sdim	if(!reservation)
494243791Sdim		return (ENOMEM);
495243791Sdim
496243791Sdim	reservation->addr = base;
497243791Sdim	reservation->size = size;
498243791Sdim	reservation->flags = flags;
499243791Sdim
500243791Sdim	if (!head->lh_first) {
501243791Sdim		LIST_INSERT_HEAD(head, reservation, links);
502243791Sdim	}
503243791Sdim	else {
504243791Sdim		resvaddr_t *node;
505243791Sdim		for(node = head->lh_first; node; node = node->links.le_next) {
506243791Sdim			if (node->addr > reservation->addr) {
507243791Sdim				/*
508243791Sdim				 * List is sorted in increasing
509243791Sdim				 * address order.
510243791Sdim				 */
511243791Sdim				LIST_INSERT_BEFORE(node, reservation, links);
512243791Sdim				break;
513243791Sdim			}
514243791Sdim
515243791Sdim			if (node->addr == reservation->addr) {
516243791Sdim				/*
517243791Sdim				 * If the entry we want to add
518243791Sdim				 * matches any already in here,
519243791Sdim				 * fail.
520243791Sdim				 */
521243791Sdim				free(reservation, M_DEVBUF);
522243791Sdim				return (EEXIST);
523243791Sdim			}
524243791Sdim
525243791Sdim			if (!node->links.le_next) {
526243791Sdim				LIST_INSERT_AFTER(node, reservation, links);
527243791Sdim				break;
528243791Sdim			}
529243791Sdim		}
530243791Sdim	}
531243791Sdim	return (0);
532243791Sdim}
533243791Sdim
534243791Sdimint
535243791Sdimeisa_add_mspace(e_dev, mbase, msize, flags)
536243791Sdim	struct eisa_device *e_dev;
537243791Sdim	u_long	mbase;
538243791Sdim	u_long	msize;
539243791Sdim	int	flags;
540243791Sdim{
541243791Sdim	return	eisa_add_resvaddr(e_dev, &(e_dev->ioconf.maddrs), mbase, msize,
542243791Sdim				  flags);
543243791Sdim}
544243791Sdim
545243791Sdimint
546243791Sdimeisa_add_iospace(e_dev, iobase, iosize, flags)
547243791Sdim	struct eisa_device *e_dev;
548243791Sdim	u_long	iobase;
549243791Sdim	u_long	iosize;
550243791Sdim	int	flags;
551243791Sdim{
552243791Sdim	return	eisa_add_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), iobase,
553243791Sdim				  iosize, flags);
554243791Sdim}
555243791Sdim
556243791Sdimstatic int
557243791Sdimeisa_reg_resvaddr(e_dev, head, resvaddr, reg_count)
558243791Sdim	struct eisa_device *e_dev;
559243791Sdim	struct resvlist *head;
560243791Sdim	resvaddr_t *resvaddr;
561243791Sdim	int *reg_count;
562243791Sdim{
563243791Sdim	if (reg_state.in_registration) {
564243791Sdim		resvaddr_t *node;
565243791Sdim		/*
566243791Sdim		 * Ensure that this resvaddr is actually in the devices'
567243791Sdim		 * reservation list.
568243791Sdim		 */
569243791Sdim		for(node = head->lh_first; node;
570243791Sdim		    node = node->links.le_next) {
571243791Sdim			if (node == resvaddr) {
572243791Sdim				char buf[35];
573243791Sdim				char separator = ',';
574243791Sdim				char *string = buf;
575243791Sdim
576243791Sdim				if (*reg_count == 0) {
577243791Sdim					/* First time */
578243791Sdim					string += sprintf(string, " at");
579243791Sdim				}
580243791Sdim
581243791Sdim				if (node->size == 1
582243791Sdim				  || (node->flags & RESVADDR_BITMASK))
583					sprintf(string, " 0x%lx", node->addr);
584				else
585					sprintf(string, " 0x%lx-0x%lx",
586						node->addr,
587						node->addr + node->size - 1);
588				eisa_reg_print(e_dev, buf,
589						*reg_count ? &separator : NULL);
590				(*reg_count)++;
591				return (0);
592			}
593		}
594		return (ENOENT);
595	}
596	return EPERM;
597}
598
599int
600eisa_reg_mspace(e_dev, resvaddr)
601	struct eisa_device *e_dev;
602	resvaddr_t *resvaddr;
603{
604#ifdef NOT_YET
605	/*
606	 * Punt on conflict detection for the moment.
607	 * I want to develop a generic routine to do
608	 * this for all device types.
609	 */
610	int checkthese = CC_MADDR;
611	if (haveseen_dev(dev, checkthese))
612		return -1;
613#endif
614	return (eisa_reg_resvaddr(e_dev, &(e_dev->ioconf.maddrs), resvaddr,
615				  &(reg_state.num_maddrs)));
616}
617
618int
619eisa_reg_iospace(e_dev, resvaddr)
620	struct eisa_device *e_dev;
621	resvaddr_t *resvaddr;
622{
623#ifdef NOT_YET
624	/*
625	 * Punt on conflict detection for the moment.
626	 * I want to develop a generic routine to do
627	 * this for all device types.
628	 */
629	int checkthese = CC_IOADDR;
630	if (haveseen_dev(dev, checkthese))
631		return -1;
632#endif
633	return (eisa_reg_resvaddr(e_dev, &(e_dev->ioconf.ioaddrs), resvaddr,
634				  &(reg_state.num_ioaddrs)));
635}
636
637int
638eisa_registerdev(e_dev, driver)
639	struct eisa_device *e_dev;
640	struct eisa_driver *driver;
641{
642	e_dev->driver = driver;	/* Driver now owns this device */
643	return (0);
644}
645
646