xref: /freebsd/sys/x86/isa/orm.c (revision a05a680469a7ac77b195021fed74e3aa58152dd7)
132580301SAttilio Rao /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3ebf5747bSPedro F. Giffuni  *
432580301SAttilio Rao  * Copyright (c) 2000 Nikolai Saoukh
532580301SAttilio Rao  * All rights reserved.
632580301SAttilio Rao  *
732580301SAttilio Rao  * Redistribution and use in source and binary forms, with or without
832580301SAttilio Rao  * modification, are permitted provided that the following conditions
932580301SAttilio Rao  * are met:
1032580301SAttilio Rao  * 1. Redistributions of source code must retain the above copyright
1132580301SAttilio Rao  *    notice, this list of conditions and the following disclaimer.
1232580301SAttilio Rao  * 2. Redistributions in binary form must reproduce the above copyright
1332580301SAttilio Rao  *    notice, this list of conditions and the following disclaimer in the
1432580301SAttilio Rao  *    documentation and/or other materials provided with the distribution.
1532580301SAttilio Rao  *
1632580301SAttilio Rao  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1732580301SAttilio Rao  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1832580301SAttilio Rao  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1932580301SAttilio Rao  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2032580301SAttilio Rao  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2132580301SAttilio Rao  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2232580301SAttilio Rao  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2332580301SAttilio Rao  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2432580301SAttilio Rao  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2532580301SAttilio Rao  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2632580301SAttilio Rao  * SUCH DAMAGE.
2732580301SAttilio Rao  */
2832580301SAttilio Rao 
2932580301SAttilio Rao #include <sys/cdefs.h>
3032580301SAttilio Rao /*
3132580301SAttilio Rao  * Driver to take care of holes in ISA I/O memory occupied
3232580301SAttilio Rao  * by option rom(s)
3332580301SAttilio Rao  */
3432580301SAttilio Rao 
3532580301SAttilio Rao #include <sys/param.h>
3632580301SAttilio Rao #include <sys/systm.h>
3732580301SAttilio Rao #include <sys/kernel.h>
3832580301SAttilio Rao #include <sys/socket.h>
3932580301SAttilio Rao 
4032580301SAttilio Rao #include <sys/module.h>
4132580301SAttilio Rao #include <sys/bus.h>
4232580301SAttilio Rao 
4332580301SAttilio Rao #include <machine/bus.h>
4432580301SAttilio Rao #include <machine/resource.h>
4532580301SAttilio Rao #include <sys/rman.h>
4632580301SAttilio Rao 
4732580301SAttilio Rao #include <isa/isavar.h>
4832580301SAttilio Rao #include <isa/pnpvar.h>
4932580301SAttilio Rao 
5032580301SAttilio Rao #define	IOMEM_START	0x0a0000
5132580301SAttilio Rao #define	IOMEM_STEP	0x000800
5232580301SAttilio Rao #define	IOMEM_END	0x100000
5332580301SAttilio Rao 
5432580301SAttilio Rao #define	ORM_ID	0x00004d3e
5532580301SAttilio Rao 
5632580301SAttilio Rao static struct isa_pnp_id orm_ids[] = {
5732580301SAttilio Rao 	{ ORM_ID,	NULL },		/* ORM0000 */
5832580301SAttilio Rao 	{ 0,		NULL },
5932580301SAttilio Rao };
6032580301SAttilio Rao 
612c383f11SMarcel Moolenaar #define MAX_ROMS	32
6232580301SAttilio Rao 
6332580301SAttilio Rao struct orm_softc {
6432580301SAttilio Rao 	int		rnum;
6532580301SAttilio Rao 	int		rid[MAX_ROMS];
6632580301SAttilio Rao 	struct resource *res[MAX_ROMS];
6732580301SAttilio Rao };
6832580301SAttilio Rao 
6932580301SAttilio Rao static int
7032580301SAttilio Rao orm_probe(device_t dev)
7132580301SAttilio Rao {
7232580301SAttilio Rao 	return (ISA_PNP_PROBE(device_get_parent(dev), dev, orm_ids));
7332580301SAttilio Rao }
7432580301SAttilio Rao 
7532580301SAttilio Rao static int
7632580301SAttilio Rao orm_attach(device_t dev)
7732580301SAttilio Rao {
7832580301SAttilio Rao 	return (0);
7932580301SAttilio Rao }
8032580301SAttilio Rao 
8132580301SAttilio Rao static void
8232580301SAttilio Rao orm_identify(driver_t* driver, device_t parent)
8332580301SAttilio Rao {
8432580301SAttilio Rao 	bus_space_handle_t	bh;
8532580301SAttilio Rao 	bus_space_tag_t		bt;
8632580301SAttilio Rao 	device_t		child;
8732580301SAttilio Rao 	u_int32_t		chunk = IOMEM_START;
8832580301SAttilio Rao 	struct resource		*res;
8932580301SAttilio Rao 	int			rid;
9032580301SAttilio Rao 	u_int32_t		rom_size;
9132580301SAttilio Rao 	struct orm_softc	*sc;
9232580301SAttilio Rao 	u_int8_t		buf[3];
9332580301SAttilio Rao 
94c850971bSBjoern A. Zeeb 	if (resource_disabled("orm", 0))
95c850971bSBjoern A. Zeeb 		return;
96c850971bSBjoern A. Zeeb 
97*a05a6804SWarner Losh 	child = BUS_ADD_CHILD(parent, ISA_ORDER_SENSITIVE, "orm", DEVICE_UNIT_ANY);
9832580301SAttilio Rao 	device_set_driver(child, driver);
9932580301SAttilio Rao 	isa_set_logicalid(child, ORM_ID);
10032580301SAttilio Rao 	isa_set_vendorid(child, ORM_ID);
10132580301SAttilio Rao 	sc = device_get_softc(child);
10232580301SAttilio Rao 	sc->rnum = 0;
1032c383f11SMarcel Moolenaar 	while (sc->rnum < MAX_ROMS && chunk < IOMEM_END) {
10432580301SAttilio Rao 		bus_set_resource(child, SYS_RES_MEMORY, sc->rnum, chunk,
10532580301SAttilio Rao 		    IOMEM_STEP);
10632580301SAttilio Rao 		rid = sc->rnum;
10732580301SAttilio Rao 		res = bus_alloc_resource_any(child, SYS_RES_MEMORY, &rid,
10832580301SAttilio Rao 		    RF_ACTIVE);
10932580301SAttilio Rao 		if (res == NULL) {
11032580301SAttilio Rao 			bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
11132580301SAttilio Rao 			chunk += IOMEM_STEP;
11232580301SAttilio Rao 			continue;
11332580301SAttilio Rao 		}
11432580301SAttilio Rao 		bt = rman_get_bustag(res);
11532580301SAttilio Rao 		bh = rman_get_bushandle(res);
11632580301SAttilio Rao 		bus_space_read_region_1(bt, bh, 0, buf, sizeof(buf));
11732580301SAttilio Rao 
11832580301SAttilio Rao 		/*
11932580301SAttilio Rao 		 * We need to release and delete the resource since we're
12032580301SAttilio Rao 		 * changing its size, or the rom isn't there.  There
12132580301SAttilio Rao 		 * is a checksum field in the ROM to prevent false
12232580301SAttilio Rao 		 * positives.  However, some common hardware (IBM thinkpads)
12332580301SAttilio Rao 		 * neglects to put a valid checksum in the ROM, so we do
12432580301SAttilio Rao 		 * not double check the checksum here.  On the ISA bus
12532580301SAttilio Rao 		 * areas that have no hardware read back as 0xff, so the
12632580301SAttilio Rao 		 * tests to see if we have 0x55 followed by 0xaa are
12732580301SAttilio Rao 		 * generally sufficient.
12832580301SAttilio Rao 		 */
12932580301SAttilio Rao 		bus_release_resource(child, SYS_RES_MEMORY, rid, res);
13032580301SAttilio Rao 		bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
13132580301SAttilio Rao 		if (buf[0] != 0x55 || buf[1] != 0xAA || (buf[2] & 0x03) != 0) {
13232580301SAttilio Rao 			chunk += IOMEM_STEP;
13332580301SAttilio Rao 			continue;
13432580301SAttilio Rao 		}
13532580301SAttilio Rao 		rom_size = buf[2] << 9;
13632580301SAttilio Rao 		bus_set_resource(child, SYS_RES_MEMORY, sc->rnum, chunk,
13732580301SAttilio Rao 		    rom_size);
13832580301SAttilio Rao 		rid = sc->rnum;
13932580301SAttilio Rao 		res = bus_alloc_resource_any(child, SYS_RES_MEMORY, &rid, 0);
14032580301SAttilio Rao 		if (res == NULL) {
14132580301SAttilio Rao 			bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
14232580301SAttilio Rao 			chunk += IOMEM_STEP;
14332580301SAttilio Rao 			continue;
14432580301SAttilio Rao 		}
14532580301SAttilio Rao 		sc->rid[sc->rnum] = rid;
14632580301SAttilio Rao 		sc->res[sc->rnum] = res;
14732580301SAttilio Rao 		sc->rnum++;
14832580301SAttilio Rao 		chunk += rom_size;
14932580301SAttilio Rao 	}
15032580301SAttilio Rao 
15132580301SAttilio Rao 	if (sc->rnum == 0)
15232580301SAttilio Rao 		device_delete_child(parent, child);
15332580301SAttilio Rao 	else if (sc->rnum == 1)
15432580301SAttilio Rao 		device_set_desc(child, "ISA Option ROM");
15532580301SAttilio Rao 	else
15632580301SAttilio Rao 		device_set_desc(child, "ISA Option ROMs");
15732580301SAttilio Rao }
15832580301SAttilio Rao 
15932580301SAttilio Rao static int
16032580301SAttilio Rao orm_detach(device_t dev)
16132580301SAttilio Rao {
16232580301SAttilio Rao 	int			i;
16332580301SAttilio Rao 	struct orm_softc	*sc = device_get_softc(dev);
16432580301SAttilio Rao 
16532580301SAttilio Rao 	for (i = 0; i < sc->rnum; i++)
16632580301SAttilio Rao 		bus_release_resource(dev, SYS_RES_MEMORY, sc->rid[i],
16732580301SAttilio Rao 		    sc->res[i]);
16832580301SAttilio Rao 	return (0);
16932580301SAttilio Rao }
17032580301SAttilio Rao 
17132580301SAttilio Rao static device_method_t orm_methods[] = {
17232580301SAttilio Rao 	/* Device interface */
17332580301SAttilio Rao 	DEVMETHOD(device_identify,	orm_identify),
17432580301SAttilio Rao 	DEVMETHOD(device_probe,		orm_probe),
17532580301SAttilio Rao 	DEVMETHOD(device_attach,	orm_attach),
17632580301SAttilio Rao 	DEVMETHOD(device_detach,	orm_detach),
17732580301SAttilio Rao 	{ 0, 0 }
17832580301SAttilio Rao };
17932580301SAttilio Rao 
18032580301SAttilio Rao static driver_t orm_driver = {
18132580301SAttilio Rao 	"orm",
18232580301SAttilio Rao 	orm_methods,
18332580301SAttilio Rao 	sizeof (struct orm_softc)
18432580301SAttilio Rao };
18532580301SAttilio Rao 
18680d2b3deSJohn Baldwin DRIVER_MODULE(orm, isa, orm_driver, 0, 0);
187d6b66397SWarner Losh ISA_PNP_INFO(orm_ids);
188