ahc_eisa.c revision 71390
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 71390 2001-01-22 21:03:48Z 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 rid = 0; 63 regs = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 64 0, ~0, 1, RF_ACTIVE); 65 if (regs == NULL) { 66 device_printf(dev, "Unable to map I/O space?!\n"); 67 return ENOMEM; 68 } 69 70 tag = rman_get_bustag(regs); 71 bsh = rman_get_bushandle(regs); 72 error = 0; 73 74 /* Pause the card preseving the IRQ type */ 75 hcntrl = bus_space_read_1(tag, bsh, HCNTRL) & IRQMS; 76 bus_space_write_1(tag, bsh, HCNTRL, hcntrl | PAUSE); 77 while ((bus_space_read_1(tag, bsh, HCNTRL) & PAUSE) == 0) 78 ; 79 80 /* Make sure we have a valid interrupt vector */ 81 intdef = bus_space_read_1(tag, bsh, INTDEF); 82 shared = (intdef & EDGE_TRIG) ? EISA_TRIGGER_EDGE : EISA_TRIGGER_LEVEL; 83 irq = intdef & VECTOR; 84 switch (irq) { 85 case 9: 86 case 10: 87 case 11: 88 case 12: 89 case 14: 90 case 15: 91 break; 92 default: 93 printf("aic7770 at slot %d: illegal irq setting %d\n", 94 eisa_get_slot(dev), intdef); 95 error = ENXIO; 96 } 97 98 if (error == 0) 99 eisa_add_intr(dev, irq, shared); 100 101 bus_release_resource(dev, SYS_RES_IOPORT, rid, regs); 102 return (error); 103} 104 105static int 106aic7770_attach(device_t dev) 107{ 108 struct aic7770_identity *entry; 109 struct ahc_softc *ahc; 110 char *name; 111 int error; 112 113 entry = aic7770_find_device(eisa_get_id(dev)); 114 if (entry == NULL) 115 return (ENXIO); 116 117 /* 118 * Allocate a softc for this card and 119 * set it up for attachment by our 120 * common detect routine. 121 */ 122 name = malloc(strlen(device_get_nameunit(dev)) + 1, M_DEVBUF, M_NOWAIT); 123 if (name == NULL) 124 return (ENOMEM); 125 strcpy(name, device_get_nameunit(dev)); 126 ahc = ahc_alloc(dev, name); 127 if (ahc == NULL) 128 return (ENOMEM); 129 130 ahc_set_unit(ahc, device_get_unit(dev)); 131 132 /* Allocate a dmatag for our SCB DMA maps */ 133 /* XXX Should be a child of the PCI bus dma tag */ 134 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, 135 /*boundary*/0, 136 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 137 /*highaddr*/BUS_SPACE_MAXADDR, 138 /*filter*/NULL, /*filterarg*/NULL, 139 /*maxsize*/MAXBSIZE, /*nsegments*/AHC_NSEG, 140 /*maxsegsz*/AHC_MAXTRANSFER_SIZE, 141 /*flags*/BUS_DMA_ALLOCNOW, 142 &ahc->parent_dmat); 143 144 if (error != 0) { 145 printf("ahc_eisa_attach: Could not allocate DMA tag " 146 "- error %d\n", error); 147 ahc_free(ahc); 148 return (ENOMEM); 149 } 150 ahc->dev_softc = dev; 151 error = aic7770_config(ahc, entry); 152 if (error != 0) { 153 ahc_free(ahc); 154 return (error); 155 } 156 157 ahc_attach(ahc); 158 return (0); 159} 160 161int 162aic7770_map_registers(struct ahc_softc *ahc) 163{ 164 struct resource *regs; 165 int rid; 166 167 rid = 0; 168 regs = bus_alloc_resource(ahc->dev_softc, SYS_RES_IOPORT, 169 &rid, 0, ~0, 1, RF_ACTIVE); 170 if (regs == NULL) { 171 device_printf(ahc->dev_softc, "Unable to map I/O space?!\n"); 172 return ENOMEM; 173 } 174 ahc->platform_data->regs_res_type = SYS_RES_IOPORT; 175 ahc->platform_data->regs_res_id = rid, 176 ahc->platform_data->regs = regs; 177 ahc->tag = rman_get_bustag(regs); 178 ahc->bsh = rman_get_bushandle(regs); 179 return (0); 180} 181 182int 183aic7770_map_int(struct ahc_softc *ahc) 184{ 185 int zero; 186 187 zero = 0; 188 ahc->platform_data->irq = 189 bus_alloc_resource(ahc->dev_softc, SYS_RES_IRQ, &zero, 190 0, ~0, 1, RF_ACTIVE); 191 if (ahc->platform_data->irq == NULL) 192 return (ENOMEM); 193 ahc->platform_data->irq_res_type = SYS_RES_IRQ; 194 return (0); 195} 196 197static device_method_t ahc_eisa_methods[] = { 198 /* Device interface */ 199 DEVMETHOD(device_probe, aic7770_probe), 200 DEVMETHOD(device_attach, aic7770_attach), 201 DEVMETHOD(device_detach, ahc_detach), 202 { 0, 0 } 203}; 204 205static driver_t ahc_eisa_driver = { 206 "ahc", 207 ahc_eisa_methods, 208 sizeof(struct ahc_softc) 209}; 210 211static devclass_t ahc_devclass; 212 213DRIVER_MODULE(ahc, eisa, ahc_eisa_driver, ahc_devclass, 0, 0); 214