aha_mca.c revision 302408
118334Speter/*- 2132718Skan * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net> 3169689Skan * All rights reserved. 4169689Skan * 518334Speter * Redistribution and use in source and binary forms, with or without 690075Sobrien * modification, are permitted provided that the following conditions 718334Speter * are met: 890075Sobrien * 1. Redistributions of source code must retain the above copyright 990075Sobrien * notice, this list of conditions and the following disclaimer. 1090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1190075Sobrien * notice, this list of conditions and the following disclaimer in the 1218334Speter * documentation and/or other materials provided with the distribution. 1390075Sobrien * 1490075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1590075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1690075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1718334Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1818334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1990075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2218334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2318334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2450397Sobrien * SUCH DAMAGE. 25132718Skan * 26132718Skan * Based on aha_isa.c 2750397Sobrien */ 2850397Sobrien 2950397Sobrien#include <sys/cdefs.h> 3050397Sobrien__FBSDID("$FreeBSD: stable/11/sys/dev/aha/aha_mca.c 241611 2012-10-16 15:25:04Z pluknet $"); 31132718Skan 3290075Sobrien#include <sys/types.h> 3390075Sobrien#include <sys/param.h> 3450397Sobrien#include <sys/systm.h> 3550397Sobrien#include <sys/kernel.h> 3650397Sobrien#include <sys/lock.h> 3790075Sobrien#include <sys/mutex.h> 3890075Sobrien 3990075Sobrien#include <sys/module.h> 40117395Skan#include <sys/bus.h> 41117395Skan#include <machine/bus.h> 42132718Skan#include <machine/resource.h> 43117395Skan#include <sys/rman.h> 4418334Speter 4552284Sobrien#include <isa/isavar.h> 4652284Sobrien 4718334Speter#include <dev/mca/mca_busreg.h> 4818334Speter#include <dev/mca/mca_busvar.h> 4918334Speter 5018334Speter#include <dev/aha/ahareg.h> 5118334Speter 5218334Speterstatic struct mca_ident aha_mca_devs[] = { 5318334Speter { 0x0f1f, "Adaptec AHA-1640 SCSI Adapter" }, 5418334Speter { 0, NULL }, 5518334Speter}; 5618334Speter 5718334Speter#define AHA_MCA_IOPORT_POS MCA_ADP_POS(MCA_POS1) 5818334Speter# define AHA_MCA_IOPORT_MASK1 0x07 5918334Speter# define AHA_MCA_IOPORT_MASK2 0xc0 6018334Speter# define AHA_MCA_IOPORT_SIZE 0x03 6150397Sobrien# define AHA_MCA_IOPORT(pos) (0x30 + \ 6218334Speter (((uint32_t)pos & \ 6318334Speter AHA_MCA_IOPORT_MASK1) << 8) + \ 6490075Sobrien (((uint32_t)pos & \ 6590075Sobrien AHA_MCA_IOPORT_MASK2) >> 4)) 6690075Sobrien 6790075Sobrien#define AHA_MCA_DRQ_POS MCA_ADP_POS(MCA_POS3) 68169689Skan# define AHA_MCA_DRQ_MASK 0x0f 69169689Skan# define AHA_MCA_DRQ(pos) (pos & AHA_MCA_DRQ_MASK) 70169689Skan 7118334Speter#define AHA_MCA_IRQ_POS MCA_ADP_POS(MCA_POS2) 7218334Speter# define AHA_MCA_IRQ_MASK 0x07 7318334Speter# define AHA_MCA_IRQ(pos) ((pos & AHA_MCA_IRQ_MASK) + 8) 74169689Skan 75169689Skan/* 7618334Speter * Not needed as the board knows its config 77117395Skan * internally and the ID will be fetched 7818334Speter * via AOP_INQUIRE_SETUP_INFO command. 7918334Speter */ 8018334Speter#define AHA_MCA_SCSIID_POS MCA_ADP_POS(MCA_POS2) 8118334Speter#define AHA_MCA_SCSIID_MASK 0xe0 82132718Skan#define AHA_MCA_SCSIID(pos) ((pos & AHA_MCA_SCSIID_MASK) >> 5) 83132718Skan 8418334Speterstatic int 8518334Speteraha_mca_probe (device_t dev) 8618334Speter{ 8718334Speter const char * desc; 8818334Speter mca_id_t id = mca_get_id(dev); 8918334Speter uint32_t iobase = 0; 9018334Speter uint32_t iosize = 0; 9118334Speter uint8_t drq = 0; 9218334Speter uint8_t irq = 0; 9318334Speter uint8_t pos; 9418334Speter 9518334Speter desc = mca_match_id(id, aha_mca_devs); 9618334Speter if (!desc) 9718334Speter return (ENXIO); 9818334Speter device_set_desc(dev, desc); 9918334Speter 10018334Speter pos = mca_pos_read(dev, AHA_MCA_IOPORT_POS); 101117395Skan iobase = AHA_MCA_IOPORT(pos); 10218334Speter iosize = AHA_MCA_IOPORT_SIZE; 10318334Speter 10418334Speter pos = mca_pos_read(dev, AHA_MCA_DRQ_POS); 10518334Speter drq = AHA_MCA_DRQ(pos); 10618334Speter 10718334Speter pos = mca_pos_read(dev, AHA_MCA_IRQ_POS); 10818334Speter irq = AHA_MCA_IRQ(pos); 10918334Speter 11090075Sobrien mca_add_iospace(dev, iobase, iosize); 11190075Sobrien mca_add_drq(dev, drq); 11290075Sobrien mca_add_irq(dev, irq); 11390075Sobrien 11490075Sobrien return (0); 11590075Sobrien} 11690075Sobrien 11718334Speterstatic int 11818334Speteraha_mca_attach (device_t dev) 11918334Speter{ 12018334Speter struct aha_softc * sc = device_get_softc(dev); 12118334Speter int error = ENOMEM; 122169689Skan 12318334Speter sc->portrid = 0; 124169689Skan sc->port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->portrid, 125132718Skan RF_ACTIVE); 126132718Skan if (sc->port == NULL) { 127132718Skan device_printf(dev, "No I/O space?!\n"); 128132718Skan goto bad; 129132718Skan } 130132718Skan 131132718Skan sc->irqrid = 0; 132132718Skan sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid, 133132718Skan RF_ACTIVE); 134132718Skan if (sc->irq == NULL) { 135132718Skan device_printf(dev, "No IRQ?!\n"); 136132718Skan goto bad; 137132718Skan } 138169689Skan 139132718Skan sc->drqrid = 0; 140132718Skan sc->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &sc->drqrid, 141132718Skan RF_ACTIVE); 142132718Skan if (sc->drq == NULL) { 143132718Skan device_printf(dev, "No DRQ?!\n"); 144132718Skan goto bad; 145132718Skan } 146132718Skan 147132718Skan aha_alloc(sc); 14890075Sobrien error = aha_probe(sc); 149132718Skan if (error) { 150169689Skan device_printf(dev, "aha_probe() failed!\n"); 151169689Skan goto bad; 152169689Skan } 15390075Sobrien 15490075Sobrien error = aha_fetch_adapter_info(sc); 155132718Skan if (error) { 156132718Skan device_printf(dev, "aha_fetch_adapter_info() failed!\n"); 15752284Sobrien goto bad; 15818334Speter } 15918334Speter 16018334Speter isa_dmacascade(rman_get_start(sc->drq)); 16118334Speter 16218334Speter error = bus_dma_tag_create( 16318334Speter /* parent */ bus_get_dma_tag(dev), 16418334Speter /* alignemnt */ 1, 16518334Speter /* boundary */ 0, 16618334Speter /* lowaddr */ BUS_SPACE_MAXADDR_24BIT, 167169689Skan /* highaddr */ BUS_SPACE_MAXADDR, 168169689Skan /* filter */ NULL, 16918334Speter /* filterarg */ NULL, 170132718Skan /* maxsize */ BUS_SPACE_MAXSIZE_24BIT, 17118334Speter /* nsegments */ ~0, 17218334Speter /* maxsegsz */ BUS_SPACE_MAXSIZE_24BIT, 17318334Speter /* flags */ 0, 17450397Sobrien /* lockfunc */ NULL, 17550397Sobrien /* lockarg */ NULL, 17650397Sobrien &sc->parent_dmat); 17750397Sobrien if (error) { 17890075Sobrien device_printf(dev, "bus_dma_tag_create() failed!\n"); 17918334Speter goto bad; 18018334Speter } 18118334Speter 182169689Skan error = aha_init(sc); 18318334Speter if (error) { 18418334Speter device_printf(dev, "aha_init() failed\n"); 18518334Speter goto bad; 18618334Speter } 18718334Speter 188169689Skan error = aha_attach(sc); 18918334Speter if (error) { 19018334Speter device_printf(dev, "aha_attach() failed\n"); 191169689Skan goto bad; 19218334Speter } 19318334Speter 19418334Speter error = bus_setup_intr(dev, sc->irq, INTR_TYPE_CAM | INTR_ENTROPY | 19518334Speter INTR_MPSAFE, NULL, aha_intr, sc, &sc->ih); 19618334Speter if (error) { 19718334Speter device_printf(dev, "Unable to register interrupt handler\n"); 19818334Speter aha_detach(sc); 19918334Speter goto bad; 20018334Speter } 20118334Speter 20250397Sobrien return (0); 20318334Speter 20418334Speterbad: 20550397Sobrien aha_free(sc); 20650397Sobrien bus_free_resource(dev, SYS_RES_IOPORT, sc->port); 20750397Sobrien bus_free_resource(dev, SYS_RES_IRQ, sc->irq); 20850397Sobrien bus_free_resource(dev, SYS_RES_DRQ, sc->drq); 20950397Sobrien return (error); 21018334Speter} 21118334Speter 21290075Sobrienstatic device_method_t aha_mca_methods[] = { 21390075Sobrien DEVMETHOD(device_probe, aha_mca_probe), 21490075Sobrien DEVMETHOD(device_attach, aha_mca_attach), 21590075Sobrien 21618334Speter { 0, 0 } 21718334Speter}; 21818334Speter 21918334Speterstatic driver_t aha_mca_driver = { 22018334Speter "aha", 22118334Speter aha_mca_methods, 22218334Speter 1, 22318334Speter/* 22418334Speter sizeof(struct aha_softc *), 22518334Speter */ 22618334Speter}; 22718334Speter 22818334Speterstatic devclass_t aha_devclass; 22918334Speter 23018334SpeterDRIVER_MODULE(aha, mca, aha_mca_driver, aha_devclass, 0, 0); 23118334SpeterMODULE_DEPEND(aha, mca, 1, 1, 1); 23218334Speter