1139749Simp/*- 265942Sgibbs * FreeBSD, EISA product support functions 365942Sgibbs * 439221Sgibbs * 571717Sgibbs * Copyright (c) 1994-1998, 2000, 2001 Justin T. Gibbs. 639221Sgibbs * All rights reserved. 739221Sgibbs * 839221Sgibbs * Redistribution and use in source and binary forms, with or without 939221Sgibbs * modification, are permitted provided that the following conditions 1039221Sgibbs * are met: 1139221Sgibbs * 1. Redistributions of source code must retain the above copyright 1239221Sgibbs * notice immediately at the beginning of the file, without modification, 1339221Sgibbs * this list of conditions, and the following disclaimer. 1439221Sgibbs * 2. The name of the author may not be used to endorse or promote products 1539221Sgibbs * derived from this software without specific prior written permission. 1639221Sgibbs * 1739221Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1839221Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1939221Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2039221Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2139221Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2239221Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2339221Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2439221Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2539221Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2639221Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2739221Sgibbs * SUCH DAMAGE. 2839221Sgibbs * 29123579Sgibbs * $Id: //depot/aic7xxx/freebsd/dev/aic7xxx/ahc_eisa.c#13 $ 3039221Sgibbs */ 3139221Sgibbs 32119418Sobrien#include <sys/cdefs.h> 33119418Sobrien__FBSDID("$FreeBSD$"); 34119418Sobrien 3595378Sgibbs#include <dev/aic7xxx/aic7xxx_osm.h> 3639221Sgibbs 3755953Speter#include <dev/eisa/eisaconf.h> 3839221Sgibbs 3939221Sgibbsstatic int 4045791Speteraic7770_probe(device_t dev) 4139221Sgibbs{ 4265942Sgibbs struct aic7770_identity *entry; 4365942Sgibbs struct resource *regs; 4463457Sgibbs uint32_t iobase; 4565942Sgibbs bus_space_handle_t bsh; 4665942Sgibbs bus_space_tag_t tag; 4765942Sgibbs u_int irq; 4865942Sgibbs u_int intdef; 4965942Sgibbs u_int hcntrl; 5065942Sgibbs int shared; 5165942Sgibbs int rid; 5265942Sgibbs int error; 5339221Sgibbs 5465942Sgibbs entry = aic7770_find_device(eisa_get_id(dev)); 5565942Sgibbs if (entry == NULL) 5645791Speter return (ENXIO); 5765942Sgibbs device_set_desc(dev, entry->name); 5839221Sgibbs 5956823Speter iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + AHC_EISA_SLOT_OFFSET; 6045791Speter 6165942Sgibbs eisa_add_iospace(dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE); 6239221Sgibbs 6371390Sgibbs rid = 0; 64127135Snjl regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 6565942Sgibbs if (regs == NULL) { 6665942Sgibbs device_printf(dev, "Unable to map I/O space?!\n"); 6765942Sgibbs return ENOMEM; 6865942Sgibbs } 6939221Sgibbs 7065942Sgibbs tag = rman_get_bustag(regs); 7165942Sgibbs bsh = rman_get_bushandle(regs); 7265942Sgibbs error = 0; 7365942Sgibbs 7465942Sgibbs /* Pause the card preseving the IRQ type */ 7565942Sgibbs hcntrl = bus_space_read_1(tag, bsh, HCNTRL) & IRQMS; 7665942Sgibbs bus_space_write_1(tag, bsh, HCNTRL, hcntrl | PAUSE); 7765942Sgibbs while ((bus_space_read_1(tag, bsh, HCNTRL) & PAUSE) == 0) 7865942Sgibbs ; 7965942Sgibbs 8065942Sgibbs /* Make sure we have a valid interrupt vector */ 8165942Sgibbs intdef = bus_space_read_1(tag, bsh, INTDEF); 8265942Sgibbs shared = (intdef & EDGE_TRIG) ? EISA_TRIGGER_EDGE : EISA_TRIGGER_LEVEL; 8365942Sgibbs irq = intdef & VECTOR; 8445791Speter switch (irq) { 8545791Speter case 9: 8645791Speter case 10: 8745791Speter case 11: 8845791Speter case 12: 8945791Speter case 14: 9045791Speter case 15: 9165942Sgibbs break; 9245791Speter default: 9365942Sgibbs printf("aic7770 at slot %d: illegal irq setting %d\n", 9465942Sgibbs eisa_get_slot(dev), intdef); 9565942Sgibbs error = ENXIO; 9639221Sgibbs } 9745791Speter 9865942Sgibbs if (error == 0) 9965942Sgibbs eisa_add_intr(dev, irq, shared); 10045791Speter 10165942Sgibbs bus_release_resource(dev, SYS_RES_IOPORT, rid, regs); 10265942Sgibbs return (error); 10339221Sgibbs} 10439221Sgibbs 10539221Sgibbsstatic int 10645791Speteraic7770_attach(device_t dev) 10739221Sgibbs{ 10865942Sgibbs struct aic7770_identity *entry; 10965942Sgibbs struct ahc_softc *ahc; 11065942Sgibbs char *name; 11165942Sgibbs int error; 11239221Sgibbs 11365942Sgibbs entry = aic7770_find_device(eisa_get_id(dev)); 11465942Sgibbs if (entry == NULL) 11565942Sgibbs return (ENXIO); 11639221Sgibbs 11765942Sgibbs /* 11865942Sgibbs * Allocate a softc for this card and 11965942Sgibbs * set it up for attachment by our 12065942Sgibbs * common detect routine. 12165942Sgibbs */ 12265942Sgibbs name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); 12365942Sgibbs if (name == NULL) 12465942Sgibbs return (ENOMEM); 12565942Sgibbs strcpy(name, device_get_nameunit(dev)); 12671390Sgibbs ahc = ahc_alloc(dev, name); 12765942Sgibbs if (ahc == NULL) 12865942Sgibbs return (ENOMEM); 12965942Sgibbs 13071390Sgibbs ahc_set_unit(ahc, device_get_unit(dev)); 13171390Sgibbs 13265942Sgibbs /* Allocate a dmatag for our SCB DMA maps */ 133161928Sjmg error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), 134161928Sjmg /*alignment*/1, /*boundary*/0, 13539221Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 13639221Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 13739221Sgibbs /*filter*/NULL, /*filterarg*/NULL, 138108479Sscottl /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 139108479Sscottl /*nsegments*/AHC_NSEG, 14039221Sgibbs /*maxsegsz*/AHC_MAXTRANSFER_SIZE, 141114618Sgibbs /*flags*/0, 14265942Sgibbs &ahc->parent_dmat); 14339221Sgibbs 14439221Sgibbs if (error != 0) { 14545967Sgibbs printf("ahc_eisa_attach: Could not allocate DMA tag " 14645967Sgibbs "- error %d\n", error); 14765942Sgibbs ahc_free(ahc); 14865942Sgibbs return (ENOMEM); 14939221Sgibbs } 15065942Sgibbs ahc->dev_softc = dev; 15195378Sgibbs error = aic7770_config(ahc, entry, /*unused ioport arg*/0); 15265942Sgibbs if (error != 0) { 15365942Sgibbs ahc_free(ahc); 15465942Sgibbs return (error); 15547274Sgibbs } 15647274Sgibbs 15739221Sgibbs ahc_attach(ahc); 15865942Sgibbs return (0); 15939221Sgibbs} 16039221Sgibbs 16139221Sgibbs 16295378Sgibbsstatic device_method_t ahc_eisa_device_methods[] = { 16345791Speter /* Device interface */ 16445791Speter DEVMETHOD(device_probe, aic7770_probe), 16545791Speter DEVMETHOD(device_attach, aic7770_attach), 16670204Sgibbs DEVMETHOD(device_detach, ahc_detach), 16745791Speter { 0, 0 } 16845791Speter}; 16945791Speter 17045791Speterstatic driver_t ahc_eisa_driver = { 171103811Sscottl "ahc", 17295378Sgibbs ahc_eisa_device_methods, 17370204Sgibbs sizeof(struct ahc_softc) 17445791Speter}; 17545791Speter 176103811SscottlDRIVER_MODULE(ahc_eisa, eisa, ahc_eisa_driver, ahc_devclass, 0, 0); 17776634SgibbsMODULE_DEPEND(ahc_eisa, ahc, 1, 1, 1); 17876634SgibbsMODULE_VERSION(ahc_eisa, 1); 179