[BACK]Return to isa_machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / x86 / isa

Annotation of src/sys/arch/x86/isa/isa_machdep.c, Revision 1.49

1.49    ! jmcneill    1: /*     $NetBSD: isa_machdep.c,v 1.48 2021/10/15 19:01:52 jmcneill Exp $        */
1.1       fvdl        2:
                      3: /*-
                      4:  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
                      9:  * Simulation Facility, NASA Ames Research Center.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     21:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     22:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     23:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     30:  * POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: /*-
                     34:  * Copyright (c) 1991 The Regents of the University of California.
                     35:  * All rights reserved.
                     36:  *
                     37:  * This code is derived from software contributed to Berkeley by
                     38:  * William Jolitz.
                     39:  *
                     40:  * Redistribution and use in source and binary forms, with or without
                     41:  * modification, are permitted provided that the following conditions
                     42:  * are met:
                     43:  * 1. Redistributions of source code must retain the above copyright
                     44:  *    notice, this list of conditions and the following disclaimer.
                     45:  * 2. Redistributions in binary form must reproduce the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer in the
                     47:  *    documentation and/or other materials provided with the distribution.
1.8       agc        48:  * 3. Neither the name of the University nor the names of its contributors
1.1       fvdl       49:  *    may be used to endorse or promote products derived from this software
                     50:  *    without specific prior written permission.
                     51:  *
                     52:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     53:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     54:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     55:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     56:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     57:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     58:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     59:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     60:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     61:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     62:  * SUCH DAMAGE.
                     63:  *
                     64:  *     @(#)isa.c       7.2 (Berkeley) 5/13/91
                     65:  */
                     66:
                     67: #include <sys/cdefs.h>
1.49    ! jmcneill   68: __KERNEL_RCSID(0, "$NetBSD: isa_machdep.c,v 1.48 2021/10/15 19:01:52 jmcneill Exp $");
1.1       fvdl       69:
                     70: #include <sys/param.h>
                     71: #include <sys/systm.h>
                     72: #include <sys/kernel.h>
                     73: #include <sys/syslog.h>
                     74: #include <sys/device.h>
                     75: #include <sys/proc.h>
1.26      ad         76: #include <sys/bus.h>
                     77: #include <sys/cpu.h>
1.1       fvdl       78:
1.12      yamt       79: #include <machine/bus_private.h>
1.1       fvdl       80: #include <machine/pio.h>
                     81: #include <machine/cpufunc.h>
1.31      dyoung     82: #include <machine/autoconf.h>
                     83: #include <machine/bootinfo.h>
1.1       fvdl       84:
                     85: #include <dev/isa/isareg.h>
                     86: #include <dev/isa/isavar.h>
                     87:
                     88: #include <uvm/uvm_extern.h>
                     89:
1.31      dyoung     90: #include "acpica.h"
                     91: #include "opt_acpi.h"
1.1       fvdl       92: #include "ioapic.h"
                     93:
                     94: #if NIOAPIC > 0
                     95: #include <machine/i82093var.h>
                     96: #include <machine/mpbiosvar.h>
1.2       fvdl       97: #endif
1.1       fvdl       98:
1.48      jmcneill   99: #if NACPICA > 0
                    100: #include <dev/acpi/acpivar.h>
                    101: #endif
                    102:
1.7       fvdl      103: static int _isa_dma_may_bounce(bus_dma_tag_t, bus_dmamap_t, int, int *);
1.1       fvdl      104:
                    105: struct x86_bus_dma_tag isa_bus_dma_tag = {
1.29      christos  106:        ._tag_needs_free        = 0,
                    107:        ._bounce_thresh         = ISA_DMA_BOUNCE_THRESHOLD,
                    108:        ._bounce_alloc_lo       = 0,
                    109:        ._bounce_alloc_hi       = ISA_DMA_BOUNCE_THRESHOLD,
                    110:        ._may_bounce            = _isa_dma_may_bounce,
1.1       fvdl      111: };
                    112:
1.7       fvdl      113: #define        IDTVEC(name)    __CONCAT(X,name)
1.25      dsl       114: typedef void (vector)(void);
1.7       fvdl      115: extern vector *IDTVEC(intr)[];
                    116:
1.1       fvdl      117: #define        LEGAL_IRQ(x)    ((x) >= 0 && (x) < NUM_LEGACY_IRQS && (x) != 2)
                    118:
                    119: int
