aha_mca.c revision 119418
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 119418 2003-08-24 17:55:58Z obrien $"); 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 + \ 6151829Smdodd (((u_int32_t)pos & \ 6251829Smdodd AHA_MCA_IOPORT_MASK1) << 8) + \ 6351829Smdodd (((u_int32_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); 8851829Smdodd u_int32_t iobase = 0; 8951829Smdodd u_int32_t iosize = 0; 9051829Smdodd u_int8_t drq = 0; 9151829Smdodd u_int8_t irq = 0; 9251829Smdodd u_int8_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 aha_unit++; 11451829Smdodd 11551829Smdodd return (0); 11651829Smdodd} 11751829Smdodd 11851829Smdoddstatic int 11951829Smdoddaha_mca_attach (device_t dev) 12051829Smdodd{ 12151829Smdodd struct aha_softc * sc = NULL; 12251829Smdodd struct resource * io = NULL; 12351829Smdodd struct resource * irq = NULL; 12451829Smdodd struct resource * drq = NULL; 12551829Smdodd int error = 0; 12651829Smdodd int unit = device_get_unit(dev); 12751829Smdodd int rid; 12851829Smdodd void * ih; 12951829Smdodd 13051829Smdodd rid = 0; 13151829Smdodd io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 13251829Smdodd 0, ~0, 1, RF_ACTIVE); 13351829Smdodd if (!io) { 13451829Smdodd device_printf(dev, "No I/O space?!\n"); 13551829Smdodd error = ENOMEM; 13651829Smdodd goto bad; 13751829Smdodd } 13851829Smdodd 13951829Smdodd rid = 0; 14051829Smdodd irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 14151829Smdodd 0, ~0, 1, RF_ACTIVE); 14251829Smdodd if (irq == NULL) { 14351829Smdodd device_printf(dev, "No IRQ?!\n"); 14451829Smdodd error = ENOMEM; 14551829Smdodd goto bad; 14651829Smdodd } 14751829Smdodd 14851829Smdodd rid = 0; 14951829Smdodd drq = bus_alloc_resource(dev, SYS_RES_DRQ, &rid, 15051829Smdodd 0, ~0, 1, RF_ACTIVE); 15151829Smdodd if (drq == NULL) { 15251829Smdodd device_printf(dev, "No DRQ?!\n"); 15351829Smdodd error = ENOMEM; 15451829Smdodd goto bad; 15551829Smdodd } 15651829Smdodd 15751829Smdodd sc = aha_alloc(unit, rman_get_bustag(io), rman_get_bushandle(io)); 15851829Smdodd if (sc == NULL) { 15951829Smdodd device_printf(dev, "aha_alloc() failed!\n"); 16051829Smdodd error = ENOMEM; 16151829Smdodd goto bad; 16251829Smdodd } 16351829Smdodd 16451829Smdodd error = aha_probe(sc); 16551829Smdodd if (error) { 16651829Smdodd device_printf(dev, "aha_probe() failed!\n"); 16751829Smdodd goto bad; 16851829Smdodd } 16951829Smdodd 17051829Smdodd error = aha_fetch_adapter_info(sc); 17151829Smdodd if (error) { 17251829Smdodd device_printf(dev, "aha_fetch_adapter_info() failed!\n"); 17351829Smdodd goto bad; 17451829Smdodd } 17551829Smdodd 17651829Smdodd isa_dmacascade(rman_get_start(drq)); 17751829Smdodd 178112782Smdodd error = bus_dma_tag_create( 179112782Smdodd /* parent */ NULL, 180112782Smdodd /* alignemnt */ 1, 181112782Smdodd /* boundary */ 0, 182112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_24BIT, 183112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 184112782Smdodd /* filter */ NULL, 185112782Smdodd /* filterarg */ NULL, 186112782Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_24BIT, 187112782Smdodd /* nsegments */ ~0, 188112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_24BIT, 189112782Smdodd /* flags */ 0, 190117126Sscottl /* lockfunc */ busdma_lock_mutex, 191117126Sscottl /* lockarg */ &Giant, 192112782Smdodd &sc->parent_dmat); 19351829Smdodd if (error) { 19451829Smdodd device_printf(dev, "bus_dma_tag_create() failed!\n"); 19551829Smdodd goto bad; 19651829Smdodd } 19751829Smdodd 19851829Smdodd error = aha_init(sc); 19951829Smdodd if (error) { 20051829Smdodd device_printf(dev, "aha_init() failed\n"); 20151829Smdodd goto bad; 20251829Smdodd } 20351829Smdodd 20451829Smdodd error = aha_attach(sc); 20551829Smdodd if (error) { 20651829Smdodd device_printf(dev, "aha_attach() failed\n"); 20751829Smdodd goto bad; 20851829Smdodd } 20951829Smdodd 21073280Smarkm error = bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, aha_intr, sc, &ih); 21151829Smdodd if (error) { 21251829Smdodd device_printf(dev, "Unable to register interrupt handler\n"); 21351829Smdodd goto bad; 21451829Smdodd } 21551829Smdodd 21651829Smdodd return (0); 21751829Smdodd 21851829Smdoddbad: 21951829Smdodd aha_free(sc); 22051829Smdodd 22151829Smdodd if (io) 22251829Smdodd bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 22351829Smdodd if (irq) 22451829Smdodd bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 22551829Smdodd if (drq) 22651829Smdodd bus_release_resource(dev, SYS_RES_DRQ, 0, drq); 22751829Smdodd 22851829Smdodd return (error); 22951829Smdodd} 23051829Smdodd 23151829Smdoddstatic device_method_t aha_mca_methods[] = { 23251829Smdodd DEVMETHOD(device_probe, aha_mca_probe), 23351829Smdodd DEVMETHOD(device_attach, aha_mca_attach), 23451829Smdodd 23551829Smdodd { 0, 0 } 23651829Smdodd}; 23751829Smdodd 23851829Smdoddstatic driver_t aha_mca_driver = { 23951829Smdodd "aha", 24051829Smdodd aha_mca_methods, 24151829Smdodd 1, 24251829Smdodd/* 24351829Smdodd sizeof(struct aha_softc *), 24451829Smdodd */ 24551829Smdodd}; 24651829Smdodd 24751829Smdoddstatic devclass_t aha_devclass; 24851829Smdodd 24951829SmdoddDRIVER_MODULE(aha, mca, aha_mca_driver, aha_devclass, 0, 0); 250