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