1 /* $OpenBSD: qlw_sbus.c,v 1.1 2014/03/15 21:49:47 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2014 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/device.h> 20 #include <sys/malloc.h> 21 #include <sys/systm.h> 22 23 #include <machine/bus.h> 24 #include <machine/intr.h> 25 #include <machine/autoconf.h> 26 27 #include <dev/sbus/sbusvar.h> 28 29 #include <scsi/scsi_all.h> 30 #include <scsi/scsiconf.h> 31 32 #include <dev/ic/qlwreg.h> 33 #include <dev/ic/qlwvar.h> 34 35 #ifndef ISP_NOFIRMWARE 36 #include <dev/microcode/isp/asm_sbus.h> 37 #endif 38 39 int qlw_sbus_match(struct device *, void *, void *); 40 void qlw_sbus_attach(struct device *, struct device *, void *); 41 42 struct cfattach qlw_sbus_ca = { 43 sizeof(struct qlw_softc), 44 qlw_sbus_match, 45 qlw_sbus_attach 46 }; 47 48 int 49 qlw_sbus_match(struct device *parent, void *cf, void *aux) 50 { 51 struct sbus_attach_args *sa = aux; 52 53 if (strcmp("ptisp", sa->sa_name) == 0 || 54 strcmp("PTI,ptisp", sa->sa_name) == 0 || 55 strcmp("SUNW,isp", sa->sa_name) == 0 || 56 strcmp("QLGC,isp", sa->sa_name) == 0) 57 return 2; 58 59 return 0; 60 } 61 62 void 63 qlw_sbus_attach(struct device *parent, struct device *self, void *aux) 64 { 65 struct qlw_softc *sc = (void *)self; 66 struct sbus_attach_args *sa = aux; 67 u_int32_t sbusburst, burst; 68 int freq; 69 70 if (sa->sa_nintr < 1) { 71 printf(": no interrupt\n"); 72 return; 73 } 74 75 if (sa->sa_nreg < 1) { 76 printf(": no registers\n"); 77 return; 78 } 79 80 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset, 81 sa->sa_size, 0, 0, &sc->sc_ioh) != 0) { 82 printf(": can't map registers\n"); 83 return; 84 } 85 86 printf(": %s\n", sa->sa_name); 87 88 if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_BIO, 0, 89 qlw_intr, sc, sc->sc_dev.dv_xname) == NULL) { 90 printf("%s: can't establish interrupt\n", DEVNAME(sc)); 91 goto unmap; 92 } 93 94 /* 95 * Get transfer burst size from PROM 96 */ 97 sbusburst = ((struct sbus_softc *)parent)->sc_burst; 98 if (sbusburst == 0) 99 sbusburst = SBUS_BURST_32 - 1; /* 1->16 */ 100 101 burst = getpropint(sa->sa_node, "burst-sizes", -1); 102 if (burst == -1) 103 burst = sbusburst; 104 105 /* Clamp at parent's burst sizes */ 106 burst &= sbusburst; 107 108 if ((burst & SBUS_BURST_32)) 109 sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_FIFO_32; 110 else if ((burst & SBUS_BURST_16)) 111 sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_FIFO_16; 112 else if ((burst & SBUS_BURST_8)) 113 sc->sc_isp_config = QLW_BURST_ENABLE | QLW_SBUS_BURST_8; 114 115 sc->sc_iot = sa->sa_bustag; 116 sc->sc_ios = sa->sa_size; 117 sc->sc_dmat = sa->sa_dmatag; 118 119 sc->sc_isp_gen = QLW_GEN_ISP1000; 120 sc->sc_isp_type = QLW_ISP1000; 121 sc->sc_numbusses = 1; 122 123 freq = getpropint(sa->sa_node, "clock-frequency", 40000000); 124 sc->sc_clock = (freq + 500000) / 1000000; 125 126 #ifndef ISP_NOFIRMWARE 127 /* 128 * Some early versions of the PTI cards don't support loading 129 * a new firmware, so only do this in the Sun or QLogic 130 * branded ones. 131 */ 132 if (strcmp("SUNW,isp", sa->sa_name) == 0 || 133 strcmp("QLGC,isp", sa->sa_name) == 0) 134 sc->sc_firmware = isp_1000_risc_code; 135 #endif 136 137 sc->sc_initiator[0] = getpropint(sa->sa_node, "scsi-initiator-id", 6); 138 139 sc->sc_host_cmd_ctrl = QLW_HOST_CMD_CTRL_SBUS; 140 sc->sc_mbox_base = QLW_MBOX_BASE_SBUS; 141 142 qlw_attach(sc); 143 return; 144 145 unmap: 146 bus_space_unmap(sa->sa_bustag, sc->sc_ioh, sa->sa_size); 147 } 148