1.15      christos  120: isa_intr_alloc(isa_chipset_tag_t ic, int mask, int type, int *irq)
1.1       fvdl      121: {
                    122:        int i, tmp, bestirq, count;
                    123:        struct intrhand **p, *q;
                    124:        struct intrsource *isp;
                    125:        struct cpu_info *ci;
                    126:
                    127:        if (type == IST_NONE)
                    128:                panic("intr_alloc: bogus type");
                    129:
                    130:        ci = &cpu_info_primary;
                    131:
                    132:        bestirq = -1;
                    133:        count = -1;
                    134:
                    135:        /* some interrupts should never be dynamically allocated */
                    136:        mask &= 0xdef8;
                    137:
                    138:        /*
                    139:         * XXX some interrupts will be used later (6 for fdc, 12 for pms).
                    140:         * the right answer is to do "breadth-first" searching of devices.
                    141:         */
                    142:        mask &= 0xefbf;
                    143:
1.26      ad        144:        mutex_enter(&cpu_lock);
1.1       fvdl      145:
                    146:        for (i = 0; i < NUM_LEGACY_IRQS; i++) {
                    147:                if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
                    148:                        continue;
                    149:                isp = ci->ci_isources[i];
                    150:                if (isp == NULL) {
1.32      mbalmer   151:                        /* if nothing's using the irq, just return it */
1.1       fvdl      152:                        *irq = i;
1.26      ad        153:                        mutex_exit(&cpu_lock);
1.32      mbalmer   154:                        return 0;
1.1       fvdl      155:                }
                    156:
                    157:                switch(isp->is_type) {
                    158:                case IST_EDGE:
                    159:                case IST_LEVEL:
                    160:                        if (type != isp->is_type)
                    161:                                continue;
                    162:                        /*
                    163:                         * if the irq is shareable, count the number of other
                    164:                         * handlers, and if it's smaller than the last irq like
                    165:                         * this, remember it
                    166:                         *
                    167:                         * XXX We should probably also consider the
                    168:                         * interrupt level and stick IPL_TTY with other
                    169:                         * IPL_TTY, etc.
                    170:                         */
                    171:                        for (p = &isp->is_handlers, tmp = 0; (q = *p) != NULL;
                    172:                             p = &q->ih_next, tmp++)
                    173:                                ;
                    174:                        if ((bestirq == -1) || (count > tmp)) {
                    175:                                bestirq = i;
                    176:                                count = tmp;
                    177:                        }
                    178:                        break;
                    179:                case IST_PULSE:
                    180:                        /* this just isn't shareable */
                    181:                        continue;
                    182:                }
                    183:        }
                    184:
1.26      ad        185:        mutex_exit(&cpu_lock);
1.1       fvdl      186:
                    187:        if (bestirq == -1)
1.32      mbalmer   188:                return 1;
1.1       fvdl      189:
                    190:        *irq = bestirq;
                    191:
1.32      mbalmer   192:        return 0;
1.1       fvdl      193: }
                    194:
                    195: const struct evcnt *
1.15      christos  196: isa_intr_evcnt(isa_chipset_tag_t ic, int irq)
1.1       fvdl      197: {
                    198:        /* XXX for now, no evcnt parent reported */
                    199:        return NULL;
                    200: }
                    201:
                    202: void *
1.32      mbalmer   203: isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
                    204:     int (*ih_fun)(void *), void *ih_arg)
