Home | History | Annotate | Line # | Download | only in sbus
esp_sbus.c revision 1.51.12.1
      1  1.51.12.1     yamt /*	$NetBSD: esp_sbus.c,v 1.51.12.1 2014/05/22 11:40:35 yamt Exp $	*/
      2        1.1       pk 
      3        1.1       pk /*-
      4        1.1       pk  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
      5        1.1       pk  * All rights reserved.
      6        1.1       pk  *
      7        1.1       pk  * This code is derived from software contributed to The NetBSD Foundation
      8        1.1       pk  * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
      9        1.1       pk  * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
     10        1.1       pk  *
     11        1.1       pk  * Redistribution and use in source and binary forms, with or without
     12        1.1       pk  * modification, are permitted provided that the following conditions
     13        1.1       pk  * are met:
     14        1.1       pk  * 1. Redistributions of source code must retain the above copyright
     15        1.1       pk  *    notice, this list of conditions and the following disclaimer.
     16        1.1       pk  * 2. Redistributions in binary form must reproduce the above copyright
     17        1.1       pk  *    notice, this list of conditions and the following disclaimer in the
     18        1.1       pk  *    documentation and/or other materials provided with the distribution.
     19        1.1       pk  *
     20        1.1       pk  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21        1.1       pk  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22        1.1       pk  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23        1.1       pk  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24        1.1       pk  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25        1.1       pk  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26        1.1       pk  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27        1.1       pk  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28        1.1       pk  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29        1.1       pk  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30        1.1       pk  * POSSIBILITY OF SUCH DAMAGE.
     31        1.1       pk  */
     32       1.17    lukem 
     33       1.17    lukem #include <sys/cdefs.h>
     34  1.51.12.1     yamt __KERNEL_RCSID(0, "$NetBSD: esp_sbus.c,v 1.51.12.1 2014/05/22 11:40:35 yamt Exp $");
     35        1.1       pk 
     36        1.1       pk #include <sys/param.h>
     37        1.1       pk #include <sys/systm.h>
     38        1.1       pk #include <sys/device.h>
     39        1.1       pk #include <sys/buf.h>
     40       1.13   petrov #include <sys/malloc.h>
     41        1.1       pk 
     42        1.1       pk #include <dev/scsipi/scsi_all.h>
     43        1.1       pk #include <dev/scsipi/scsipi_all.h>
     44        1.1       pk #include <dev/scsipi/scsiconf.h>
     45        1.1       pk #include <dev/scsipi/scsi_message.h>
     46        1.1       pk 
     47       1.38       ad #include <sys/bus.h>
     48       1.38       ad #include <sys/intr.h>
     49        1.1       pk #include <machine/autoconf.h>
     50        1.1       pk 
     51        1.1       pk #include <dev/ic/lsi64854reg.h>
     52        1.1       pk #include <dev/ic/lsi64854var.h>
     53        1.1       pk 
     54        1.1       pk #include <dev/ic/ncr53c9xreg.h>
     55        1.1       pk #include <dev/ic/ncr53c9xvar.h>
     56        1.1       pk 
     57        1.1       pk #include <dev/sbus/sbusvar.h>
     58        1.1       pk 
     59       1.37   martin #include "opt_ddb.h"
     60       1.37   martin 
     61       1.13   petrov /* #define ESP_SBUS_DEBUG */
     62       1.13   petrov 
     63        1.1       pk struct esp_softc {
     64        1.1       pk 	struct ncr53c9x_softc sc_ncr53c9x;	/* glue to MI code */
     65        1.1       pk 
     66        1.1       pk 	bus_space_tag_t	sc_bustag;
     67        1.1       pk 	bus_dma_tag_t	sc_dmatag;
     68        1.1       pk 
     69        1.1       pk 	bus_space_handle_t sc_reg;		/* the registers */
     70        1.1       pk 	struct lsi64854_softc *sc_dma;		/* pointer to my dma */
     71        1.1       pk 
     72        1.1       pk 	int	sc_pri;				/* SBUS priority */
     73        1.1       pk };
     74        1.1       pk 
     75       1.44  tsutsui int	espmatch_sbus(device_t, cfdata_t, void *);
     76       1.44  tsutsui void	espattach_sbus(device_t, device_t, void *);
     77       1.44  tsutsui void	espattach_dma(device_t, device_t, void *);
     78        1.1       pk 
     79       1.44  tsutsui static void	espattach(struct esp_softc *, struct ncr53c9x_glue *);
     80        1.1       pk 
     81       1.44  tsutsui CFATTACH_DECL_NEW(esp_sbus, sizeof(struct esp_softc),
     82       1.26  thorpej     espmatch_sbus, espattach_sbus, NULL, NULL);
     83       1.25  thorpej 
     84       1.44  tsutsui CFATTACH_DECL_NEW(esp_dma, sizeof(struct esp_softc),
     85       1.26  thorpej     espmatch_sbus, espattach_dma, NULL, NULL);
     86        1.1       pk 
     87        1.1       pk /*
     88        1.1       pk  * Functions and the switch for the MI code.
     89        1.1       pk  */
     90       1.44  tsutsui static uint8_t	esp_read_reg(struct ncr53c9x_softc *, int);
     91       1.44  tsutsui static void	esp_write_reg(struct ncr53c9x_softc *, int, uint8_t);
     92       1.44  tsutsui static uint8_t	esp_rdreg1(struct ncr53c9x_softc *, int);
     93       1.44  tsutsui static void	esp_wrreg1(struct ncr53c9x_softc *, int, uint8_t);
     94       1.30    perry static int	esp_dma_isintr(struct ncr53c9x_softc *);
     95       1.30    perry static void	esp_dma_reset(struct ncr53c9x_softc *);
     96       1.30    perry static int	esp_dma_intr(struct ncr53c9x_softc *);
     97       1.44  tsutsui static int	esp_dma_setup(struct ncr53c9x_softc *, uint8_t **,
     98       1.30    perry 				    size_t *, int, size_t *);
     99       1.30    perry static void	esp_dma_go(struct ncr53c9x_softc *);
    100       1.30    perry static void	esp_dma_stop(struct ncr53c9x_softc *);
    101       1.30    perry static int	esp_dma_isactive(struct ncr53c9x_softc *);
    102        1.1       pk 
    103       1.37   martin #ifdef DDB
    104       1.37   martin static void	esp_init_ddb_cmds(void);
    105       1.37   martin #endif
    106       1.37   martin 
    107        1.1       pk static struct ncr53c9x_glue esp_sbus_glue = {
    108        1.1       pk 	esp_read_reg,
    109        1.1       pk 	esp_write_reg,
    110        1.1       pk 	esp_dma_isintr,
    111        1.1       pk 	esp_dma_reset,
    112        1.1       pk 	esp_dma_intr,
    113        1.1       pk 	esp_dma_setup,
    114        1.1       pk 	esp_dma_go,
    115        1.1       pk 	esp_dma_stop,
    116        1.1       pk 	esp_dma_isactive,
    117        1.1       pk 	NULL,			/* gl_clear_latched_intr */
    118        1.1       pk };
    119        1.1       pk 
    120        1.6   mjacob static struct ncr53c9x_glue esp_sbus_glue1 = {
    121        1.6   mjacob 	esp_rdreg1,
    122        1.6   mjacob 	esp_wrreg1,
    123        1.6   mjacob 	esp_dma_isintr,
    124        1.6   mjacob 	esp_dma_reset,
    125        1.6   mjacob 	esp_dma_intr,
    126        1.6   mjacob 	esp_dma_setup,
    127        1.6   mjacob 	esp_dma_go,
    128        1.6   mjacob 	esp_dma_stop,
    129        1.6   mjacob 	esp_dma_isactive,
    130        1.6   mjacob 	NULL,			/* gl_clear_latched_intr */
    131        1.6   mjacob };
    132        1.6   mjacob 
    133        1.1       pk int
    134       1.48   cegger espmatch_sbus(device_t parent, cfdata_t cf, void *aux)
    135        1.1       pk {
    136        1.6   mjacob 	int rv;
    137        1.1       pk 	struct sbus_attach_args *sa = aux;
    138        1.1       pk 
    139       1.13   petrov 	if (strcmp("SUNW,fas", sa->sa_name) == 0)
    140       1.13   petrov 	        return 1;
    141       1.13   petrov 
    142       1.23  thorpej 	rv = (strcmp(cf->cf_name, sa->sa_name) == 0 ||
    143        1.6   mjacob 	    strcmp("ptscII", sa->sa_name) == 0);
    144       1.44  tsutsui 	return rv;
    145        1.1       pk }
    146        1.1       pk 
    147        1.1       pk void
    148       1.44  tsutsui espattach_sbus(device_t parent, device_t self, void *aux)
    149        1.1       pk {
    150       1.44  tsutsui 	struct esp_softc *esc = device_private(self);
    151        1.1       pk 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
    152       1.44  tsutsui 	struct sbus_softc *sbsc = device_private(parent);
    153        1.1       pk 	struct sbus_attach_args *sa = aux;
    154       1.13   petrov 	struct lsi64854_softc *lsc;
    155       1.44  tsutsui 	device_t dma_dev;
    156       1.13   petrov 	int burst, sbusburst;
    157        1.1       pk 
    158       1.44  tsutsui 	sc->sc_dev = self;
    159       1.44  tsutsui 
    160       1.37   martin #ifdef DDB
    161       1.37   martin 	esp_init_ddb_cmds();
    162       1.37   martin #endif
    163       1.37   martin 
    164        1.1       pk 	esc->sc_bustag = sa->sa_bustag;
    165        1.1       pk 	esc->sc_dmatag = sa->sa_dmatag;
    166        1.1       pk 
    167       1.29       pk 	sc->sc_id = prom_getpropint(sa->sa_node, "initiator-id", 7);
    168       1.29       pk 	sc->sc_freq = prom_getpropint(sa->sa_node, "clock-frequency", -1);
    169        1.1       pk 	if (sc->sc_freq < 0)
    170       1.44  tsutsui 		sc->sc_freq = sbsc->sc_clockfreq;
    171        1.1       pk 
    172       1.13   petrov #ifdef ESP_SBUS_DEBUG
    173       1.44  tsutsui 	aprint_normal("\n");
    174       1.44  tsutsui 	aprint_normal_dev(self, "%s: sc_id %d, freq %d\n",
    175       1.44  tsutsui 	    __func__, sc->sc_id, sc->sc_freq);
    176       1.44  tsutsui 	aprint_normal("%s", device_xname(self));
    177       1.13   petrov #endif
    178       1.13   petrov 
    179       1.13   petrov 	if (strcmp("SUNW,fas", sa->sa_name) == 0) {
    180       1.13   petrov 
    181       1.13   petrov 		/*
    182       1.44  tsutsui 		 * fas has 2 register spaces: dma(lsi64854) and
    183       1.44  tsutsui 		 *                            SCSI core (ncr53c9x)
    184       1.13   petrov 		 */
    185       1.13   petrov 		if (sa->sa_nreg != 2) {
    186       1.44  tsutsui 			aprint_error(": %d register spaces\n", sa->sa_nreg);
    187       1.13   petrov 			return;
    188       1.13   petrov 		}
    189       1.13   petrov 
    190       1.13   petrov 		/*
    191       1.13   petrov 		 * allocate space for dma, in SUNW,fas there are no separate
    192       1.13   petrov 		 * dma device
    193       1.13   petrov 		 */
    194       1.44  tsutsui 		lsc = malloc(sizeof(struct lsi64854_softc), M_DEVBUF, M_NOWAIT);
    195       1.13   petrov 
    196       1.13   petrov 		if (lsc == NULL) {
    197       1.44  tsutsui 			aprint_error(": out of memory (lsi64854_softc)\n");
    198       1.13   petrov 			return;
    199       1.13   petrov 		}
    200       1.45  tsutsui 		lsc->sc_dev = malloc(sizeof(struct device), M_DEVBUF,
    201       1.45  tsutsui 		    M_NOWAIT | M_ZERO);
    202       1.45  tsutsui 		if (lsc->sc_dev == NULL) {
    203       1.45  tsutsui 			aprint_error(": out of memory (device_t)\n");
    204       1.45  tsutsui 			free(lsc, M_DEVBUF);
    205       1.45  tsutsui 			return;
    206       1.45  tsutsui 		}
    207       1.13   petrov 		esc->sc_dma = lsc;
    208       1.13   petrov 
    209       1.13   petrov 		lsc->sc_bustag = sa->sa_bustag;
    210       1.13   petrov 		lsc->sc_dmatag = sa->sa_dmatag;
    211       1.13   petrov 
    212       1.44  tsutsui 		strlcpy(lsc->sc_dev->dv_xname, device_xname(sc->sc_dev),
    213       1.44  tsutsui 		    sizeof(lsc->sc_dev->dv_xname));
    214       1.13   petrov 
    215       1.13   petrov 		/* Map dma registers */
    216       1.20      eeh 		if (sa->sa_npromvaddrs) {
    217       1.20      eeh 			sbus_promaddr_to_handle(sa->sa_bustag,
    218       1.44  tsutsui 			    sa->sa_promvaddrs[0], &lsc->sc_regs);
    219       1.20      eeh 		} else {
    220       1.20      eeh 			if (sbus_bus_map(sa->sa_bustag,
    221       1.44  tsutsui 			    sa->sa_reg[0].oa_space,
    222       1.44  tsutsui 			    sa->sa_reg[0].oa_base,
    223       1.44  tsutsui 			    sa->sa_reg[0].oa_size,
    224       1.44  tsutsui 			    0, &lsc->sc_regs) != 0) {
    225       1.44  tsutsui 				aprint_error(": cannot map dma registers\n");
    226       1.20      eeh 				return;
    227       1.20      eeh 			}
    228       1.13   petrov 		}
    229       1.13   petrov 
    230       1.13   petrov 		/*
    231       1.13   petrov 		 * XXX is this common(from bpp.c), the same in dma_sbus...etc.
    232       1.13   petrov 		 *
    233       1.13   petrov 		 * Get transfer burst size from PROM and plug it into the
    234       1.13   petrov 		 * controller registers. This is needed on the Sun4m; do
    235       1.13   petrov 		 * others need it too?
    236       1.13   petrov 		 */
    237       1.44  tsutsui 		sbusburst = sbsc->sc_burst;
    238       1.13   petrov 		if (sbusburst == 0)
    239       1.13   petrov 			sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
    240       1.13   petrov 
    241       1.29       pk 		burst = prom_getpropint(sa->sa_node, "burst-sizes", -1);
    242       1.13   petrov 
    243       1.13   petrov #if ESP_SBUS_DEBUG
    244       1.44  tsutsui 		aprint_normal("%s: burst 0x%x, sbus 0x%x\n",
    245       1.44  tsutsui 		    __func__, burst, sbusburst);
    246       1.44  tsutsui 		aprint_normal("%s", device_xname(self));
    247       1.13   petrov #endif
    248       1.13   petrov 
    249       1.13   petrov 		if (burst == -1)
    250       1.13   petrov 			/* take SBus burst sizes */
    251       1.13   petrov 			burst = sbusburst;
    252       1.13   petrov 
    253       1.13   petrov 		/* Clamp at parent's burst sizes */
    254       1.13   petrov 		burst &= sbusburst;
    255       1.13   petrov 		lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
    256       1.13   petrov 		    (burst & SBUS_BURST_16) ? 16 : 0;
    257       1.13   petrov 
    258       1.13   petrov 		lsc->sc_channel = L64854_CHANNEL_SCSI;
    259       1.13   petrov 		lsc->sc_client = sc;
    260       1.13   petrov 
    261       1.13   petrov 		lsi64854_attach(lsc);
    262       1.13   petrov 
    263       1.13   petrov 		/*
    264       1.13   petrov 		 * map SCSI core registers
    265       1.13   petrov 		 */
    266       1.20      eeh 		if (sa->sa_npromvaddrs > 1) {
    267       1.20      eeh 			sbus_promaddr_to_handle(sa->sa_bustag,
    268       1.44  tsutsui 			    sa->sa_promvaddrs[1], &esc->sc_reg);
    269       1.20      eeh 		} else {
    270       1.20      eeh 			if (sbus_bus_map(sa->sa_bustag,
    271       1.44  tsutsui 			    sa->sa_reg[1].oa_space,
    272       1.44  tsutsui 			    sa->sa_reg[1].oa_base,
    273       1.44  tsutsui 			    sa->sa_reg[1].oa_size,
    274       1.44  tsutsui 			    0, &esc->sc_reg) != 0) {
    275       1.44  tsutsui 				aprint_error(": cannot map "
    276       1.44  tsutsui 				    "scsi core registers\n");
    277       1.20      eeh 				return;
    278       1.20      eeh 			}
    279       1.13   petrov 		}
    280       1.13   petrov 
    281       1.13   petrov 		if (sa->sa_nintr == 0) {
    282       1.44  tsutsui 			aprint_error(": no interrupt property\n");
    283       1.13   petrov 			return;
    284       1.13   petrov 		}
    285       1.13   petrov 
    286       1.13   petrov 		esc->sc_pri = sa->sa_pri;
    287       1.13   petrov 
    288       1.13   petrov 		espattach(esc, &esp_sbus_glue);
    289       1.13   petrov 
    290       1.13   petrov 		return;
    291       1.13   petrov 	}
    292       1.13   petrov 
    293        1.1       pk 	/*
    294        1.1       pk 	 * Find the DMA by poking around the dma device structures
    295        1.1       pk 	 *
    296        1.1       pk 	 * What happens here is that if the dma driver has not been
    297        1.1       pk 	 * configured, then this returns a NULL pointer. Then when the
    298        1.1       pk 	 * dma actually gets configured, it does the opposing test, and
    299        1.1       pk 	 * if the sc->sc_esp field in it's softc is NULL, then tries to
    300        1.1       pk 	 * find the matching esp driver.
    301        1.1       pk 	 */
    302       1.39    joerg 	dma_dev = device_find_by_driver_unit("dma", device_unit(self));
    303       1.42   mjacob 	if (dma_dev == NULL) {
    304       1.44  tsutsui 		aprint_error(": no corresponding DMA device\n");
    305       1.42   mjacob 		return;
    306       1.42   mjacob 	}
    307       1.39    joerg 	esc->sc_dma = device_private(dma_dev);
    308       1.39    joerg 	esc->sc_dma->sc_client = sc;
    309       1.15       pk 
    310       1.15       pk 	/*
    311       1.15       pk 	 * The `ESC' DMA chip must be reset before we can access
    312       1.15       pk 	 * the esp registers.
    313       1.15       pk 	 */
    314       1.15       pk 	if (esc->sc_dma->sc_rev == DMAREV_ESC)
    315       1.15       pk 		DMA_RESET(esc->sc_dma);
    316        1.1       pk 
    317        1.1       pk 	/*
    318        1.1       pk 	 * Map my registers in, if they aren't already in virtual
    319        1.1       pk 	 * address space.
    320        1.1       pk 	 */
    321       1.20      eeh 	if (sa->sa_npromvaddrs) {
    322       1.20      eeh 		sbus_promaddr_to_handle(sa->sa_bustag,
    323       1.44  tsutsui 		    sa->sa_promvaddrs[0], &esc->sc_reg);
    324       1.20      eeh 	} else {
    325       1.19       pk 		if (sbus_bus_map(sa->sa_bustag,
    326       1.44  tsutsui 		    sa->sa_slot, sa->sa_offset, sa->sa_size,
    327       1.44  tsutsui 		    0, &esc->sc_reg) != 0) {
    328       1.44  tsutsui 			aprint_error(": cannot map registers\n");
    329        1.1       pk 			return;
    330        1.1       pk 		}
    331        1.1       pk 	}
    332        1.1       pk 
    333        1.7       pk 	if (sa->sa_nintr == 0) {
    334        1.7       pk 		/*
    335        1.7       pk 		 * No interrupt properties: we quit; this might
    336        1.7       pk 		 * happen on e.g. a Sparc X terminal.
    337        1.7       pk 		 */
    338       1.44  tsutsui 		aprint_error(": no interrupt property\n");
    339        1.7       pk 		return;
    340        1.7       pk 	}
    341        1.7       pk 
    342        1.1       pk 	esc->sc_pri = sa->sa_pri;
    343        1.1       pk 
    344        1.6   mjacob 	if (strcmp("ptscII", sa->sa_name) == 0) {
    345        1.6   mjacob 		espattach(esc, &esp_sbus_glue1);
    346        1.6   mjacob 	} else {
    347        1.6   mjacob 		espattach(esc, &esp_sbus_glue);
    348        1.6   mjacob 	}
    349        1.1       pk }
    350        1.1       pk 
    351        1.1       pk void
    352       1.44  tsutsui espattach_dma(device_t parent, device_t self, void *aux)
    353        1.1       pk {
    354       1.44  tsutsui 	struct esp_softc *esc = device_private(self);
    355        1.1       pk 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
    356        1.1       pk 	struct sbus_attach_args *sa = aux;
    357        1.1       pk 
    358        1.6   mjacob 	if (strcmp("ptscII", sa->sa_name) == 0) {
    359        1.6   mjacob 		return;
    360        1.6   mjacob 	}
    361        1.6   mjacob 
    362       1.44  tsutsui 	sc->sc_dev = self;
    363       1.44  tsutsui 
    364        1.1       pk 	esc->sc_bustag = sa->sa_bustag;
    365        1.1       pk 	esc->sc_dmatag = sa->sa_dmatag;
    366        1.1       pk 
    367       1.29       pk 	sc->sc_id = prom_getpropint(sa->sa_node, "initiator-id", 7);
    368       1.29       pk 	sc->sc_freq = prom_getpropint(sa->sa_node, "clock-frequency", -1);
    369        1.1       pk 
    370       1.44  tsutsui 	esc->sc_dma = device_private(parent);
    371        1.2       pk 	esc->sc_dma->sc_client = sc;
    372        1.1       pk 
    373        1.1       pk 	/*
    374        1.1       pk 	 * Map my registers in, if they aren't already in virtual
    375        1.1       pk 	 * address space.
    376        1.1       pk 	 */
    377       1.20      eeh 	if (sa->sa_npromvaddrs) {
    378       1.20      eeh 		sbus_promaddr_to_handle(sa->sa_bustag,
    379       1.44  tsutsui 		    sa->sa_promvaddrs[0], &esc->sc_reg);
    380       1.20      eeh 	} else {
    381       1.19       pk 		if (sbus_bus_map(sa->sa_bustag,
    382       1.44  tsutsui 		    sa->sa_slot, sa->sa_offset, sa->sa_size,
    383       1.44  tsutsui 		    0, &esc->sc_reg) != 0) {
    384       1.44  tsutsui 			aprint_error(": cannot map registers\n");
    385        1.1       pk 			return;
    386        1.1       pk 		}
    387        1.1       pk 	}
    388        1.1       pk 
    389        1.7       pk 	if (sa->sa_nintr == 0) {
    390        1.7       pk 		/*
    391        1.7       pk 		 * No interrupt properties: we quit; this might
    392        1.7       pk 		 * happen on e.g. a Sparc X terminal.
    393        1.7       pk 		 */
    394       1.44  tsutsui 		aprint_error(": no interrupt property\n");
    395        1.7       pk 		return;
    396        1.7       pk 	}
    397        1.7       pk 
    398        1.1       pk 	esc->sc_pri = sa->sa_pri;
    399        1.1       pk 
    400        1.6   mjacob 	espattach(esc, &esp_sbus_glue);
    401        1.1       pk }
    402        1.1       pk 
    403        1.1       pk 
    404        1.1       pk /*
    405        1.1       pk  * Attach this instance, and then all the sub-devices
    406        1.1       pk  */
    407        1.1       pk void
    408       1.44  tsutsui espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
    409        1.1       pk {
    410        1.1       pk 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
    411       1.13   petrov 	unsigned int uid = 0;
    412        1.1       pk 
    413        1.1       pk 	/*
    414        1.1       pk 	 * Set up glue for MI code early; we use some of it here.
    415        1.1       pk 	 */
    416        1.6   mjacob 	sc->sc_glue = gluep;
    417        1.1       pk 
    418       1.28  tsutsui 	/* gimme MHz */
    419        1.1       pk 	sc->sc_freq /= 1000000;
    420        1.1       pk 
    421        1.1       pk 	/*
    422        1.1       pk 	 * XXX More of this should be in ncr53c9x_attach(), but
    423        1.1       pk 	 * XXX should we really poke around the chip that much in
    424        1.1       pk 	 * XXX the MI code?  Think about this more...
    425        1.1       pk 	 */
    426        1.1       pk 
    427        1.1       pk 	/*
    428        1.1       pk 	 * It is necessary to try to load the 2nd config register here,
    429        1.1       pk 	 * to find out what rev the esp chip is, else the ncr53c9x_reset
    430        1.1       pk 	 * will not set up the defaults correctly.
    431        1.1       pk 	 */
    432        1.1       pk 	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
    433        1.1       pk 	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
    434       1.13   petrov 	sc->sc_cfg3 = NCRCFG3_CDB;
    435        1.1       pk 	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
    436        1.1       pk 
    437        1.1       pk 	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
    438        1.1       pk 	    (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
    439        1.1       pk 		sc->sc_rev = NCR_VARIANT_ESP100;
    440        1.1       pk 	} else {
    441        1.1       pk 		sc->sc_cfg2 = NCRCFG2_SCSI2;
    442        1.1       pk 		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
    443        1.1       pk 		sc->sc_cfg3 = 0;
    444        1.1       pk 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
    445       1.13   petrov 		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
    446        1.1       pk 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
    447        1.1       pk 		if (NCR_READ_REG(sc, NCR_CFG3) !=
    448        1.1       pk 		    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
    449        1.1       pk 			sc->sc_rev = NCR_VARIANT_ESP100A;
    450        1.1       pk 		} else {
    451        1.1       pk 			/* NCRCFG2_FE enables > 64K transfers */
    452        1.1       pk 			sc->sc_cfg2 |= NCRCFG2_FE;
    453       1.13   petrov 			sc->sc_cfg3 = 0;
    454        1.1       pk 			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
    455        1.1       pk 			sc->sc_rev = NCR_VARIANT_ESP200;
    456       1.13   petrov 
    457       1.44  tsutsui 			/*
    458       1.44  tsutsui 			 * XXX spec says it's valid after power up or
    459       1.44  tsutsui 			 * chip reset
    460       1.44  tsutsui 			 */
    461       1.13   petrov 			uid = NCR_READ_REG(sc, NCR_UID);
    462       1.13   petrov 			if (((uid & 0xf8) >> 3) == 0x0a) /* XXX */
    463       1.13   petrov 				sc->sc_rev = NCR_VARIANT_FAS366;
    464        1.1       pk 		}
    465        1.1       pk 	}
    466        1.1       pk 
    467       1.13   petrov #ifdef ESP_SBUS_DEBUG
    468       1.44  tsutsui 	aprint_debug("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid);
    469       1.44  tsutsui 	aprint_normal("%s", device_xname(sc->sc_dev));
    470       1.13   petrov #endif
    471       1.13   petrov 
    472        1.1       pk 	/*
    473        1.1       pk 	 * XXX minsync and maxxfer _should_ be set up in MI code,
    474        1.1       pk 	 * XXX but it appears to have some dependency on what sort
    475        1.1       pk 	 * XXX of DMA we're hooked up to, etc.
    476        1.1       pk 	 */
    477        1.1       pk 
    478        1.1       pk 	/*
    479        1.1       pk 	 * This is the value used to start sync negotiations
    480        1.1       pk 	 * Note that the NCR register "SYNCTP" is programmed
    481        1.1       pk 	 * in "clocks per byte", and has a minimum value of 4.
    482        1.1       pk 	 * The SCSI period used in negotiation is one-fourth
    483        1.1       pk 	 * of the time (in nanoseconds) needed to transfer one byte.
    484        1.1       pk 	 * Since the chip's clock is given in MHz, we have the following
    485        1.1       pk 	 * formula: 4 * period = (1000 / freq) * 4
    486        1.1       pk 	 */
    487        1.1       pk 	sc->sc_minsync = 1000 / sc->sc_freq;
    488        1.1       pk 
    489        1.1       pk 	/*
    490        1.1       pk 	 * Alas, we must now modify the value a bit, because it's
    491       1.31    perry 	 * only valid when can switch on FASTCLK and FASTSCSI bits
    492       1.31    perry 	 * in config register 3...
    493        1.1       pk 	 */
    494        1.1       pk 	switch (sc->sc_rev) {
    495        1.1       pk 	case NCR_VARIANT_ESP100:
    496        1.1       pk 		sc->sc_maxxfer = 64 * 1024;
    497        1.1       pk 		sc->sc_minsync = 0;	/* No synch on old chip? */
    498        1.1       pk 		break;
    499        1.1       pk 
    500        1.1       pk 	case NCR_VARIANT_ESP100A:
    501        1.1       pk 		sc->sc_maxxfer = 64 * 1024;
    502        1.1       pk 		/* Min clocks/byte is 5 */
    503        1.1       pk 		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
    504        1.1       pk 		break;
    505        1.1       pk 
    506        1.1       pk 	case NCR_VARIANT_ESP200:
    507       1.13   petrov 	case NCR_VARIANT_FAS366:
    508        1.1       pk 		sc->sc_maxxfer = 16 * 1024 * 1024;
    509        1.1       pk 		/* XXX - do actually set FAST* bits */
    510        1.1       pk 		break;
    511        1.1       pk 	}
    512        1.1       pk 
    513        1.1       pk 	/* Establish interrupt channel */
    514  1.51.12.1     yamt 	bus_intr_establish(esc->sc_bustag, esc->sc_pri, IPL_BIO,
    515       1.44  tsutsui 	    ncr53c9x_intr, sc);
    516        1.1       pk 
    517        1.1       pk 	/* register interrupt stats */
    518        1.9      cgd 	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
    519       1.44  tsutsui 	    device_xname(sc->sc_dev), "intr");
    520        1.1       pk 
    521       1.13   petrov 	/* Turn on target selection using the `dma' method */
    522       1.13   petrov 	if (sc->sc_rev != NCR_VARIANT_FAS366)
    523       1.13   petrov 		sc->sc_features |= NCR_F_DMASELECT;
    524       1.13   petrov 
    525        1.1       pk 	/* Do the common parts of attachment. */
    526       1.14   bouyer 	sc->sc_adapter.adapt_minphys = minphys;
    527       1.14   bouyer 	sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
    528       1.14   bouyer 	ncr53c9x_attach(sc);
    529        1.1       pk }
    530        1.1       pk 
    531        1.1       pk /*
    532        1.1       pk  * Glue functions.
    533        1.1       pk  */
    534        1.1       pk 
    535       1.13   petrov #ifdef ESP_SBUS_DEBUG
    536       1.13   petrov int esp_sbus_debug = 0;
    537       1.13   petrov 
    538       1.13   petrov static struct {
    539       1.13   petrov 	char *r_name;
    540       1.31    perry 	int   r_flag;
    541       1.13   petrov } esp__read_regnames [] = {
    542       1.13   petrov 	{ "TCL", 0},			/* 0/00 */
    543       1.13   petrov 	{ "TCM", 0},			/* 1/04 */
    544       1.13   petrov 	{ "FIFO", 0},			/* 2/08 */
    545       1.13   petrov 	{ "CMD", 0},			/* 3/0c */
    546       1.13   petrov 	{ "STAT", 0},			/* 4/10 */
    547       1.13   petrov 	{ "INTR", 0},			/* 5/14 */
    548       1.13   petrov 	{ "STEP", 0},			/* 6/18 */
    549       1.13   petrov 	{ "FFLAGS", 1},			/* 7/1c */
    550       1.13   petrov 	{ "CFG1", 1},			/* 8/20 */
    551       1.13   petrov 	{ "STAT2", 0},			/* 9/24 */
    552       1.13   petrov 	{ "CFG4", 1},			/* a/28 */
    553       1.13   petrov 	{ "CFG2", 1},			/* b/2c */
    554       1.13   petrov 	{ "CFG3", 1},			/* c/30 */
    555       1.13   petrov 	{ "-none", 1},			/* d/34 */
    556       1.13   petrov 	{ "TCH", 1},			/* e/38 */
    557       1.13   petrov 	{ "TCX", 1},			/* f/3c */
    558       1.13   petrov };
    559       1.13   petrov 
    560       1.13   petrov static struct {
    561       1.13   petrov 	char *r_name;
    562       1.13   petrov 	int   r_flag;
    563       1.13   petrov } esp__write_regnames[] = {
    564       1.13   petrov 	{ "TCL", 1},			/* 0/00 */
    565       1.13   petrov 	{ "TCM", 1},			/* 1/04 */
    566       1.13   petrov 	{ "FIFO", 0},			/* 2/08 */
    567       1.13   petrov 	{ "CMD", 0},			/* 3/0c */
    568       1.13   petrov 	{ "SELID", 1},			/* 4/10 */
    569       1.13   petrov 	{ "TIMEOUT", 1},		/* 5/14 */
    570       1.13   petrov 	{ "SYNCTP", 1},			/* 6/18 */
    571       1.13   petrov 	{ "SYNCOFF", 1},		/* 7/1c */
    572       1.13   petrov 	{ "CFG1", 1},			/* 8/20 */
    573       1.13   petrov 	{ "CCF", 1},			/* 9/24 */
    574       1.13   petrov 	{ "TEST", 1},			/* a/28 */
    575       1.13   petrov 	{ "CFG2", 1},			/* b/2c */
    576       1.13   petrov 	{ "CFG3", 1},			/* c/30 */
    577       1.13   petrov 	{ "-none", 1},			/* d/34 */
    578       1.13   petrov 	{ "TCH", 1},			/* e/38 */
    579       1.13   petrov 	{ "TCX", 1},			/* f/3c */
    580       1.13   petrov };
    581       1.13   petrov #endif
    582       1.13   petrov 
    583       1.44  tsutsui uint8_t
    584       1.44  tsutsui esp_read_reg(struct ncr53c9x_softc *sc, int reg)
    585        1.1       pk {
    586        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    587       1.44  tsutsui 	uint8_t v;
    588        1.1       pk 
    589       1.13   petrov 	v = bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4);
    590       1.13   petrov #ifdef ESP_SBUS_DEBUG
    591       1.13   petrov 	if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
    592       1.13   petrov 		printf("RD:%x <%s> %x\n", reg * 4,
    593       1.44  tsutsui 		    ((unsigned int)reg < 0x10) ?
    594       1.44  tsutsui 		    esp__read_regnames[reg].r_name : "<***>", v);
    595       1.13   petrov #endif
    596       1.13   petrov 	return v;
    597        1.1       pk }
    598        1.1       pk 
    599        1.1       pk void
    600       1.44  tsutsui esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v)
    601        1.1       pk {
    602        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    603        1.1       pk 
    604       1.13   petrov #ifdef ESP_SBUS_DEBUG
    605       1.13   petrov 	if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
    606       1.13   petrov 		printf("WR:%x <%s> %x\n", reg * 4,
    607       1.44  tsutsui 		    ((unsigned int)reg < 0x10) ?
    608       1.44  tsutsui 		    esp__write_regnames[reg].r_name : "<***>", v);
    609       1.13   petrov #endif
    610        1.1       pk 	bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v);
    611        1.6   mjacob }
    612        1.6   mjacob 
    613       1.44  tsutsui uint8_t
    614       1.44  tsutsui esp_rdreg1(struct ncr53c9x_softc *sc, int reg)
    615        1.6   mjacob {
    616        1.6   mjacob 	struct esp_softc *esc = (struct esp_softc *)sc;
    617        1.6   mjacob 
    618       1.44  tsutsui 	return bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg);
    619        1.6   mjacob }
    620        1.6   mjacob 
    621        1.6   mjacob void
    622       1.44  tsutsui esp_wrreg1(struct ncr53c9x_softc *sc, int reg, uint8_t v)
    623        1.6   mjacob {
    624        1.6   mjacob 	struct esp_softc *esc = (struct esp_softc *)sc;
    625        1.6   mjacob 
    626        1.6   mjacob 	bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg, v);
    627        1.1       pk }
    628        1.1       pk 
    629        1.1       pk int
    630       1.44  tsutsui esp_dma_isintr(struct ncr53c9x_softc *sc)
    631        1.1       pk {
    632        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    633        1.1       pk 
    634       1.44  tsutsui 	return DMA_ISINTR(esc->sc_dma);
    635        1.1       pk }
    636        1.1       pk 
    637        1.1       pk void
    638       1.44  tsutsui esp_dma_reset(struct ncr53c9x_softc *sc)
    639        1.1       pk {
    640        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    641        1.1       pk 
    642        1.1       pk 	DMA_RESET(esc->sc_dma);
    643        1.1       pk }
    644        1.1       pk 
    645        1.1       pk int
    646       1.44  tsutsui esp_dma_intr(struct ncr53c9x_softc *sc)
    647        1.1       pk {
    648        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    649        1.1       pk 
    650       1.44  tsutsui 	return DMA_INTR(esc->sc_dma);
    651        1.1       pk }
    652        1.1       pk 
    653        1.1       pk int
    654       1.44  tsutsui esp_dma_setup(struct ncr53c9x_softc *sc, uint8_t **addr, size_t *len,
    655       1.44  tsutsui     int datain, size_t *dmasize)
    656        1.1       pk {
    657        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    658        1.1       pk 
    659       1.44  tsutsui 	return DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize);
    660        1.1       pk }
    661        1.1       pk 
    662        1.1       pk void
    663       1.44  tsutsui esp_dma_go(struct ncr53c9x_softc *sc)
    664        1.1       pk {
    665        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    666        1.1       pk 
    667        1.1       pk 	DMA_GO(esc->sc_dma);
    668        1.1       pk }
    669        1.1       pk 
    670        1.1       pk void
    671       1.44  tsutsui esp_dma_stop(struct ncr53c9x_softc *sc)
    672        1.1       pk {
    673        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    674       1.44  tsutsui 	uint32_t csr;
    675        1.1       pk 
    676        1.1       pk 	csr = L64854_GCSR(esc->sc_dma);
    677        1.1       pk 	csr &= ~D_EN_DMA;
    678        1.1       pk 	L64854_SCSR(esc->sc_dma, csr);
    679        1.1       pk }
    680        1.1       pk 
    681        1.1       pk int
    682       1.44  tsutsui esp_dma_isactive(struct ncr53c9x_softc *sc)
    683        1.1       pk {
    684        1.1       pk 	struct esp_softc *esc = (struct esp_softc *)sc;
    685        1.1       pk 
    686       1.44  tsutsui 	return DMA_ISACTIVE(esc->sc_dma);
    687        1.1       pk }
    688       1.12      eeh 
    689       1.12      eeh #ifdef DDB
    690       1.12      eeh #include <machine/db_machdep.h>
    691       1.12      eeh #include <ddb/db_output.h>
    692       1.37   martin #include <ddb/db_command.h>
    693       1.37   martin 
    694       1.37   martin void db_esp(db_expr_t, bool, db_expr_t, const char*);
    695       1.37   martin 
    696       1.37   martin const struct db_command db_esp_command_table[] = {
    697       1.37   martin 	{ DDB_ADD_CMD("esp",	db_esp,	0,
    698       1.37   martin 	  "display status of all esp SCSI controllers and their devices",
    699       1.37   martin 	  NULL, NULL) },
    700       1.37   martin 	{ DDB_ADD_CMD(NULL,	NULL,	0, NULL, NULL, NULL) }
    701       1.37   martin };
    702       1.12      eeh 
    703       1.37   martin static void
    704       1.44  tsutsui esp_init_ddb_cmds(void)
    705       1.37   martin {
    706       1.37   martin 	static int db_cmds_initialized = 0;
    707       1.37   martin 
    708       1.44  tsutsui 	if (db_cmds_initialized)
    709       1.44  tsutsui 		return;
    710       1.37   martin 	db_cmds_initialized = 1;
    711       1.37   martin 	(void)db_register_tbl(DDB_MACH_CMD, db_esp_command_table);
    712       1.37   martin }
    713       1.12      eeh 
    714       1.12      eeh void
    715       1.37   martin db_esp(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    716       1.12      eeh {
    717       1.39    joerg 	device_t dv;
    718       1.12      eeh 	struct ncr53c9x_softc *sc;
    719       1.12      eeh 	struct ncr53c9x_ecb *ecb;
    720       1.12      eeh 	struct ncr53c9x_linfo *li;
    721       1.12      eeh 	int u, t, i;
    722       1.12      eeh 
    723       1.44  tsutsui 	for (u = 0; u < 10; u++) {
    724       1.39    joerg 		dv = device_find_by_driver_unit("esp", u);
    725       1.41   simonb 		if (dv == NULL)
    726       1.41   simonb 			continue;
    727       1.39    joerg 		sc = device_private(dv);
    728       1.12      eeh 
    729       1.44  tsutsui 		db_printf("%s: nexus %p phase %x prev %x"
    730       1.44  tsutsui 		    " dp %p dleft %lx ify %x\n", device_xname(dv),
    731       1.44  tsutsui 		    sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
    732       1.44  tsutsui 		      sc->sc_dp, sc->sc_dleft, sc->sc_msgify);
    733       1.12      eeh 		db_printf("\tmsgout %x msgpriq %x msgin %x:%x:%x:%x:%x\n",
    734       1.44  tsutsui 		     sc->sc_msgout, sc->sc_msgpriq, sc->sc_imess[0],
    735       1.44  tsutsui 		     sc->sc_imess[1], sc->sc_imess[2], sc->sc_imess[3],
    736       1.44  tsutsui 		     sc->sc_imess[0]);
    737       1.12      eeh 		db_printf("ready: ");
    738       1.44  tsutsui 		for (ecb = TAILQ_FIRST(&sc->ready_list); ecb != NULL;
    739       1.44  tsutsui 		    ecb = TAILQ_NEXT(ecb, chain)) {
    740       1.12      eeh 			db_printf("ecb %p ", ecb);
    741       1.44  tsutsui 			if (ecb == TAILQ_NEXT(ecb, chain)) {
    742       1.44  tsutsui 				db_printf("\nWARNING: tailq loop on ecb %p",
    743       1.44  tsutsui 				    ecb);
    744       1.12      eeh 				break;
    745       1.12      eeh 			}
    746       1.12      eeh 		}
    747       1.12      eeh 		db_printf("\n");
    748       1.31    perry 
    749       1.44  tsutsui 		for (t = 0; t < sc->sc_ntarg; t++) {
    750       1.12      eeh 			LIST_FOREACH(li, &sc->sc_tinfo[t].luns, link) {
    751       1.44  tsutsui 				db_printf("t%d lun %d untagged %p"
    752       1.44  tsutsui 				    " busy %d used %x\n",
    753       1.44  tsutsui 				    t, (int)li->lun, li->untagged, li->busy,
    754       1.44  tsutsui 				    li->used);
    755       1.44  tsutsui 				for (i = 0; i < 256; i++)
    756       1.44  tsutsui 					ecb = li->queued[i];
    757       1.44  tsutsui 					if (ecb != NULL) {
    758       1.44  tsutsui 						db_printf("ecb %p tag %x\n",
    759       1.44  tsutsui 						    ecb, i);
    760       1.12      eeh 					}
    761       1.12      eeh 			}
    762       1.12      eeh 		}
    763       1.12      eeh 	}
    764       1.12      eeh }
    765       1.12      eeh #endif
    766