aha_mca.c revision 122361
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 122361 2003-11-09 19:51:16Z imp $"); 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; 12951829Smdodd io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 13051829Smdodd 0, ~0, 1, RF_ACTIVE); 13151829Smdodd if (!io) { 13251829Smdodd device_printf(dev, "No I/O space?!\n"); 13351829Smdodd error = ENOMEM; 13451829Smdodd goto bad; 13551829Smdodd } 13651829Smdodd 13751829Smdodd rid = 0; 13851829Smdodd irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 13951829Smdodd 0, ~0, 1, RF_ACTIVE); 14051829Smdodd if (irq == NULL) { 14151829Smdodd device_printf(dev, "No IRQ?!\n"); 14251829Smdodd error = ENOMEM; 14351829Smdodd goto bad; 14451829Smdodd } 14551829Smdodd 14651829Smdodd rid = 0; 14751829Smdodd drq = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 14851829Smdodd 0, ~0, 1, RF_ACTIVE); 14951829Smdodd if (drq == NULL) { 15051829Smdodd device_printf(dev, "No DRQ?!\n"); 15151829Smdodd error = ENOMEM; 15251829Smdodd goto bad; 15351829Smdodd } 15451829Smdodd 155122361Simp aha_alloc(sc, unit, rman_get_bustag(io), rman_get_bushandle(io)); 15651829Smdodd error = aha_probe(sc); 15751829Smdodd if (error) { 15851829Smdodd device_printf(dev, "aha_probe() failed!\n"); 15951829Smdodd goto bad; 16051829Smdodd } 16151829Smdodd 16251829Smdodd error = aha_fetch_adapter_info(sc); 16351829Smdodd if (error) { 16451829Smdodd device_printf(dev, "aha_fetch_adapter_info() failed!\n"); 16551829Smdodd goto bad; 16651829Smdodd } 16751829Smdodd 16851829Smdodd isa_dmacascade(rman_get_start(drq)); 16951829Smdodd 170112782Smdodd error = bus_dma_tag_create( 171112782Smdodd /* parent */ NULL, 172112782Smdodd /* alignemnt */ 1, 173112782Smdodd /* boundary */ 0, 174112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_24BIT, 175112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 176112782Smdodd /* filter */ NULL, 177112782Smdodd /* filterarg */ NULL, 178112782Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_24BIT, 179112782Smdodd /* nsegments */ ~0, 180112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_24BIT, 181112782Smdodd /* flags */ 0, 182117126Sscottl /* lockfunc */ busdma_lock_mutex, 183117126Sscottl /* lockarg */ &Giant, 184112782Smdodd &sc->parent_dmat); 18551829Smdodd if (error) { 18651829Smdodd device_printf(dev, "bus_dma_tag_create() failed!\n"); 18751829Smdodd goto bad; 18851829Smdodd } 18951829Smdodd 19051829Smdodd error = aha_init(sc); 19151829Smdodd if (error) { 19251829Smdodd device_printf(dev, "aha_init() failed\n"); 19351829Smdodd goto bad; 19451829Smdodd } 19551829Smdodd 19651829Smdodd error = aha_attach(sc); 19751829Smdodd if (error) { 19851829Smdodd device_printf(dev, "aha_attach() failed\n"); 19951829Smdodd goto bad; 20051829Smdodd } 20151829Smdodd 20273280Smarkm error = bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, aha_intr, sc, &ih); 20351829Smdodd if (error) { 20451829Smdodd device_printf(dev, "Unable to register interrupt handler\n"); 20551829Smdodd goto bad; 20651829Smdodd } 20751829Smdodd 20851829Smdodd return (0); 20951829Smdodd 21051829Smdoddbad: 21151829Smdodd aha_free(sc); 21251829Smdodd 21351829Smdodd if (io) 21451829Smdodd bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 21551829Smdodd if (irq) 21651829Smdodd bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 21751829Smdodd if (drq) 21851829Smdodd bus_release_resource(dev, SYS_RES_DRQ, 0, drq); 21951829Smdodd 22051829Smdodd return (error); 22151829Smdodd} 22251829Smdodd 22351829Smdoddstatic device_method_t aha_mca_methods[] = { 22451829Smdodd DEVMETHOD(device_probe, aha_mca_probe), 22551829Smdodd DEVMETHOD(device_attach, aha_mca_attach), 22651829Smdodd 22751829Smdodd { 0, 0 } 22851829Smdodd}; 22951829Smdodd 23051829Smdoddstatic driver_t aha_mca_driver = { 23151829Smdodd "aha", 23251829Smdodd aha_mca_methods, 23351829Smdodd 1, 23451829Smdodd/* 23551829Smdodd sizeof(struct aha_softc *), 23651829Smdodd */ 23751829Smdodd}; 23851829Smdodd 23951829Smdoddstatic devclass_t aha_devclass; 24051829Smdodd 24151829SmdoddDRIVER_MODULE(aha, mca, aha_mca_driver, aha_devclass, 0, 0); 242