ahc_eisa.c revision 70204
1/* 2 * FreeBSD, EISA product support functions 3 * 4 * 5 * Copyright (c) 1994, 1995, 1996, 1997, 1998, 2000 Justin T. Gibbs. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Id$ 30 * 31 * $FreeBSD: head/sys/dev/aic7xxx/ahc_eisa.c 70204 2000-12-20 01:11:37Z gibbs $ 32 */ 33 34#include <dev/aic7xxx/aic7xxx_freebsd.h> 35 36#include <dev/eisa/eisaconf.h> 37 38static int 39aic7770_probe(device_t dev) 40{ 41 struct aic7770_identity *entry; 42 struct resource *regs; 43 uint32_t iobase; 44 bus_space_handle_t bsh; 45 bus_space_tag_t tag; 46 u_int irq; 47 u_int intdef; 48 u_int hcntrl; 49 int shared; 50 int rid; 51 int error; 52 53 entry = aic7770_find_device(eisa_get_id(dev)); 54 if (entry == NULL) 55 return (ENXIO); 56 device_set_desc(dev, entry->name); 57 58 iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + AHC_EISA_SLOT_OFFSET; 59 60 eisa_add_iospace(dev, iobase, AHC_EISA_IOSIZE, RESVADDR_NONE); 61 62 regs = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 63 0, ~0, 1, RF_ACTIVE); 64 if (regs == NULL) { 65 device_printf(dev, "Unable to map I/O space?!\n"); 66 return ENOMEM; 67 } 68 69 tag = rman_get_bustag(regs); 70 bsh = rman_get_bushandle(regs); 71 error = 0; 72 73 /* Pause the card preseving the IRQ type */ 74 hcntrl = bus_space_read_1(tag, bsh, HCNTRL) & IRQMS; 75 bus_space_write_1(tag, bsh, HCNTRL, hcntrl | PAUSE); 76 while ((bus_space_read_1(tag, bsh, HCNTRL) & PAUSE) == 0) 77 ; 78 79 /* Make sure we have a valid interrupt vector */ 80 intdef = bus_space_read_1(tag, bsh, INTDEF); 81 shared = (intdef & EDGE_TRIG) ? EISA_TRIGGER_EDGE : EISA_TRIGGER_LEVEL; 82 irq = intdef & VECTOR; 83 switch (irq) { 84 case 9: 85 case 10: 86 case 11: 87 case 12: 88 case 14: 89 case 15: 90 break; 91 default: 92 printf("aic7770 at slot %d: illegal irq setting %d\n", 93 eisa_get_slot(dev), intdef); 94 error = ENXIO; 95 } 96 97 if (error == 0) 98 eisa_add_intr(dev, irq, shared); 99 100 bus_release_resource(dev, SYS_RES_IOPORT, rid, regs); 101 return (error); 102} 103 104static int 105aic7770_attach(device_t dev) 106{ 107 struct aic7770_identity *entry; 108 struct ahc_softc *ahc; 109 char *name; 110 int error; 111 112 entry = aic7770_find_device(eisa_get_id(dev)); 113 if (entry == NULL) 114 return (ENXIO); 115 116 /* 117 * Allocate a softc for this card and 118 * set it up for attachment by our 119 * common detect routine. 120 */ 121 name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); 122 if (name == NULL) 123 return (ENOMEM); 124 strcpy(name, device_get_nameunit(dev)); 125 ahc = ahc_alloc(NULL, name); 126 if (ahc == NULL) 127 return (ENOMEM); 128 129 /* Allocate a dmatag for our SCB DMA maps */ 130 /* XXX Should be a child of the PCI bus dma tag */ 131 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, 132 /*boundary*/0, 133 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 134 /*highaddr*/BUS_SPACE_MAXADDR, 135 /*filter*/NULL, /*filterarg*/NULL, 136 /*maxsize*/MAXBSIZE, /*nsegments*/AHC_NSEG, 137 /*maxsegsz*/AHC_MAXTRANSFER_SIZE, 138 /*flags*/BUS_DMA_ALLOCNOW, 139 &ahc->parent_dmat); 140 141 if (error != 0) { 142 printf("ahc_eisa_attach: Could not allocate DMA tag " 143 "- error %d\n", error); 144 ahc_free(ahc); 145 return (ENOMEM); 146 } 147 ahc->dev_softc = dev; 148 error = aic7770_config(ahc, entry); 149 if (error != 0) { 150 ahc_free(ahc); 151 return (error); 152 } 153 154 ahc_attach(ahc); 155 return (0); 156} 157 158int 159aic7770_map_registers(struct ahc_softc *ahc) 160{ 161 struct resource *regs; 162 int rid; 163 164 regs = bus_alloc_resource(ahc->dev_softc, SYS_RES_IOPORT, 165 &rid, 0, ~0, 1, RF_ACTIVE); 166 if (regs == NULL) { 167 device_printf(ahc->dev_softc, "Unable to map I/O space?!\n"); 168 return ENOMEM; 169 } 170 ahc->platform_data->regs_res_type = SYS_RES_IOPORT; 171 ahc->platform_data->regs_res_id = rid, 172 ahc->platform_data->regs = regs; 173 ahc->tag = rman_get_bustag(regs); 174 ahc->bsh = rman_get_bushandle(regs); 175 return (0); 176} 177 178int 179aic7770_map_int(struct ahc_softc *ahc) 180{ 181 int zero; 182 183 zero = 0; 184 ahc->platform_data->irq = 185 bus_alloc_resource(ahc->dev_softc, SYS_RES_IRQ, &zero, 186 0, ~0, 1, RF_ACTIVE); 187 if (ahc->platform_data->irq == NULL) 188 return (ENOMEM); 189 ahc->platform_data->irq_res_type = SYS_RES_IRQ; 190 return (0); 191} 192 193static device_method_t ahc_eisa_methods[] = { 194 /* Device interface */ 195 DEVMETHOD(device_probe, aic7770_probe), 196 DEVMETHOD(device_attach, aic7770_attach), 197 DEVMETHOD(device_detach, ahc_detach), 198 { 0, 0 } 199}; 200 201static driver_t ahc_eisa_driver = { 202 "ahc", 203 ahc_eisa_methods, 204 sizeof(struct ahc_softc) 205}; 206 207static devclass_t ahc_devclass; 208 209DRIVER_MODULE(ahc, eisa, ahc_eisa_driver, ahc_devclass, 0, 0); 210