1.1       fvdl      205: {
1.34      jdolecek  206:        return isa_intr_establish_xname(ic, irq, type, level,
                    207:            ih_fun, ih_arg, "unknown");
                    208: }
                    209:
                    210: void *
                    211: isa_intr_establish_xname(isa_chipset_tag_t ic, int irq, int type, int level,
                    212:     int (*ih_fun)(void *), void *ih_arg, const char *xname)
                    213: {
1.1       fvdl      214:        struct pic *pic;
                    215:        int pin;
1.41      cherry    216: #if NIOAPIC > 0
1.38      bouyer    217:        intr_handle_t mpih = 0;
1.35      cherry    218:        struct ioapic_softc *ioapic = NULL;
1.1       fvdl      219: #endif
                    220:
                    221:        pin = irq;
                    222:        pic = &i8259_pic;
                    223:
                    224: #if NIOAPIC > 0
                    225:        if (mp_busses != NULL) {
1.10      fvdl      226:                if (intr_find_mpmapping(mp_isa_bus, irq, &mpih) == 0 ||
                    227:                    intr_find_mpmapping(mp_eisa_bus, irq, &mpih) == 0) {
1.1       fvdl      228:                        if (!APIC_IRQ_ISLEGACY(mpih)) {
                    229:                                pin = APIC_IRQ_PIN(mpih);
1.23      drochner  230:                                ioapic = ioapic_find(APIC_IRQ_APIC(mpih));
                    231:                                if (ioapic == NULL) {
1.1       fvdl      232:                                        printf("isa_intr_establish: "
                    233:                                               "unknown apic %d\n",
                    234:                                            APIC_IRQ_APIC(mpih));
                    235:                                        return NULL;
                    236:                                }
1.23      drochner  237:                                pic = &ioapic->sc_pic;
1.1       fvdl      238:                        }
                    239:                } else
                    240:                        printf("isa_intr_establish: no MP mapping found\n");
                    241:        }
                    242: #endif
1.34      jdolecek  243:        return intr_establish_xname(irq, pic, pin, type, level, ih_fun, ih_arg,
                    244:            false, xname);
1.1       fvdl      245: }
                    246:
1.32      mbalmer   247: /* Deregister an interrupt handler. */
1.1       fvdl      248: void
1.15      christos  249: isa_intr_disestablish(isa_chipset_tag_t ic, void *arg)
1.1       fvdl      250: {
1.44      cherry    251: #if !defined(XENPV)
1.1       fvdl      252:        struct intrhand *ih = arg;
                    253:
                    254:        if (!LEGAL_IRQ(ih->ih_pin))
                    255:                panic("intr_disestablish: bogus irq");
                    256:
                    257:        intr_disestablish(ih);
1.35      cherry    258: #endif
1.1       fvdl      259: }
                    260:
                    261: void
1.32      mbalmer   262: isa_attach_hook(device_t parent, device_t self, struct isabus_attach_args *iba)
1.1       fvdl      263: {
1.4       fvdl      264:        extern struct x86_isa_chipset x86_isa_chipset;
1.1       fvdl      265:        extern int isa_has_been_seen;
                    266:
                    267:        /*
                    268:         * Notify others that might need to know that the ISA bus
                    269:         * has now been attached.
                    270:         */
                    271:        if (isa_has_been_seen)
                    272:                panic("isaattach: ISA bus already seen!");
                    273:        isa_has_been_seen = 1;
                    274:
                    275:        /*
                    276:         * Since we can only have one ISA bus, we just use a single
                    277:         * statically allocated ISA chipset structure.  Pass it up
                    278:         * now.
                    279:         */
1.4       fvdl      280:        iba->iba_ic = &x86_isa_chipset;
1.1       fvdl      281: }
                    282:
1.27      dyoung    283: void
1.28      dyoung    284: isa_detach_hook(isa_chipset_tag_t ic, device_t self)
1.27      dyoung    285: {
                    286:        extern int isa_has_been_seen;
                    287:
                    288:        isa_has_been_seen = 0;
                    289: }
                    290:
1.1       fvdl      291: int
1.21      cegger    292: isa_mem_alloc(bus_space_tag_t t, bus_size_t size, bus_size_t align,
1.32      mbalmer   293:     bus_addr_t boundary, int flags, bus_addr_t *addrp, bus_space_handle_t *bshp)
1.1       fvdl      294: {
1.32      mbalmer   295:        /* Allocate physical address space in the ISA hole. */
                    296:        return bus_space_alloc(t, IOM_BEGIN, IOM_END - 1, size, align,
                    297:            boundary, flags, addrp, bshp);
1.1       fvdl      298: }
                    299:
                    300: void
1.21      cegger    301: isa_mem_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
1.1       fvdl      302: {
                    303:        bus_space_free(t, bsh, size);
                    304: }
                    305:
                    306: /*
1.7       fvdl      307:  * ISA only has 24-bits of address space.  This means
                    308:  * we can't DMA to pages over 16M.  In order to DMA to
                    309:  * arbitrary buffers, we use "bounce buffers" - pages
                    310:  * in memory below the 16M boundary.  On DMA reads,
                    311:  * DMA happens to the bounce buffers, and is copied into
                    312:  * the caller's buffer.  On writes, data is copied into
                    313:  * but bounce buffer, and the DMA happens from those
                    314:  * pages.  To software using the DMA mapping interface,
                    315:  * this looks simply like a data cache.
                    316:  *
                    317:  * If we have more than 16M of RAM in the system, we may
                    318:  * need bounce buffers.  We check and remember that here.
                    319:  *
                    320:  * There are exceptions, however.  VLB devices can do
                    321:  * 32-bit DMA, and indicate that here.
                    322:  *
                    323:  * ...or, there is an opposite case.  The most segments
                    324:  * a transfer will require is (maxxfer / PAGE_SIZE) + 1.  If
                    325:  * the caller can't handle that many segments (e.g. the
                    326:  * ISA DMA controller), we may have to bounce it as well.
                    327:  */
                    328: static int
