150825Smdodd/*-
250825Smdodd * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net>
350825Smdodd * All rights reserved.
450825Smdodd *
550825Smdodd * Redistribution and use in source and binary forms, with or without
650825Smdodd * modification, are permitted provided that the following conditions
750825Smdodd * are met:
850825Smdodd * 1. Redistributions of source code must retain the above copyright
950825Smdodd *    notice, this list of conditions and the following disclaimer.
1050825Smdodd * 2. Redistributions in binary form must reproduce the above copyright
1150825Smdodd *    notice, this list of conditions and the following disclaimer in the
1250825Smdodd *    documentation and/or other materials provided with the distribution.
1350825Smdodd *
1450825Smdodd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1550825Smdodd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1650825Smdodd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1750825Smdodd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1850825Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1950825Smdodd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2050825Smdodd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2150825Smdodd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2250825Smdodd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2350825Smdodd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2450825Smdodd * SUCH DAMAGE.
2550825Smdodd *
2650825Smdodd */
2750825Smdodd
28119418Sobrien#include <sys/cdefs.h>
29119418Sobrien__FBSDID("$FreeBSD$");
30119418Sobrien
3150825Smdodd/*
3250825Smdodd * References:
3350825Smdodd *		The CMU Mach3 microkernel
3450825Smdodd *		NetBSD MCA patches by Scott Telford
3550825Smdodd *		Linux MCA code.
3650825Smdodd */
3750825Smdodd
3850825Smdodd#include <sys/param.h>
3950825Smdodd#include <sys/systm.h>
4050825Smdodd#include <sys/queue.h>
4150825Smdodd#include <sys/malloc.h>
4250825Smdodd#include <sys/kernel.h>
43114216Skan#include <sys/limits.h>
4450825Smdodd#include <sys/module.h>
4550825Smdodd#include <sys/bus.h>
4650825Smdodd
4750825Smdodd#include <machine/bus.h>
4850825Smdodd#include <machine/resource.h>
4950825Smdodd#include <sys/rman.h>
5050825Smdodd
5150825Smdodd#include <dev/mca/mca_busreg.h>
5250825Smdodd#include <dev/mca/mca_busvar.h>
5350825Smdodd
5450825Smdodd#include <sys/interrupt.h>
5550825Smdodd
5655890Smdodd#define MAX_COL	 79
5750825Smdodd
5850825Smdoddstatic void	mca_reg_print	(device_t, char *, char *, int *);
5950825Smdodd
6050825Smdoddstruct mca_device {
6152050Smdodd	struct resource_list rl;	/* Resources */
6252050Smdodd
6350825Smdodd	mca_id_t	id;
6450825Smdodd	u_int8_t	slot;
6550825Smdodd	u_int8_t	enabled;
6650825Smdodd	u_int8_t	pos[8];		/* Programable Option Select Regs. */
6750825Smdodd};
6850825Smdodd
6950825Smdodd/* Not supposed to use this function! */
7050825Smdoddvoid
71189004Srdivackymca_pos_set (device_t dev, u_int8_t reg, u_int8_t data)
7250825Smdodd{
7350825Smdodd	struct mca_device *	m_dev = device_get_ivars(dev);
7450825Smdodd	u_int8_t		slot = mca_get_slot(dev);
7550825Smdodd
7650825Smdodd	if ((slot > MCA_MAX_ADAPTERS) || (reg > MCA_POS7))
7750825Smdodd		return;
7850825Smdodd
7950825Smdodd	/* Disable motherboard setup */
8050825Smdodd	outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
8150825Smdodd
8250825Smdodd	/* Select adapter setup regs */
8350825Smdodd	outb(MCA_ADAP_SETUP_REG, ((slot & 0x0f) | MCA_ADAP_SET));
8450825Smdodd
8550825Smdodd	/* Write the register */
8650825Smdodd	outb(MCA_POS_REG(reg), data);
8750825Smdodd
8850825Smdodd	/* Disable adapter setup */
8950825Smdodd	outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
9050825Smdodd
9150825Smdodd	/* Update the IVAR copy */
9250825Smdodd	m_dev->pos[reg] = data;
9350825Smdodd
9450825Smdodd	return;
9550825Smdodd}
9650825Smdodd
9750825Smdoddu_int8_t
98189004Srdivackymca_pos_get (device_t dev, u_int8_t reg)
9950825Smdodd{
10050825Smdodd	u_int8_t	slot = mca_get_slot(dev);
10150825Smdodd	u_int8_t	data = 0;
10250825Smdodd
10350825Smdodd	if ((slot > MCA_MAX_ADAPTERS) || (reg > MCA_POS7))
10450825Smdodd		return (0);
10550825Smdodd
10650825Smdodd	/* Disable motherboard setup */
10750825Smdodd	outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
10850825Smdodd
10950825Smdodd	switch (slot) {
11050825Smdodd		case MCA_MB_SCSI_SLOT:
11150825Smdodd
11250825Smdodd			/* Disable adapter setup */
11350825Smdodd			outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
11450825Smdodd
11550825Smdodd			/* Select motherboard video setup regs */
11650825Smdodd			outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_SCSI);
11750825Smdodd
11850825Smdodd			/* read the register */
11950825Smdodd			data = inb(MCA_POS_REG(reg));
12050825Smdodd
12150825Smdodd			/* Disable motherboard setup */
12250825Smdodd			outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
12350825Smdodd
12450825Smdodd			break;
12550825Smdodd		case MCA_MB_VIDEO_SLOT:
12650825Smdodd			/* Disable adapter setup */
12750825Smdodd			outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
12850825Smdodd
12950825Smdodd			/* Select motherboard scsi setup regs */
13050825Smdodd			outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_VIDEO);
13150825Smdodd
13250825Smdodd			/* read the register */
13350825Smdodd			data = inb(MCA_POS_REG(reg));
13450825Smdodd
13550825Smdodd			/* Disable motherboard setup */
13650825Smdodd			outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
13750825Smdodd			break;
13850825Smdodd		default:
13950825Smdodd
14050825Smdodd			/* Select adapter setup regs */
14150825Smdodd			outb(MCA_ADAP_SETUP_REG,
14250825Smdodd			     ((slot & 0x0f) | MCA_ADAP_SET));
14350825Smdodd
14450825Smdodd			/* read the register */
14550825Smdodd			data = inb(MCA_POS_REG(reg));
14650825Smdodd
14750825Smdodd			/* Disable adapter setup */
14850825Smdodd			outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
14950825Smdodd			break;
15050825Smdodd	}
15150825Smdodd
15250825Smdodd	return (data);
15350825Smdodd}
15450825Smdodd
15550825Smdoddconst char *
156189004Srdivackymca_match_id (u_int16_t id, struct mca_ident *mca_devs)
15750825Smdodd{
15850825Smdodd	struct mca_ident *	m = mca_devs;
15950825Smdodd	while(m->name != NULL) {
16050825Smdodd		if (id == m->id)
16150825Smdodd			return (m->name);
16250825Smdodd		m++;
16350825Smdodd	}
16450825Smdodd	return (NULL);
16550825Smdodd}
16650825Smdodd
16750825Smdoddu_int8_t
168189004Srdivackymca_pos_read (device_t dev, u_int8_t reg)
16950825Smdodd{
17050825Smdodd	struct mca_device *	m_dev = device_get_ivars(dev);
17150825Smdodd
17250825Smdodd	if (reg > MCA_POS7)
17350825Smdodd		return (0);
17450825Smdodd
17550825Smdodd	return (m_dev->pos[reg]);
17650825Smdodd}
17750825Smdodd
17851674Smdoddvoid
17950825Smdoddmca_add_irq (dev, irq)
18050825Smdodd	device_t		dev;
18150825Smdodd	int			irq;
18250825Smdodd{
18350825Smdodd	struct mca_device *	m_dev = device_get_ivars(dev);
18451674Smdodd	int			rid = 0;
18550825Smdodd
18651674Smdodd	while (resource_list_find(&(m_dev->rl), SYS_RES_IRQ, rid)) rid++;
18751674Smdodd	resource_list_add(&(m_dev->rl), SYS_RES_IRQ, rid, irq, irq, 1);
18850825Smdodd
18951674Smdodd	return;
19050825Smdodd}
19150825Smdodd
19251674Smdoddvoid
19350825Smdoddmca_add_drq (dev, drq)
19451674Smdodd	device_t		dev;
19551674Smdodd	int			drq;
19650825Smdodd{
19750825Smdodd	struct mca_device *	m_dev = device_get_ivars(dev);
19851674Smdodd	int			rid = 0;
19950825Smdodd
20051674Smdodd	while (resource_list_find(&(m_dev->rl), SYS_RES_DRQ, rid)) rid++;
20151674Smdodd	resource_list_add(&(m_dev->rl), SYS_RES_DRQ, rid, drq, drq, 1);
20250825Smdodd
20351674Smdodd	return;
20450825Smdodd}
20550825Smdodd
20651674Smdoddvoid
20751674Smdoddmca_add_mspace (dev, mbase, msize)
20850825Smdodd	device_t		dev;
20950825Smdodd	u_long			mbase;
21050825Smdodd	u_long			msize;
21150825Smdodd{
21251674Smdodd	struct mca_device *	m_dev = device_get_ivars(dev);
21351674Smdodd	int			rid = 0;
21450825Smdodd
21551674Smdodd	while (resource_list_find(&(m_dev->rl), SYS_RES_MEMORY, rid)) rid++;
21651674Smdodd	resource_list_add(&(m_dev->rl), SYS_RES_MEMORY, rid,
21751674Smdodd		mbase, (mbase + msize), msize);
21851674Smdodd
21951674Smdodd	return;
22050825Smdodd}
22150825Smdodd
22251674Smdoddvoid
22351674Smdoddmca_add_iospace (dev, iobase, iosize)
22450825Smdodd	device_t		dev;
22550825Smdodd	u_long			iobase;
22650825Smdodd	u_long			iosize;
22750825Smdodd{
22850825Smdodd	struct mca_device *	m_dev = device_get_ivars(dev);
22951674Smdodd	int			rid = 0;
23050825Smdodd
23151674Smdodd	while (resource_list_find(&(m_dev->rl), SYS_RES_IOPORT, rid)) rid++;
23251674Smdodd	resource_list_add(&(m_dev->rl), SYS_RES_IOPORT, rid,
23351674Smdodd		iobase, (iobase + iosize), iosize);
23451674Smdodd
23551674Smdodd	return;
23650825Smdodd}
23750825Smdodd
23850825Smdoddstatic int
23950825Smdoddmca_probe (device_t dev)
24050825Smdodd{
24154073Smdodd	device_t		child;
24250825Smdodd	struct mca_device *	m_dev = NULL;
24350825Smdodd	int			devices_found = 0;
24450825Smdodd	u_int8_t		slot;
24550825Smdodd	u_int8_t		reg;
24650825Smdodd
24750825Smdodd	device_set_desc(dev, "MCA bus");
24850825Smdodd
24950825Smdodd	/* Disable adapter setup */
25050825Smdodd	outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
25150825Smdodd	/* Disable motherboard setup */
25250825Smdodd	outb(MCA_MB_SETUP_REG, MCA_MB_SETUP_DIS);
25350825Smdodd
25450825Smdodd	if (bootverbose) {
25550825Smdodd		printf("POS REG     00 01 02 03 04 05 06 07\n");
25650825Smdodd		printf("-----------------------------------\n");
25750825Smdodd	}
25850825Smdodd
25950825Smdodd	for (slot = 0; slot < MCA_MAX_SLOTS; slot++) {
26050825Smdodd
26150825Smdodd		if (!m_dev) {
26250825Smdodd			m_dev = (struct mca_device *)malloc(sizeof(*m_dev),
26350825Smdodd		 					    M_DEVBUF, M_NOWAIT);
26450825Smdodd			if (!m_dev) {
26550825Smdodd				device_printf(dev, "cannot malloc mca_device");
26650825Smdodd				break;
26750825Smdodd			}
26850825Smdodd		}
26950825Smdodd		bzero(m_dev, sizeof(*m_dev));
27050825Smdodd
27150825Smdodd		/* Select adapter setup regs */
27250825Smdodd		outb(MCA_ADAP_SETUP_REG, ((slot & 0x0f) | MCA_ADAP_SET));
27350825Smdodd
27450825Smdodd		/* Read the POS registers */
27550825Smdodd		for (reg = MCA_POS0; reg <= MCA_POS7; reg++) {
27650825Smdodd			m_dev->pos[reg] = inb(MCA_POS_REG(reg));
27750825Smdodd		}
27850825Smdodd
27950825Smdodd		/* Disable adapter setup */
28050825Smdodd		outb(MCA_ADAP_SETUP_REG, MCA_ADAP_SETUP_DIS);
28150825Smdodd
28250825Smdodd		if (bootverbose) {
28350825Smdodd			printf("mca slot %d:", slot + 1);
28450825Smdodd			for (reg = MCA_POS0; reg <= MCA_POS7; reg++) {
28550825Smdodd				printf(" %02x", m_dev->pos[reg]);
28650825Smdodd			}
28750825Smdodd			printf("\n");
28850825Smdodd		}
28950825Smdodd
29050825Smdodd		m_dev->id = (u_int16_t)m_dev->pos[MCA_POS0] |
29150825Smdodd			    ((u_int16_t)m_dev->pos[MCA_POS1] << 8);
29250825Smdodd
29350825Smdodd		if (m_dev->id == 0xffff) {
29450825Smdodd			continue;
29550825Smdodd		}
29650825Smdodd
29750825Smdodd		devices_found++;
29850825Smdodd
29950825Smdodd		m_dev->enabled = (m_dev->pos[MCA_POS2] & MCA_POS2_ENABLE);
30050825Smdodd		m_dev->slot = slot;
30150825Smdodd
30251674Smdodd		resource_list_init(&(m_dev->rl));
30350825Smdodd
30454073Smdodd		child = device_add_child(dev, NULL, -1);
30554073Smdodd		device_set_ivars(child, m_dev);
30651674Smdodd
30750825Smdodd		m_dev = NULL;
30850825Smdodd	}
30950825Smdodd
31050825Smdodd	if (m_dev) {
31150825Smdodd		free(m_dev, M_DEVBUF);
31250825Smdodd	}
31350825Smdodd
31450825Smdodd	return (devices_found ? 0 : ENXIO);
31550825Smdodd}
31650825Smdodd
31750825Smdoddstatic void
31850825Smdoddmca_reg_print (dev, string, separator, column)
31950825Smdodd	device_t	dev;
32050825Smdodd	char *		string;
32150825Smdodd	char *		separator;
32250825Smdodd	int *		column;
32350825Smdodd{
32450825Smdodd	int		length = strlen(string);
32550825Smdodd
32650825Smdodd	length += (separator ? 2 : 1);
32750825Smdodd
32850825Smdodd	if (((*column) + length) >= MAX_COL) {
32950825Smdodd		printf("\n");
33050825Smdodd		(*column) = 0;
33150825Smdodd	} else if ((*column) != 0) {
33250825Smdodd		if (separator) {
33350825Smdodd			printf("%c", *separator);
33450825Smdodd			(*column)++;
33550825Smdodd		}
33650825Smdodd		printf(" ");
33750825Smdodd		(*column)++;
33850825Smdodd	}
33950825Smdodd
34050825Smdodd	if ((*column) == 0) {
34150825Smdodd		(*column) += device_printf(dev, "%s", string);
34250825Smdodd	} else {
34350825Smdodd		(*column) += printf("%s", string);
34450825Smdodd	}
34550825Smdodd
34650825Smdodd	return;
34750825Smdodd}
34850825Smdodd
34950825Smdoddstatic int
35050825Smdoddmca_print_child (device_t dev, device_t child)
35150825Smdodd{
35251674Smdodd	char				buf[MAX_COL+1];
35351674Smdodd	struct mca_device *		m_dev = device_get_ivars(child);
35451674Smdodd	int				rid;
35551674Smdodd	struct resource_list_entry *	rle;
35651674Smdodd	char				separator = ',';
35751674Smdodd	int				column = 0;
35851674Smdodd	int				retval = 0;
35950825Smdodd
36050825Smdodd	if (device_get_desc(child)) {
36150825Smdodd		snprintf(buf, sizeof(buf), "<%s>", device_get_desc(child));
36250825Smdodd		mca_reg_print(child, buf, NULL, &column);
36350825Smdodd	}
36450825Smdodd
36550825Smdodd	rid = 0;
36651674Smdodd	while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_IOPORT, rid++))) {
36751674Smdodd		if (rle->count == 1) {
36850825Smdodd			snprintf(buf, sizeof(buf), "%s%lx",
36950825Smdodd				((rid == 1) ? "io 0x" : "0x"),
37051674Smdodd				rle->start);
37150825Smdodd		} else {
37250825Smdodd			snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
37350825Smdodd				((rid == 1) ? "io 0x" : "0x"),
37451674Smdodd				rle->start,
37551674Smdodd				(rle->start + rle->count));
37650825Smdodd		}
37750825Smdodd		mca_reg_print(child, buf,
37850825Smdodd			((rid == 2) ? &separator : NULL), &column);
37950825Smdodd	}
38050825Smdodd
38150825Smdodd	rid = 0;
38251674Smdodd	while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_MEMORY, rid++))) {
38351674Smdodd		if (rle->count == 1) {
38450825Smdodd			snprintf(buf, sizeof(buf), "%s%lx",
38550825Smdodd				((rid == 1) ? "mem 0x" : "0x"),
38651674Smdodd				rle->start);
38750825Smdodd		} else {
38850825Smdodd			snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
38950825Smdodd				((rid == 1) ? "mem 0x" : "0x"),
39051674Smdodd				rle->start,
39151674Smdodd				(rle->start + rle->count));
39250825Smdodd		}
39350825Smdodd		mca_reg_print(child, buf,
39450825Smdodd			((rid == 2) ? &separator : NULL), &column);
39550825Smdodd	}
39650825Smdodd
39750825Smdodd	rid = 0;
39851674Smdodd	while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_IRQ, rid++))) {
39951674Smdodd		snprintf(buf, sizeof(buf), "irq %ld", rle->start);
40050825Smdodd		mca_reg_print(child, buf,
40150825Smdodd			((rid == 1) ? &separator : NULL), &column);
40250825Smdodd	}
40350825Smdodd
40450825Smdodd	rid = 0;
40551674Smdodd	while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_DRQ, rid++))) {
40651674Smdodd		snprintf(buf, sizeof(buf), "drq %lx", rle->start);
40750825Smdodd		mca_reg_print(child, buf,
40850825Smdodd			((rid == 1) ? &separator : NULL), &column);
40950825Smdodd	}
41050825Smdodd
41150825Smdodd	snprintf(buf, sizeof(buf), "on %s id %04x slot %d\n",
41250825Smdodd		device_get_nameunit(dev),
41350825Smdodd		mca_get_id(child), mca_get_slot(child)+1);
41450825Smdodd	mca_reg_print(child, buf, NULL, &column);
41550825Smdodd
41650825Smdodd	return (retval);
41750825Smdodd}
41850825Smdodd
41950825Smdoddstatic void
42050825Smdoddmca_probe_nomatch (device_t dev, device_t child)
42150825Smdodd{
42250825Smdodd	mca_id_t	mca_id = mca_get_id(child);
42350825Smdodd	u_int8_t	slot = mca_get_slot(child);
42450825Smdodd	u_int8_t	enabled = mca_get_enabled(child);
42550825Smdodd
42650825Smdodd	device_printf(dev, "unknown card (id 0x%04x, %s) at slot %d\n",
42750825Smdodd		mca_id,
42850825Smdodd		(enabled ? "enabled" : "disabled"),
42950825Smdodd		slot + 1);
43050825Smdodd
43150825Smdodd	return;
43250825Smdodd}
43350825Smdodd
43450825Smdoddstatic int
435194020Savgmca_read_ivar (device_t dev, device_t child, int which, uintptr_t * result)
43650825Smdodd{
43751674Smdodd	struct mca_device *		m_dev = device_get_ivars(child);
43850825Smdodd
43950825Smdodd	switch (which) {
44050825Smdodd		case MCA_IVAR_SLOT:
44150825Smdodd			*result = m_dev->slot;
44250825Smdodd			break;
44350825Smdodd		case MCA_IVAR_ID:
44450825Smdodd			*result = m_dev->id;
44550825Smdodd			break;
44650825Smdodd		case MCA_IVAR_ENABLED:
44750825Smdodd			*result = m_dev->enabled;
44850825Smdodd			break;
44950825Smdodd		default:
45050825Smdodd			return (ENOENT);
45150825Smdodd			break;
45250825Smdodd	}
45350825Smdodd
45450825Smdodd	return (0);
45550825Smdodd}
45650825Smdodd
45750825Smdoddstatic struct resource *
45850825Smdoddmca_alloc_resource (device_t dev, device_t child, int type, int *rid,
45950825Smdodd		    u_long start, u_long end, u_long count, u_int flags)
46050825Smdodd{
46151674Smdodd	struct mca_device *		m_dev = device_get_ivars(child);
46251674Smdodd	struct resource_list_entry *	rle;
46351674Smdodd	int				isdefault;
46451674Smdodd	int				passthrough;
46550825Smdodd
46651674Smdodd	isdefault = (start == 0UL && end == ~0UL);
46751674Smdodd	passthrough = (device_get_parent(child) != dev);
46850825Smdodd
46951674Smdodd	if (!passthrough && !isdefault) {
47051674Smdodd		rle = resource_list_find(&(m_dev->rl), type, *rid);
47151674Smdodd		if (!rle) {
47251674Smdodd			resource_list_add(&(m_dev->rl), type, *rid,
47351674Smdodd					  start, end, count);
47451674Smdodd		}
47550825Smdodd	}
47650825Smdodd
47757980Smdodd	if (type == SYS_RES_IRQ) {
47857980Smdodd		flags |= RF_SHAREABLE;
47957980Smdodd	}
48057980Smdodd
48152915Smdodd	return (resource_list_alloc(&(m_dev->rl), dev, child, type, rid,
48251674Smdodd				    start, end, count, flags));
48350825Smdodd}
48450825Smdodd
48569295Smdoddstatic struct resource_list *
48669295Smdoddmca_get_resource_list (device_t dev, device_t child)
48750825Smdodd{
48869295Smdodd	struct mca_device *	m_dev = device_get_ivars(child);
48969295Smdodd	struct resource_list *	rl = &m_dev->rl;
49069295Smdodd
49169295Smdodd 	if (!rl)
49271239Sjhb		return (NULL);
49369295Smdodd
49469295Smdodd	return (rl);
49550825Smdodd}
49650825Smdodd
49750825Smdoddstatic device_method_t mca_methods[] = {
49850825Smdodd	/* Device interface */
49950825Smdodd	DEVMETHOD(device_probe,		mca_probe),
50050825Smdodd	DEVMETHOD(device_attach,	bus_generic_attach),
50150825Smdodd	DEVMETHOD(device_shutdown,      bus_generic_shutdown),
50250825Smdodd	DEVMETHOD(device_suspend,       bus_generic_suspend),
50350825Smdodd	DEVMETHOD(device_resume,	bus_generic_resume),
50450825Smdodd
50550825Smdodd	/* Bus interface */
50650825Smdodd	DEVMETHOD(bus_print_child,	mca_print_child),
50750825Smdodd	DEVMETHOD(bus_probe_nomatch,	mca_probe_nomatch),
50850825Smdodd	DEVMETHOD(bus_read_ivar,	mca_read_ivar),
50969295Smdodd	DEVMETHOD(bus_write_ivar,	bus_generic_write_ivar),
51050825Smdodd	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
51150825Smdodd	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
51250825Smdodd
51369295Smdodd	DEVMETHOD(bus_get_resource_list,mca_get_resource_list),
51469295Smdodd	DEVMETHOD(bus_alloc_resource,	mca_alloc_resource),
51569295Smdodd	DEVMETHOD(bus_release_resource,	bus_generic_rl_release_resource),
51669295Smdodd	DEVMETHOD(bus_set_resource,     bus_generic_rl_set_resource),
51769295Smdodd	DEVMETHOD(bus_get_resource,     bus_generic_rl_get_resource),
51869295Smdodd	DEVMETHOD(bus_delete_resource,  bus_generic_rl_delete_resource),
51969295Smdodd	DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
52069295Smdodd	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
52155890Smdodd
522227843Smarius	DEVMETHOD_END
52350825Smdodd};
52450825Smdodd
52550825Smdoddstatic driver_t mca_driver = {
52650825Smdodd	"mca",
52750825Smdodd	mca_methods,
52850825Smdodd	1,		/* no softc */
52950825Smdodd};
53050825Smdodd
53150825Smdoddstatic devclass_t mca_devclass;
53250825Smdodd
533104015SjhbDRIVER_MODULE(mca, legacy, mca_driver, mca_devclass, 0, 0);
534