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: releng/10.2/sys/dev/aha/aha_mca.c 241611 2012-10-16 15:25:04Z pluknet $"); 31119418Sobrien 3251829Smdodd#include <sys/types.h> 3351829Smdodd#include <sys/param.h> 34241611Spluknet#include <sys/systm.h> 3551829Smdodd#include <sys/kernel.h> 36117126Sscottl#include <sys/lock.h> 37117126Sscottl#include <sys/mutex.h> 3851829Smdodd 3951829Smdodd#include <sys/module.h> 4051829Smdodd#include <sys/bus.h> 4151829Smdodd#include <machine/bus.h> 4251829Smdodd#include <machine/resource.h> 4351829Smdodd#include <sys/rman.h> 4451829Smdodd 45135260Sphk#include <isa/isavar.h> 4651829Smdodd 4751829Smdodd#include <dev/mca/mca_busreg.h> 4851829Smdodd#include <dev/mca/mca_busvar.h> 4951829Smdodd 5051829Smdodd#include <dev/aha/ahareg.h> 5151829Smdodd 5251829Smdoddstatic struct mca_ident aha_mca_devs[] = { 5351829Smdodd { 0x0f1f, "Adaptec AHA-1640 SCSI Adapter" }, 5451829Smdodd { 0, NULL }, 5551829Smdodd}; 5651829Smdodd 5751829Smdodd#define AHA_MCA_IOPORT_POS MCA_ADP_POS(MCA_POS1) 5851829Smdodd# define AHA_MCA_IOPORT_MASK1 0x07 5951829Smdodd# define AHA_MCA_IOPORT_MASK2 0xc0 6051829Smdodd# define AHA_MCA_IOPORT_SIZE 0x03 6151829Smdodd# define AHA_MCA_IOPORT(pos) (0x30 + \ 62122340Simp (((uint32_t)pos & \ 6351829Smdodd AHA_MCA_IOPORT_MASK1) << 8) + \ 64122340Simp (((uint32_t)pos & \ 6551829Smdodd AHA_MCA_IOPORT_MASK2) >> 4)) 6651829Smdodd 6751829Smdodd#define AHA_MCA_DRQ_POS MCA_ADP_POS(MCA_POS3) 6851829Smdodd# define AHA_MCA_DRQ_MASK 0x0f 6951829Smdodd# define AHA_MCA_DRQ(pos) (pos & AHA_MCA_DRQ_MASK) 7051829Smdodd 7151829Smdodd#define AHA_MCA_IRQ_POS MCA_ADP_POS(MCA_POS2) 7251829Smdodd# define AHA_MCA_IRQ_MASK 0x07 7351829Smdodd# define AHA_MCA_IRQ(pos) ((pos & AHA_MCA_IRQ_MASK) + 8) 7451829Smdodd 7551829Smdodd/* 7651829Smdodd * Not needed as the board knows its config 7751829Smdodd * internally and the ID will be fetched 7851829Smdodd * via AOP_INQUIRE_SETUP_INFO command. 7951829Smdodd */ 8051829Smdodd#define AHA_MCA_SCSIID_POS MCA_ADP_POS(MCA_POS2) 8151829Smdodd#define AHA_MCA_SCSIID_MASK 0xe0 8251829Smdodd#define AHA_MCA_SCSIID(pos) ((pos & AHA_MCA_SCSIID_MASK) >> 5) 8351829Smdodd 8451829Smdoddstatic int 8551829Smdoddaha_mca_probe (device_t dev) 8651829Smdodd{ 8751829Smdodd const char * desc; 8851829Smdodd mca_id_t id = mca_get_id(dev); 89122340Simp uint32_t iobase = 0; 90122340Simp uint32_t iosize = 0; 91140467Simp uint8_t drq = 0; 92140467Simp uint8_t irq = 0; 93140467Simp uint8_t pos; 9451829Smdodd 9551829Smdodd desc = mca_match_id(id, aha_mca_devs); 9651829Smdodd if (!desc) 9751829Smdodd return (ENXIO); 9851829Smdodd device_set_desc(dev, desc); 9951829Smdodd 10051829Smdodd pos = mca_pos_read(dev, AHA_MCA_IOPORT_POS); 10151829Smdodd iobase = AHA_MCA_IOPORT(pos); 10251829Smdodd iosize = AHA_MCA_IOPORT_SIZE; 10351829Smdodd 10451829Smdodd pos = mca_pos_read(dev, AHA_MCA_DRQ_POS); 10551829Smdodd drq = AHA_MCA_DRQ(pos); 10651829Smdodd 10751829Smdodd pos = mca_pos_read(dev, AHA_MCA_IRQ_POS); 10851829Smdodd irq = AHA_MCA_IRQ(pos); 10951829Smdodd 11051829Smdodd mca_add_iospace(dev, iobase, iosize); 11151829Smdodd mca_add_drq(dev, drq); 11251829Smdodd mca_add_irq(dev, irq); 11351829Smdodd 11451829Smdodd return (0); 11551829Smdodd} 11651829Smdodd 11751829Smdoddstatic int 11851829Smdoddaha_mca_attach (device_t dev) 11951829Smdodd{ 120122361Simp struct aha_softc * sc = device_get_softc(dev); 121140467Simp int error = ENOMEM; 12251829Smdodd 123140467Simp sc->portrid = 0; 124140467Simp sc->port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->portrid, 125140467Simp RF_ACTIVE); 126140467Simp if (sc->port == NULL) { 12751829Smdodd device_printf(dev, "No I/O space?!\n"); 12851829Smdodd goto bad; 12951829Smdodd } 13051829Smdodd 131140467Simp sc->irqrid = 0; 132140467Simp sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid, 133140467Simp RF_ACTIVE); 134140467Simp if (sc->irq == NULL) { 13551829Smdodd device_printf(dev, "No IRQ?!\n"); 13651829Smdodd goto bad; 13751829Smdodd } 13851829Smdodd 139140467Simp sc->drqrid = 0; 140140467Simp sc->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &sc->drqrid, 141140467Simp RF_ACTIVE); 142140467Simp if (sc->drq == NULL) { 14351829Smdodd device_printf(dev, "No DRQ?!\n"); 14451829Smdodd goto bad; 14551829Smdodd } 14651829Smdodd 147241589Sjhb aha_alloc(sc); 14851829Smdodd error = aha_probe(sc); 14951829Smdodd if (error) { 15051829Smdodd device_printf(dev, "aha_probe() failed!\n"); 15151829Smdodd goto bad; 15251829Smdodd } 15351829Smdodd 15451829Smdodd error = aha_fetch_adapter_info(sc); 15551829Smdodd if (error) { 15651829Smdodd device_printf(dev, "aha_fetch_adapter_info() failed!\n"); 15751829Smdodd goto bad; 15851829Smdodd } 15951829Smdodd 160140467Simp isa_dmacascade(rman_get_start(sc->drq)); 16151829Smdodd 162112782Smdodd error = bus_dma_tag_create( 163183678Simp /* parent */ bus_get_dma_tag(dev), 164112782Smdodd /* alignemnt */ 1, 165112782Smdodd /* boundary */ 0, 166112782Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_24BIT, 167112782Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 168112782Smdodd /* filter */ NULL, 169112782Smdodd /* filterarg */ NULL, 170112782Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_24BIT, 171112782Smdodd /* nsegments */ ~0, 172112782Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_24BIT, 173112782Smdodd /* flags */ 0, 174241589Sjhb /* lockfunc */ NULL, 175241589Sjhb /* lockarg */ NULL, 176112782Smdodd &sc->parent_dmat); 17751829Smdodd if (error) { 17851829Smdodd device_printf(dev, "bus_dma_tag_create() failed!\n"); 17951829Smdodd goto bad; 18051829Smdodd } 18151829Smdodd 18251829Smdodd error = aha_init(sc); 18351829Smdodd if (error) { 18451829Smdodd device_printf(dev, "aha_init() failed\n"); 18551829Smdodd goto bad; 18651829Smdodd } 18751829Smdodd 18851829Smdodd error = aha_attach(sc); 18951829Smdodd if (error) { 19051829Smdodd device_printf(dev, "aha_attach() failed\n"); 19151829Smdodd goto bad; 19251829Smdodd } 19351829Smdodd 194241589Sjhb error = bus_setup_intr(dev, sc->irq, INTR_TYPE_CAM | INTR_ENTROPY | 195241611Spluknet INTR_MPSAFE, NULL, aha_intr, sc, &sc->ih); 19651829Smdodd if (error) { 19751829Smdodd device_printf(dev, "Unable to register interrupt handler\n"); 198241589Sjhb aha_detach(sc); 19951829Smdodd goto bad; 20051829Smdodd } 20151829Smdodd 20251829Smdodd return (0); 20351829Smdodd 20451829Smdoddbad: 20551829Smdodd aha_free(sc); 206140467Simp bus_free_resource(dev, SYS_RES_IOPORT, sc->port); 207140467Simp bus_free_resource(dev, SYS_RES_IRQ, sc->irq); 208140467Simp bus_free_resource(dev, SYS_RES_DRQ, sc->drq); 20951829Smdodd return (error); 21051829Smdodd} 21151829Smdodd 21251829Smdoddstatic device_method_t aha_mca_methods[] = { 21351829Smdodd DEVMETHOD(device_probe, aha_mca_probe), 21451829Smdodd DEVMETHOD(device_attach, aha_mca_attach), 21551829Smdodd 21651829Smdodd { 0, 0 } 21751829Smdodd}; 21851829Smdodd 21951829Smdoddstatic driver_t aha_mca_driver = { 22051829Smdodd "aha", 22151829Smdodd aha_mca_methods, 22251829Smdodd 1, 22351829Smdodd/* 22451829Smdodd sizeof(struct aha_softc *), 22551829Smdodd */ 22651829Smdodd}; 22751829Smdodd 22851829Smdoddstatic devclass_t aha_devclass; 22951829Smdodd 23051829SmdoddDRIVER_MODULE(aha, mca, aha_mca_driver, aha_devclass, 0, 0); 231165102SmjacobMODULE_DEPEND(aha, mca, 1, 1, 1); 232