xref: /freebsd/sys/x86/isa/orm.c (revision d6b6639713e65ebb7982ddbc864e468328acdc8f)
132580301SAttilio Rao /*-
2ebf5747bSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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 __FBSDID("$FreeBSD$");
3132580301SAttilio Rao 
3232580301SAttilio Rao /*
3332580301SAttilio Rao  * Driver to take care of holes in ISA I/O memory occupied
3432580301SAttilio Rao  * by option rom(s)
3532580301SAttilio Rao  */
3632580301SAttilio Rao 
3732580301SAttilio Rao #include <sys/param.h>
3832580301SAttilio Rao #include <sys/systm.h>
3932580301SAttilio Rao #include <sys/kernel.h>
4032580301SAttilio Rao #include <sys/socket.h>
4132580301SAttilio Rao 
4232580301SAttilio Rao #include <sys/module.h>
4332580301SAttilio Rao #include <sys/bus.h>
4432580301SAttilio Rao 
4532580301SAttilio Rao #include <machine/bus.h>
4632580301SAttilio Rao #include <machine/resource.h>
4732580301SAttilio Rao #include <sys/rman.h>
4832580301SAttilio Rao 
4932580301SAttilio Rao #include <isa/isavar.h>
5032580301SAttilio Rao #include <isa/pnpvar.h>
5132580301SAttilio Rao 
5232580301SAttilio Rao #define	IOMEM_START	0x0a0000
5332580301SAttilio Rao #define	IOMEM_STEP	0x000800
5432580301SAttilio Rao #define	IOMEM_END	0x100000
5532580301SAttilio Rao 
5632580301SAttilio Rao #define	ORM_ID	0x00004d3e
5732580301SAttilio Rao 
5832580301SAttilio Rao static struct isa_pnp_id orm_ids[] = {
5932580301SAttilio Rao 	{ ORM_ID,	NULL },		/* ORM0000 */
6032580301SAttilio Rao 	{ 0,		NULL },
6132580301SAttilio Rao };
6232580301SAttilio Rao 
632c383f11SMarcel Moolenaar #define MAX_ROMS	32
6432580301SAttilio Rao 
6532580301SAttilio Rao struct orm_softc {
6632580301SAttilio Rao 	int		rnum;
6732580301SAttilio Rao 	int		rid[MAX_ROMS];
6832580301SAttilio Rao 	struct resource *res[MAX_ROMS];
6932580301SAttilio Rao };
7032580301SAttilio Rao 
7132580301SAttilio Rao static int
7232580301SAttilio Rao orm_probe(device_t dev)
7332580301SAttilio Rao {
7432580301SAttilio Rao 	return (ISA_PNP_PROBE(device_get_parent(dev), dev, orm_ids));
7532580301SAttilio Rao }
7632580301SAttilio Rao 
7732580301SAttilio Rao static int
7832580301SAttilio Rao orm_attach(device_t dev)
7932580301SAttilio Rao {
8032580301SAttilio Rao 	return (0);
8132580301SAttilio Rao }
8232580301SAttilio Rao 
8332580301SAttilio Rao static void
8432580301SAttilio Rao orm_identify(driver_t* driver, device_t parent)
8532580301SAttilio Rao {
8632580301SAttilio Rao 	bus_space_handle_t	bh;
8732580301SAttilio Rao 	bus_space_tag_t		bt;
8832580301SAttilio Rao 	device_t		child;
8932580301SAttilio Rao 	u_int32_t		chunk = IOMEM_START;
9032580301SAttilio Rao 	struct resource		*res;
9132580301SAttilio Rao 	int			rid;
9232580301SAttilio Rao 	u_int32_t		rom_size;
9332580301SAttilio Rao 	struct orm_softc	*sc;
9432580301SAttilio Rao 	u_int8_t		buf[3];
9532580301SAttilio Rao 
96c850971bSBjoern A. Zeeb 	if (resource_disabled("orm", 0))
97c850971bSBjoern A. Zeeb 		return;
98c850971bSBjoern A. Zeeb 
9932580301SAttilio Rao 	child = BUS_ADD_CHILD(parent, ISA_ORDER_SENSITIVE, "orm", -1);
10032580301SAttilio Rao 	device_set_driver(child, driver);
10132580301SAttilio Rao 	isa_set_logicalid(child, ORM_ID);
10232580301SAttilio Rao 	isa_set_vendorid(child, ORM_ID);
10332580301SAttilio Rao 	sc = device_get_softc(child);
10432580301SAttilio Rao 	sc->rnum = 0;
1052c383f11SMarcel Moolenaar 	while (sc->rnum < MAX_ROMS && chunk < IOMEM_END) {
10632580301SAttilio Rao 		bus_set_resource(child, SYS_RES_MEMORY, sc->rnum, chunk,
10732580301SAttilio Rao 		    IOMEM_STEP);
10832580301SAttilio Rao 		rid = sc->rnum;
10932580301SAttilio Rao 		res = bus_alloc_resource_any(child, SYS_RES_MEMORY, &rid,
11032580301SAttilio Rao 		    RF_ACTIVE);
11132580301SAttilio Rao 		if (res == NULL) {
11232580301SAttilio Rao 			bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
11332580301SAttilio Rao 			chunk += IOMEM_STEP;
11432580301SAttilio Rao 			continue;
11532580301SAttilio Rao 		}
11632580301SAttilio Rao 		bt = rman_get_bustag(res);
11732580301SAttilio Rao 		bh = rman_get_bushandle(res);
11832580301SAttilio Rao 		bus_space_read_region_1(bt, bh, 0, buf, sizeof(buf));
11932580301SAttilio Rao 
12032580301SAttilio Rao 		/*
12132580301SAttilio Rao 		 * We need to release and delete the resource since we're
12232580301SAttilio Rao 		 * changing its size, or the rom isn't there.  There
12332580301SAttilio Rao 		 * is a checksum field in the ROM to prevent false
12432580301SAttilio Rao 		 * positives.  However, some common hardware (IBM thinkpads)
12532580301SAttilio Rao 		 * neglects to put a valid checksum in the ROM, so we do
12632580301SAttilio Rao 		 * not double check the checksum here.  On the ISA bus
12732580301SAttilio Rao 		 * areas that have no hardware read back as 0xff, so the
12832580301SAttilio Rao 		 * tests to see if we have 0x55 followed by 0xaa are
12932580301SAttilio Rao 		 * generally sufficient.
13032580301SAttilio Rao 		 */
13132580301SAttilio Rao 		bus_release_resource(child, SYS_RES_MEMORY, rid, res);
13232580301SAttilio Rao 		bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
13332580301SAttilio Rao 		if (buf[0] != 0x55 || buf[1] != 0xAA || (buf[2] & 0x03) != 0) {
13432580301SAttilio Rao 			chunk += IOMEM_STEP;
13532580301SAttilio Rao 			continue;
13632580301SAttilio Rao 		}
13732580301SAttilio Rao 		rom_size = buf[2] << 9;
13832580301SAttilio Rao 		bus_set_resource(child, SYS_RES_MEMORY, sc->rnum, chunk,
13932580301SAttilio Rao 		    rom_size);
14032580301SAttilio Rao 		rid = sc->rnum;
14132580301SAttilio Rao 		res = bus_alloc_resource_any(child, SYS_RES_MEMORY, &rid, 0);
14232580301SAttilio Rao 		if (res == NULL) {
14332580301SAttilio Rao 			bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
14432580301SAttilio Rao 			chunk += IOMEM_STEP;
14532580301SAttilio Rao 			continue;
14632580301SAttilio Rao 		}
14732580301SAttilio Rao 		sc->rid[sc->rnum] = rid;
14832580301SAttilio Rao 		sc->res[sc->rnum] = res;
14932580301SAttilio Rao 		sc->rnum++;
15032580301SAttilio Rao 		chunk += rom_size;
15132580301SAttilio Rao 	}
15232580301SAttilio Rao 
15332580301SAttilio Rao 	if (sc->rnum == 0)
15432580301SAttilio Rao 		device_delete_child(parent, child);
15532580301SAttilio Rao 	else if (sc->rnum == 1)
15632580301SAttilio Rao 		device_set_desc(child, "ISA Option ROM");
15732580301SAttilio Rao 	else
15832580301SAttilio Rao 		device_set_desc(child, "ISA Option ROMs");
15932580301SAttilio Rao }
16032580301SAttilio Rao 
16132580301SAttilio Rao static int
16232580301SAttilio Rao orm_detach(device_t dev)
16332580301SAttilio Rao {
16432580301SAttilio Rao 	int			i;
16532580301SAttilio Rao 	struct orm_softc	*sc = device_get_softc(dev);
16632580301SAttilio Rao 
16732580301SAttilio Rao 	for (i = 0; i < sc->rnum; i++)
16832580301SAttilio Rao 		bus_release_resource(dev, SYS_RES_MEMORY, sc->rid[i],
16932580301SAttilio Rao 		    sc->res[i]);
17032580301SAttilio Rao 	return (0);
17132580301SAttilio Rao }
17232580301SAttilio Rao 
17332580301SAttilio Rao static device_method_t orm_methods[] = {
17432580301SAttilio Rao 	/* Device interface */
17532580301SAttilio Rao 	DEVMETHOD(device_identify,	orm_identify),
17632580301SAttilio Rao 	DEVMETHOD(device_probe,		orm_probe),
17732580301SAttilio Rao 	DEVMETHOD(device_attach,	orm_attach),
17832580301SAttilio Rao 	DEVMETHOD(device_detach,	orm_detach),
17932580301SAttilio Rao 	{ 0, 0 }
18032580301SAttilio Rao };
18132580301SAttilio Rao 
18232580301SAttilio Rao static driver_t orm_driver = {
18332580301SAttilio Rao 	"orm",
18432580301SAttilio Rao 	orm_methods,
18532580301SAttilio Rao 	sizeof (struct orm_softc)
18632580301SAttilio Rao };
18732580301SAttilio Rao 
18832580301SAttilio Rao static devclass_t orm_devclass;
18932580301SAttilio Rao 
19032580301SAttilio Rao DRIVER_MODULE(orm, isa, orm_driver, orm_devclass, 0, 0);
191*d6b66397SWarner Losh ISA_PNP_INFO(orm_ids);
192