aha_mca.c revision 127135
151829Smdodd/*- 251829Smdodd * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net> 351829Smdodd * All rights reserved. 451829Smdodd * 551829Smdodd * Redistribution and use in source and binary forms, with or without 651829Smdodd * modification, are permitted provided that the following conditions 751829Smdodd * are met: 851829Smdodd * 1. Redistributions of source code must retain the above copyright 951829Smdodd * notice, this list of conditions and the following disclaimer. 1051829Smdodd * 2. Redistributions in binary form must reproduce the above copyright 1151829Smdodd * notice, this list of conditions and the following disclaimer in the 1251829Smdodd * documentation and/or other materials provided with the distribution. 1351829Smdodd * 1451829Smdodd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1551829Smdodd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1651829Smdodd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1751829Smdodd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1851829Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1951829Smdodd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2051829Smdodd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2151829Smdodd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2251829Smdodd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2351829Smdodd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2451829Smdodd * SUCH DAMAGE. 2551829Smdodd * 2651829Smdodd * Based on aha_isa.c 2751829Smdodd */ 2851829Smdodd 29119418Sobrien#include <sys/cdefs.h> 30119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/aha/aha_mca.c 127135 2004-03-17 17:50:55Z njl $"); 31119418Sobrien 3251829Smdodd#include <sys/types.h> 3351829Smdodd#include <sys/param.h> 3451829Smdodd#include <sys/kernel.h> 35117126Sscottl#include <sys/lock.h> 36117126Sscottl#include <sys/mutex.h> 3751829Smdodd 3851829Smdodd#include <sys/module.h> 3951829Smdodd#include <sys/bus.h> 4051829Smdodd#include <machine/bus.h> 4151829Smdodd#include <machine/resource.h> 4251829Smdodd#include <sys/rman.h> 4351829Smdodd 4451829Smdodd#include <i386/isa/isa_dma.h> 4551829Smdodd 4651829Smdodd#include <dev/mca/mca_busreg.h> 4751829Smdodd#include <dev/mca/mca_busvar.h> 4851829Smdodd 4951829Smdodd#include <dev/aha/ahareg.h> 5051829Smdodd 5151829Smdoddstatic struct mca_ident aha_mca_devs[] = { 5251829Smdodd { 0x0f1f, "Adaptec AHA-1640 SCSI Adapter" }, 5351829Smdodd { 0, NULL }, 5451829Smdodd}; 5551829Smdodd 5651829Smdodd#define AHA_MCA_IOPORT_POS MCA_ADP_POS(MCA_POS1) 5751829Smdodd# define AHA_MCA_IOPORT_MASK1 0x07 5851829Smdodd# define AHA_MCA_IOPORT_MASK2 0xc0 5951829Smdodd# define AHA_MCA_IOPORT_SIZE 0x03 6051829Smdodd# define AHA_MCA_IOPORT(pos) (0x30 + \ 61122340Simp (((uint32_t)pos & \ 6251829Smdodd AHA_MCA_IOPORT_MASK1) << 8) + \ 63122340Simp (((uint32_t)pos & \ 6451829Smdodd AHA_MCA_IOPORT_MASK2) >> 4)) 6551829Smdodd 6651829Smdodd#define AHA_MCA_DRQ_POS MCA_ADP_POS(MCA_POS3) 6751829Smdodd# define AHA_MCA_DRQ_MASK 0x0f 6851829Smdodd# define AHA_MCA_DRQ(pos) (pos & AHA_MCA_DRQ_MASK) 6951829Smdodd 7051829Smdodd#define AHA_MCA_IRQ_POS MCA_ADP_POS(MCA_POS2) 7151829Smdodd# define AHA_MCA_IRQ_MASK 0x07 7251829Smdodd# define AHA_MCA_IRQ(pos) ((pos & AHA_MCA_IRQ_MASK) + 8) 7351829Smdodd 7451829Smdodd/* 7551829Smdodd * Not needed as the board knows its config 7651829Smdodd * internally and the ID will be fetched 7751829Smdodd * via AOP_INQUIRE_SETUP_INFO command. 7851829Smdodd */ 7951829Smdodd#define AHA_MCA_SCSIID_POS MCA_ADP_POS(MCA_POS2) 8051829Smdodd#define AHA_MCA_SCSIID_MASK 0xe0 8151829Smdodd#define AHA_MCA_SCSIID(pos) ((pos & AHA_MCA_SCSIID_MASK) >> 5) 8251829Smdodd 8351829Smdoddstatic int 8451829Smdoddaha_mca_probe (device_t dev) 8551829Smdodd{ 8651829Smdodd const char * desc; 8751829Smdodd mca_id_t id = mca_get_id(dev); 88122340Simp uint32_t iobase = 0; 89122340Simp uint32_t iosize = 0; 90122340Simp uint8_t drq = 0; 91122340Simp uint8_t irq = 0; 92122340Simp uint8_t pos; 9351829Smdodd 9451829Smdodd desc = mca_match_id(id, aha_mca_devs); 9551829Smdodd if (!desc) 9651829Smdodd return (ENXIO); 9751829Smdodd device_set_desc(dev, desc); 9851829Smdodd 9951829Smdodd pos = mca_pos_read(dev, AHA_MCA_IOPORT_POS); 10051829Smdodd iobase = AHA_MCA_IOPORT(pos); 10151829Smdodd iosize = AHA_MCA_IOPORT_SIZE; 10251829Smdodd 10351829Smdodd pos = mca_pos_read(dev, AHA_MCA_DRQ_POS); 10451829Smdodd drq = AHA_MCA_DRQ(pos); 10551829Smdodd 10651829Smdodd pos = mca_pos_read(dev, AHA_MCA_IRQ_POS); 10751829Smdodd irq = AHA_MCA_IRQ(pos); 10851829Smdodd 10951829Smdodd mca_add_iospace(dev, iobase, iosize); 11051829Smdodd mca_add_drq(dev, drq); 11151829Smdodd mca_add_irq(dev, irq); 11251829Smdodd 11351829Smdodd return (0); 11451829Smdodd} 11551829Smdodd 11651829Smdoddstatic int 11751829Smdoddaha_mca_attach (device_t dev) 11851829Smdodd{ 119122361Simp struct aha_softc * sc = device_get_softc(dev); 12051829Smdodd struct resource * io = NULL; 12151829Smdodd struct resource * irq = NULL; 12251829Smdodd struct resource * drq = NULL; 12351829Smdodd int error = 0; 12451829Smdodd int unit = device_get_unit(dev); 12551829Smdodd int rid; 12651829Smdodd void * ih; 12751829Smdodd 12851829Smdodd rid = 0; 129127135Snjl io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 13051829Smdodd if (!io) { 13151829Smdodd device_printf(dev, "No I/O space?!\n"); 13251829Smdodd error = ENOMEM; 13351829Smdodd goto bad; 13451829Smdodd } 13551829Smdodd 13651829Smdodd rid = 0; 137127135Snjl irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 13851829Smdodd if (irq == NULL) { 13951829Smdodd device_printf(dev, "No IRQ?!\n"); 14051829Smdodd error = ENOMEM; 14151829Smdodd goto bad; 14251829Smdodd } 14351829Smdodd 14451829Smdodd rid = 0; 145127135Snjl drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &rid, RF_ACTIVE); 14651829Smdodd if (drq == NULL) { 14751829Smdodd device_printf(dev, "No DRQ?!\n"); 14851829Smdodd error = ENOMEM; 14951829Smdodd goto bad; 15051829Smdodd } 15151829Smdodd 152122361Simp aha_alloc(sc, unit, rman_get_bustag(io), rman_get_bushandle(io)); 15351829Smdodd error = aha_probe(sc); 15451829Smdodd if (error) { 15551829Smdodd device_printf(dev, "aha_probe() failed!\n"); 15651829Smdodd goto bad; 15751829Smdodd } 15851829Smdodd 15951829Smdodd error = aha_fetch_adapter_info(sc); 16051829Smdodd if (error) { 16151829Smdodd device_printf(dev, "aha_fetch_adapter_info() failed!\n"); 16251829Smdodd goto bad; 16351829Smdodd } 16451829Smdodd 16551829Smdodd isa_dmacascade(rman_get_start(drq)); 16651829Smdodd 167112782Smdodd error = bus_dma_tag_create( 168112782Smdodd /* parent */ NULL, 169112782Smdodd /* alignemnt */ 1, 170112782Smdodd /* boundary */ 0, 171112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_24BIT, 172112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 173112782Smdodd /* filter */ NULL, 174112782Smdodd /* filterarg */ NULL, 175112782Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_24BIT, 176112782Smdodd /* nsegments */ ~0, 177112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_24BIT, 178112782Smdodd /* flags */ 0, 179117126Sscottl /* lockfunc */ busdma_lock_mutex, 180117126Sscottl /* lockarg */ &Giant, 181112782Smdodd &sc->parent_dmat); 18251829Smdodd if (error) { 18351829Smdodd device_printf(dev, "bus_dma_tag_create() failed!\n"); 18451829Smdodd goto bad; 18551829Smdodd } 18651829Smdodd 18751829Smdodd error = aha_init(sc); 18851829Smdodd if (error) { 18951829Smdodd device_printf(dev, "aha_init() failed\n"); 19051829Smdodd goto bad; 19151829Smdodd } 19251829Smdodd 19351829Smdodd error = aha_attach(sc); 19451829Smdodd if (error) { 19551829Smdodd device_printf(dev, "aha_attach() failed\n"); 19651829Smdodd goto bad; 19751829Smdodd } 19851829Smdodd 19973280Smarkm error = bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, aha_intr, sc, &ih); 20051829Smdodd if (error) { 20151829Smdodd device_printf(dev, "Unable to register interrupt handler\n"); 20251829Smdodd goto bad; 20351829Smdodd } 20451829Smdodd 20551829Smdodd return (0); 20651829Smdodd 20751829Smdoddbad: 20851829Smdodd aha_free(sc); 20951829Smdodd 21051829Smdodd if (io) 21151829Smdodd bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 21251829Smdodd if (irq) 21351829Smdodd bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 21451829Smdodd if (drq) 21551829Smdodd bus_release_resource(dev, SYS_RES_DRQ, 0, drq); 21651829Smdodd 21751829Smdodd return (error); 21851829Smdodd} 21951829Smdodd 22051829Smdoddstatic device_method_t aha_mca_methods[] = { 22151829Smdodd DEVMETHOD(device_probe, aha_mca_probe), 22251829Smdodd DEVMETHOD(device_attach, aha_mca_attach), 22351829Smdodd 22451829Smdodd { 0, 0 } 22551829Smdodd}; 22651829Smdodd 22751829Smdoddstatic driver_t aha_mca_driver = { 22851829Smdodd "aha", 22951829Smdodd aha_mca_methods, 23051829Smdodd 1, 23151829Smdodd/* 23251829Smdodd sizeof(struct aha_softc *), 23351829Smdodd */ 23451829Smdodd}; 23551829Smdodd 23651829Smdoddstatic devclass_t aha_devclass; 23751829Smdodd 23851829SmdoddDRIVER_MODULE(aha, mca, aha_mca_driver, aha_devclass, 0, 0); 239