1.15      christos  329: _isa_dma_may_bounce(bus_dma_tag_t t, bus_dmamap_t map, int flags,
1.14      christos  330:     int *cookieflagsp)
1.1       fvdl      331: {
1.7       fvdl      332:        if ((flags & ISABUS_DMA_32BIT) != 0)
1.1       fvdl      333:                map->_dm_bounce_thresh = 0;
                    334:
1.7       fvdl      335:        if (((map->_dm_size / PAGE_SIZE) + 1) > map->_dm_segcnt)
1.11      thorpej   336:                *cookieflagsp |= X86_DMA_MIGHT_NEED_BOUNCE;
1.7       fvdl      337:        return 0;
1.1       fvdl      338: }
1.31      dyoung    339:
                    340: device_t
                    341: device_isa_register(device_t dev, void *aux)
                    342: {
                    343:        /*
                    344:         * Handle network interfaces here, the attachment information is
                    345:         * not available driver-independently later.
                    346:         *
                    347:         * For disks, there is nothing useful available at attach time.
                    348:         */
                    349:        if (device_class(dev) == DV_IFNET) {
                    350:                struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF);
                    351:                if (bin == NULL)
                    352:                        return NULL;
                    353:
                    354:                /*
                    355:                 * We don't check the driver name against the device name
                    356:                 * passed by the boot ROM.  The ROM should stay usable if
                    357:                 * the driver becomes obsolete.  The physical attachment
                    358:                 * information (checked below) must be sufficient to
1.32      mbalmer   359:                 * identify the device.
1.31      dyoung    360:                 */
                    361:                if (bin->bus == BI_BUS_ISA &&
                    362:                    device_is_a(device_parent(dev), "isa")) {
                    363:                        struct isa_attach_args *iaa = aux;
                    364:
                    365:                        /* Compare IO base address */
                    366:                        /* XXXJRT What about multiple IO addrs? */
                    367:                        if (iaa->ia_nio > 0 &&
                    368:                            bin->addr.iobase == iaa->ia_io[0].ir_addr)
                    369:                                return dev;
                    370:                }
                    371:        }
1.46      bouyer    372:        if (vm_guest == VM_GUEST_XENPVH)
                    373:                prop_dictionary_set_bool(device_properties(dev),
                    374:                    "no-legacy-devices", true);
1.31      dyoung    375: #if NACPICA > 0
                    376:        if (device_is_a(dev, "isa") && acpi_active) {
1.47      jmcneill  377:                /*
                    378:                 * For FACP >= 2, the LEGACY_DEVICES flag indicates that
                    379:                 * the motherboard supports user-visible devices on the LPC
                    380:                 * or ISA bus. If clear, assume that no such devices are
                    381:                 * present and we can enumerate everything we need using
                    382:                 * ACPI tables.
                    383:                 */
                    384:                if (AcpiGbl_FADT.Header.Revision >= 2 &&
                    385:                    !(AcpiGbl_FADT.BootFlags & ACPI_FADT_LEGACY_DEVICES)) {
1.31      dyoung    386:                        prop_dictionary_set_bool(device_properties(dev),
                    387:                            "no-legacy-devices", true);
1.47      jmcneill  388:                }
1.31      dyoung    389:        }
1.49    ! jmcneill  390:        if (vm_guest == VM_GUEST_VMWARE &&
        !           391:            device_is_a(dev, "isa") && acpi_active) {
        !           392:                prop_dictionary_set_bool(device_properties(dev),
        !           393:                    "no-legacy-devices", true);
        !           394:        }
1.31      dyoung    395: #endif /* NACPICA > 0 */
                    396:        return NULL;
                    397: }

CVSweb <webmaster@jp.NetBSD.org>