1 1.73 thorpej /* $NetBSD: hpc.c,v 1.73 2021/08/07 16:19:04 thorpej Exp $ */ 2 1.1 thorpej 3 1.1 thorpej /* 4 1.1 thorpej * Copyright (c) 2000 Soren S. Jorvang 5 1.1 thorpej * Copyright (c) 2001 Rafal K. Boni 6 1.3 thorpej * Copyright (c) 2001 Jason R. Thorpe 7 1.1 thorpej * All rights reserved. 8 1.7 simonb * 9 1.1 thorpej * Redistribution and use in source and binary forms, with or without 10 1.1 thorpej * modification, are permitted provided that the following conditions 11 1.1 thorpej * are met: 12 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 13 1.1 thorpej * notice, this list of conditions and the following disclaimer. 14 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 16 1.1 thorpej * documentation and/or other materials provided with the distribution. 17 1.1 thorpej * 3. All advertising materials mentioning features or use of this software 18 1.1 thorpej * must display the following acknowledgement: 19 1.1 thorpej * This product includes software developed for the 20 1.16 keihan * NetBSD Project. See http://www.NetBSD.org/ for 21 1.1 thorpej * information about NetBSD. 22 1.1 thorpej * 4. The name of the author may not be used to endorse or promote products 23 1.1 thorpej * derived from this software without specific prior written permission. 24 1.7 simonb * 25 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 1.1 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 1.1 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 1.1 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 1.1 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 1.1 thorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 1.1 thorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 1.1 thorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 1.1 thorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 1.1 thorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 1.1 thorpej */ 36 1.13 lukem 37 1.13 lukem #include <sys/cdefs.h> 38 1.73 thorpej __KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.73 2021/08/07 16:19:04 thorpej Exp $"); 39 1.1 thorpej 40 1.1 thorpej #include <sys/param.h> 41 1.1 thorpej #include <sys/systm.h> 42 1.26 sekiya #include <sys/kernel.h> 43 1.1 thorpej #include <sys/device.h> 44 1.1 thorpej #include <sys/reboot.h> 45 1.26 sekiya #include <sys/callout.h> 46 1.1 thorpej 47 1.66 dyoung #include <sys/bus.h> 48 1.1 thorpej #include <machine/machtype.h> 49 1.50 rumble #include <machine/sysconf.h> 50 1.1 thorpej 51 1.1 thorpej #include <sgimips/gio/gioreg.h> 52 1.1 thorpej #include <sgimips/gio/giovar.h> 53 1.1 thorpej 54 1.1 thorpej #include <sgimips/hpc/hpcvar.h> 55 1.1 thorpej #include <sgimips/hpc/hpcreg.h> 56 1.21 sekiya #include <sgimips/ioc/iocreg.h> 57 1.1 thorpej 58 1.42 rumble #include <dev/ic/smc93cx6var.h> 59 1.42 rumble 60 1.1 thorpej #include "locators.h" 61 1.1 thorpej 62 1.45 rumble struct hpc_device { 63 1.3 thorpej const char *hd_name; 64 1.29 rumble bus_addr_t hd_base; 65 1.3 thorpej bus_addr_t hd_devoff; 66 1.3 thorpej bus_addr_t hd_dmaoff; 67 1.3 thorpej int hd_irq; 68 1.3 thorpej int hd_sysmask; 69 1.45 rumble }; 70 1.17 sekiya 71 1.45 rumble static const struct hpc_device hpc1_devices[] = { 72 1.25 sekiya /* probe order is important for IP20 zsc */ 73 1.25 sekiya 74 1.45 rumble { "zsc", /* Personal Iris/Indigo serial 0/1 duart 1 */ 75 1.29 rumble HPC_BASE_ADDRESS_0, 76 1.24 sekiya 0x0d10, 0, 77 1.24 sekiya 5, 78 1.27 pooka HPCDEV_IP12 | HPCDEV_IP20 }, 79 1.24 sekiya 80 1.45 rumble { "zsc", /* Personal Iris/Indigo kbd/ms duart 0 */ 81 1.29 rumble HPC_BASE_ADDRESS_0, 82 1.25 sekiya 0x0d00, 0, 83 1.25 sekiya 5, 84 1.27 pooka HPCDEV_IP12 | HPCDEV_IP20 }, 85 1.25 sekiya 86 1.45 rumble { "sq", /* Personal Iris/Indigo onboard ethernet */ 87 1.29 rumble HPC_BASE_ADDRESS_0, 88 1.22 sekiya HPC1_ENET_DEVREGS, HPC1_ENET_REGS, 89 1.22 sekiya 3, 90 1.27 pooka HPCDEV_IP12 | HPCDEV_IP20 }, 91 1.45 rumble 92 1.45 rumble { "sq", /* E++ GIO adapter slot 0 (Indigo) */ 93 1.29 rumble HPC_BASE_ADDRESS_1, 94 1.29 rumble HPC1_ENET_DEVREGS, HPC1_ENET_REGS, 95 1.29 rumble 6, 96 1.29 rumble HPCDEV_IP12 | HPCDEV_IP20 }, 97 1.29 rumble 98 1.45 rumble { "sq", /* E++ GIO adapter slot 0 (Indy) */ 99 1.29 rumble HPC_BASE_ADDRESS_1, 100 1.29 rumble HPC1_ENET_DEVREGS, HPC1_ENET_REGS, 101 1.29 rumble 22, 102 1.29 rumble HPCDEV_IP24 }, 103 1.29 rumble 104 1.45 rumble { "sq", /* E++ GIO adapter slot 1 (Indigo) */ 105 1.29 rumble HPC_BASE_ADDRESS_2, 106 1.29 rumble HPC1_ENET_DEVREGS, HPC1_ENET_REGS, 107 1.44 rumble 6, 108 1.29 rumble HPCDEV_IP12 | HPCDEV_IP20 }, 109 1.29 rumble 110 1.45 rumble { "sq", /* E++ GIO adapter slot 1 (Indy/Challenge S) */ 111 1.29 rumble HPC_BASE_ADDRESS_2, 112 1.29 rumble HPC1_ENET_DEVREGS, HPC1_ENET_REGS, 113 1.29 rumble 23, 114 1.29 rumble HPCDEV_IP24 }, 115 1.29 rumble 116 1.45 rumble { "wdsc", /* Personal Iris/Indigo onboard SCSI */ 117 1.45 rumble HPC_BASE_ADDRESS_0, 118 1.45 rumble HPC1_SCSI0_DEVREGS, HPC1_SCSI0_REGS, 119 1.45 rumble 2, /* XXX 1 = IRQ_LOCAL0 + 2 */ 120 1.45 rumble HPCDEV_IP12 | HPCDEV_IP20 }, 121 1.45 rumble 122 1.54 rumble { "wdsc", /* GIO32 SCSI adapter slot 0 (Indigo) */ 123 1.54 rumble HPC_BASE_ADDRESS_1, 124 1.54 rumble HPC1_SCSI0_DEVREGS, HPC1_SCSI0_REGS, 125 1.54 rumble 6, 126 1.54 rumble HPCDEV_IP12 | HPCDEV_IP20 }, 127 1.54 rumble 128 1.54 rumble { "wdsc", /* GIO32 SCSI adapter slot 0 (Indy) */ 129 1.54 rumble HPC_BASE_ADDRESS_1, 130 1.54 rumble HPC1_SCSI0_DEVREGS, HPC1_SCSI0_REGS, 131 1.54 rumble 22, 132 1.54 rumble HPCDEV_IP24 }, 133 1.54 rumble 134 1.54 rumble { "wdsc", /* GIO32 SCSI adapter slot 1 (Indigo) */ 135 1.54 rumble HPC_BASE_ADDRESS_2, 136 1.54 rumble HPC1_SCSI0_DEVREGS, HPC1_SCSI0_REGS, 137 1.54 rumble 6, 138 1.54 rumble HPCDEV_IP12 | HPCDEV_IP20 }, 139 1.54 rumble 140 1.54 rumble { "wdsc", /* GIO32 SCSI adapter slot 1 (Indy/Challenge S) */ 141 1.54 rumble HPC_BASE_ADDRESS_2, 142 1.54 rumble HPC1_SCSI0_DEVREGS, HPC1_SCSI0_REGS, 143 1.54 rumble 23, 144 1.54 rumble HPCDEV_IP24 }, 145 1.54 rumble 146 1.45 rumble { NULL, 147 1.45 rumble 0, 148 1.45 rumble 0, 0, 149 1.45 rumble 0, 150 1.45 rumble 0 151 1.45 rumble } 152 1.45 rumble }; 153 1.45 rumble 154 1.45 rumble static const struct hpc_device hpc3_devices[] = { 155 1.45 rumble { "zsc", /* serial 0/1 duart 0 */ 156 1.45 rumble HPC_BASE_ADDRESS_0, 157 1.45 rumble /* XXX Magic numbers */ 158 1.45 rumble HPC3_PBUS_CH6_DEVREGS + IOC_SERIAL_REGS, 0, 159 1.45 rumble 29, 160 1.45 rumble HPCDEV_IP22 | HPCDEV_IP24 }, 161 1.45 rumble 162 1.45 rumble { "pckbc", /* Indigo2/Indy ps2 keyboard/mouse controller */ 163 1.45 rumble HPC_BASE_ADDRESS_0, 164 1.45 rumble HPC3_PBUS_CH6_DEVREGS + IOC_KB_REGS, 0, 165 1.45 rumble 28, 166 1.45 rumble HPCDEV_IP22 | HPCDEV_IP24 }, 167 1.45 rumble 168 1.45 rumble { "sq", /* Indigo2/Indy/Challenge S/Challenge M onboard enet */ 169 1.45 rumble HPC_BASE_ADDRESS_0, 170 1.45 rumble HPC3_ENET_DEVREGS, HPC3_ENET_REGS, 171 1.45 rumble 3, 172 1.45 rumble HPCDEV_IP22 | HPCDEV_IP24 }, 173 1.45 rumble 174 1.45 rumble { "sq", /* Challenge S IOPLUS secondary ethernet */ 175 1.45 rumble HPC_BASE_ADDRESS_1, 176 1.45 rumble HPC3_ENET_DEVREGS, HPC3_ENET_REGS, 177 1.52 rumble 0, 178 1.45 rumble HPCDEV_IP24 }, 179 1.45 rumble 180 1.45 rumble { "wdsc", /* Indigo2/Indy/Challenge S/Challenge M onboard SCSI */ 181 1.29 rumble HPC_BASE_ADDRESS_0, 182 1.31 rumble HPC3_SCSI0_DEVREGS, HPC3_SCSI0_REGS, 183 1.3 thorpej 1, /* XXX 1 = IRQ_LOCAL0 + 1 */ 184 1.3 thorpej HPCDEV_IP22 | HPCDEV_IP24 }, 185 1.3 thorpej 186 1.45 rumble { "wdsc", /* Indigo2/Challenge M secondary onboard SCSI */ 187 1.29 rumble HPC_BASE_ADDRESS_0, 188 1.31 rumble HPC3_SCSI1_DEVREGS, HPC3_SCSI1_REGS, 189 1.3 thorpej 2, /* XXX 2 = IRQ_LOCAL0 + 2 */ 190 1.3 thorpej HPCDEV_IP22 }, 191 1.18 sekiya 192 1.45 rumble { "haltwo", /* Indigo2/Indy onboard audio */ 193 1.29 rumble HPC_BASE_ADDRESS_0, 194 1.31 rumble HPC3_PBUS_CH0_DEVREGS, HPC3_PBUS_DMAREGS, 195 1.14 lonewolf 8 + 4, /* XXX IRQ_LOCAL1 + 4 */ 196 1.15 lonewolf HPCDEV_IP22 | HPCDEV_IP24 }, 197 1.3 thorpej 198 1.45 rumble { "pi1ppc", /* Indigo2/Indy/Challenge S/Challenge M onboard pport */ 199 1.35 kurahone HPC_BASE_ADDRESS_0, 200 1.35 kurahone HPC3_PBUS_CH6_DEVREGS + IOC_PLP_REGS, 0, 201 1.35 kurahone -1, 202 1.35 kurahone HPCDEV_IP22 | HPCDEV_IP24 }, 203 1.35 kurahone 204 1.70 macallan { "button", /* Indy front panel */ 205 1.62 macallan HPC_BASE_ADDRESS_0, 206 1.62 macallan HPC3_PBUS_CH6_DEVREGS + IOC_PANEL, 0, 207 1.62 macallan 9, 208 1.62 macallan HPCDEV_IP24 }, 209 1.62 macallan 210 1.3 thorpej { NULL, 211 1.29 rumble 0, 212 1.3 thorpej 0, 0, 213 1.3 thorpej 0, 214 1.3 thorpej 0 215 1.3 thorpej } 216 1.3 thorpej }; 217 1.3 thorpej 218 1.1 thorpej struct hpc_softc { 219 1.65 tsutsui device_t sc_dev; 220 1.1 thorpej 221 1.1 thorpej bus_addr_t sc_base; 222 1.1 thorpej 223 1.1 thorpej bus_space_tag_t sc_ct; 224 1.1 thorpej bus_space_handle_t sc_ch; 225 1.1 thorpej }; 226 1.1 thorpej 227 1.22 sekiya static struct hpc_values hpc1_values = { 228 1.23 sekiya .revision = 1, 229 1.23 sekiya .scsi0_regs = HPC1_SCSI0_REGS, 230 1.23 sekiya .scsi0_regs_size = HPC1_SCSI0_REGS_SIZE, 231 1.23 sekiya .scsi0_cbp = HPC1_SCSI0_CBP, 232 1.23 sekiya .scsi0_ndbp = HPC1_SCSI0_NDBP, 233 1.23 sekiya .scsi0_bc = HPC1_SCSI0_BC, 234 1.23 sekiya .scsi0_ctl = HPC1_SCSI0_CTL, 235 1.23 sekiya .scsi0_gio = HPC1_SCSI0_GIO, 236 1.23 sekiya .scsi0_dev = HPC1_SCSI0_DEV, 237 1.23 sekiya .scsi0_dmacfg = HPC1_SCSI0_DMACFG, 238 1.23 sekiya .scsi0_piocfg = HPC1_SCSI0_PIOCFG, 239 1.48 rumble .scsi1_regs = 0, 240 1.48 rumble .scsi1_regs_size = 0, 241 1.48 rumble .scsi1_cbp = 0, 242 1.48 rumble .scsi1_ndbp = 0, 243 1.48 rumble .scsi1_bc = 0, 244 1.48 rumble .scsi1_ctl = 0, 245 1.48 rumble .scsi1_gio = 0, 246 1.48 rumble .scsi1_dev = 0, 247 1.48 rumble .scsi1_dmacfg = 0, 248 1.48 rumble .scsi1_piocfg = 0, 249 1.23 sekiya .enet_regs = HPC1_ENET_REGS, 250 1.23 sekiya .enet_regs_size = HPC1_ENET_REGS_SIZE, 251 1.23 sekiya .enet_intdelay = HPC1_ENET_INTDELAY, 252 1.30 rumble .enet_intdelayval = HPC1_ENET_INTDELAY_OFF, 253 1.23 sekiya .enetr_cbp = HPC1_ENETR_CBP, 254 1.23 sekiya .enetr_ndbp = HPC1_ENETR_NDBP, 255 1.23 sekiya .enetr_bc = HPC1_ENETR_BC, 256 1.23 sekiya .enetr_ctl = HPC1_ENETR_CTL, 257 1.23 sekiya .enetr_ctl_active = HPC1_ENETR_CTL_ACTIVE, 258 1.23 sekiya .enetr_reset = HPC1_ENETR_RESET, 259 1.23 sekiya .enetr_dmacfg = 0, 260 1.30 rumble .enetr_piocfg = 0, 261 1.23 sekiya .enetx_cbp = HPC1_ENETX_CBP, 262 1.23 sekiya .enetx_ndbp = HPC1_ENETX_NDBP, 263 1.23 sekiya .enetx_bc = HPC1_ENETX_BC, 264 1.23 sekiya .enetx_ctl = HPC1_ENETX_CTL, 265 1.23 sekiya .enetx_ctl_active = HPC1_ENETX_CTL_ACTIVE, 266 1.30 rumble .enetx_dev = 0, 267 1.23 sekiya .enetr_fifo = HPC1_ENETR_FIFO, 268 1.23 sekiya .enetr_fifo_size = HPC1_ENETR_FIFO_SIZE, 269 1.23 sekiya .enetx_fifo = HPC1_ENETX_FIFO, 270 1.23 sekiya .enetx_fifo_size = HPC1_ENETX_FIFO_SIZE, 271 1.23 sekiya .scsi0_devregs_size = HPC1_SCSI0_DEVREGS_SIZE, 272 1.48 rumble .scsi1_devregs_size = 0, 273 1.23 sekiya .enet_devregs = HPC1_ENET_DEVREGS, 274 1.23 sekiya .enet_devregs_size = HPC1_ENET_DEVREGS_SIZE, 275 1.30 rumble .pbus_fifo = 0, 276 1.30 rumble .pbus_fifo_size = 0, 277 1.30 rumble .pbus_bbram = 0, 278 1.22 sekiya #define MAX_SCSI_XFER (512*1024) 279 1.23 sekiya .scsi_max_xfer = MAX_SCSI_XFER, 280 1.48 rumble .scsi_dma_segs = (MAX_SCSI_XFER / 4096), 281 1.23 sekiya .scsi_dma_segs_size = 4096, 282 1.49 rumble .scsi_dma_datain_cmd = (HPC1_SCSI_DMACTL_ACTIVE | HPC1_SCSI_DMACTL_DIR), 283 1.49 rumble .scsi_dma_dataout_cmd = HPC1_SCSI_DMACTL_ACTIVE, 284 1.48 rumble .scsi_dmactl_flush = HPC1_SCSI_DMACTL_FLUSH, 285 1.48 rumble .scsi_dmactl_active = HPC1_SCSI_DMACTL_ACTIVE, 286 1.48 rumble .scsi_dmactl_reset = HPC1_SCSI_DMACTL_RESET 287 1.22 sekiya }; 288 1.22 sekiya 289 1.22 sekiya static struct hpc_values hpc3_values = { 290 1.37 sekiya .revision = 3, 291 1.31 rumble .scsi0_regs = HPC3_SCSI0_REGS, 292 1.31 rumble .scsi0_regs_size = HPC3_SCSI0_REGS_SIZE, 293 1.31 rumble .scsi0_cbp = HPC3_SCSI0_CBP, 294 1.31 rumble .scsi0_ndbp = HPC3_SCSI0_NDBP, 295 1.31 rumble .scsi0_bc = HPC3_SCSI0_BC, 296 1.31 rumble .scsi0_ctl = HPC3_SCSI0_CTL, 297 1.31 rumble .scsi0_gio = HPC3_SCSI0_GIO, 298 1.31 rumble .scsi0_dev = HPC3_SCSI0_DEV, 299 1.31 rumble .scsi0_dmacfg = HPC3_SCSI0_DMACFG, 300 1.31 rumble .scsi0_piocfg = HPC3_SCSI0_PIOCFG, 301 1.31 rumble .scsi1_regs = HPC3_SCSI1_REGS, 302 1.31 rumble .scsi1_regs_size = HPC3_SCSI1_REGS_SIZE, 303 1.31 rumble .scsi1_cbp = HPC3_SCSI1_CBP, 304 1.31 rumble .scsi1_ndbp = HPC3_SCSI1_NDBP, 305 1.31 rumble .scsi1_bc = HPC3_SCSI1_BC, 306 1.31 rumble .scsi1_ctl = HPC3_SCSI1_CTL, 307 1.31 rumble .scsi1_gio = HPC3_SCSI1_GIO, 308 1.31 rumble .scsi1_dev = HPC3_SCSI1_DEV, 309 1.31 rumble .scsi1_dmacfg = HPC3_SCSI1_DMACFG, 310 1.31 rumble .scsi1_piocfg = HPC3_SCSI1_PIOCFG, 311 1.31 rumble .enet_regs = HPC3_ENET_REGS, 312 1.31 rumble .enet_regs_size = HPC3_ENET_REGS_SIZE, 313 1.23 sekiya .enet_intdelay = 0, 314 1.23 sekiya .enet_intdelayval = 0, 315 1.31 rumble .enetr_cbp = HPC3_ENETR_CBP, 316 1.31 rumble .enetr_ndbp = HPC3_ENETR_NDBP, 317 1.31 rumble .enetr_bc = HPC3_ENETR_BC, 318 1.31 rumble .enetr_ctl = HPC3_ENETR_CTL, 319 1.31 rumble .enetr_ctl_active = HPC3_ENETR_CTL_ACTIVE, 320 1.31 rumble .enetr_reset = HPC3_ENETR_RESET, 321 1.31 rumble .enetr_dmacfg = HPC3_ENETR_DMACFG, 322 1.31 rumble .enetr_piocfg = HPC3_ENETR_PIOCFG, 323 1.31 rumble .enetx_cbp = HPC3_ENETX_CBP, 324 1.31 rumble .enetx_ndbp = HPC3_ENETX_NDBP, 325 1.31 rumble .enetx_bc = HPC3_ENETX_BC, 326 1.31 rumble .enetx_ctl = HPC3_ENETX_CTL, 327 1.31 rumble .enetx_ctl_active = HPC3_ENETX_CTL_ACTIVE, 328 1.31 rumble .enetx_dev = HPC3_ENETX_DEV, 329 1.31 rumble .enetr_fifo = HPC3_ENETR_FIFO, 330 1.31 rumble .enetr_fifo_size = HPC3_ENETR_FIFO_SIZE, 331 1.31 rumble .enetx_fifo = HPC3_ENETX_FIFO, 332 1.31 rumble .enetx_fifo_size = HPC3_ENETX_FIFO_SIZE, 333 1.31 rumble .scsi0_devregs_size = HPC3_SCSI0_DEVREGS_SIZE, 334 1.31 rumble .scsi1_devregs_size = HPC3_SCSI1_DEVREGS_SIZE, 335 1.31 rumble .enet_devregs = HPC3_ENET_DEVREGS, 336 1.31 rumble .enet_devregs_size = HPC3_ENET_DEVREGS_SIZE, 337 1.31 rumble .pbus_fifo = HPC3_PBUS_FIFO, 338 1.31 rumble .pbus_fifo_size = HPC3_PBUS_FIFO_SIZE, 339 1.31 rumble .pbus_bbram = HPC3_PBUS_BBRAM, 340 1.23 sekiya .scsi_max_xfer = MAX_SCSI_XFER, 341 1.48 rumble .scsi_dma_segs = (MAX_SCSI_XFER / 8192), 342 1.23 sekiya .scsi_dma_segs_size = 8192, 343 1.49 rumble .scsi_dma_datain_cmd = HPC3_SCSI_DMACTL_ACTIVE, 344 1.49 rumble .scsi_dma_dataout_cmd =(HPC3_SCSI_DMACTL_ACTIVE | HPC3_SCSI_DMACTL_DIR), 345 1.48 rumble .scsi_dmactl_flush = HPC3_SCSI_DMACTL_FLUSH, 346 1.48 rumble .scsi_dmactl_active = HPC3_SCSI_DMACTL_ACTIVE, 347 1.48 rumble .scsi_dmactl_reset = HPC3_SCSI_DMACTL_RESET 348 1.22 sekiya }; 349 1.22 sekiya 350 1.65 tsutsui static int hpc_match(device_t, cfdata_t, void *); 351 1.65 tsutsui static void hpc_attach(device_t, device_t, void *); 352 1.41 rumble static int hpc_print(void *, const char *); 353 1.1 thorpej 354 1.41 rumble static int hpc_revision(struct hpc_softc *, struct gio_attach_args *); 355 1.29 rumble 356 1.65 tsutsui static int hpc_submatch(device_t, cfdata_t, const int *, void *); 357 1.3 thorpej 358 1.57 rumble //static int hpc_power_intr(void *); 359 1.1 thorpej 360 1.26 sekiya #if defined(BLINK) 361 1.58 ad static callout_t hpc_blink_ch; 362 1.26 sekiya static void hpc_blink(void *); 363 1.26 sekiya #endif 364 1.26 sekiya 365 1.42 rumble static int hpc_read_eeprom(int, bus_space_tag_t, bus_space_handle_t, 366 1.42 rumble uint8_t *, size_t); 367 1.42 rumble 368 1.65 tsutsui CFATTACH_DECL_NEW(hpc, sizeof(struct hpc_softc), 369 1.11 thorpej hpc_match, hpc_attach, NULL, NULL); 370 1.1 thorpej 371 1.68 macallan static void hpc_bus_mem_init(bus_space_tag_t, void *); 372 1.68 macallan 373 1.68 macallan static struct mips_bus_space hpc_mbst; 374 1.68 macallan bus_space_tag_t hpc_memt = NULL; 375 1.68 macallan 376 1.68 macallan 377 1.41 rumble static int 378 1.65 tsutsui hpc_match(device_t parent, cfdata_t cf, void *aux) 379 1.1 thorpej { 380 1.1 thorpej struct gio_attach_args* ga = aux; 381 1.1 thorpej 382 1.61 rumble if (mach_type == MACH_SGI_IP12 || mach_type == MACH_SGI_IP20 || 383 1.61 rumble mach_type == MACH_SGI_IP22) { 384 1.61 rumble /* Make sure it's actually there and readable */ 385 1.61 rumble if (!platform.badaddr((void*)MIPS_PHYS_TO_KSEG1(ga->ga_addr), 386 1.64 tsutsui sizeof(uint32_t))) 387 1.61 rumble return 1; 388 1.61 rumble } 389 1.1 thorpej 390 1.61 rumble return 0; 391 1.1 thorpej } 392 1.1 thorpej 393 1.41 rumble static void 394 1.65 tsutsui hpc_attach(device_t parent, device_t self, void *aux) 395 1.1 thorpej { 396 1.65 tsutsui struct hpc_softc *sc = device_private(self); 397 1.1 thorpej struct gio_attach_args* ga = aux; 398 1.1 thorpej struct hpc_attach_args ha; 399 1.3 thorpej const struct hpc_device *hd; 400 1.27 pooka uint32_t hpctype; 401 1.46 rumble int isonboard; 402 1.46 rumble int isioplus; 403 1.27 pooka int sysmask; 404 1.3 thorpej 405 1.65 tsutsui sc->sc_dev = self; 406 1.65 tsutsui 407 1.58 ad #ifdef BLINK 408 1.58 ad callout_init(&hpc_blink_ch, 0); 409 1.58 ad #endif 410 1.58 ad 411 1.3 thorpej switch (mach_type) { 412 1.27 pooka case MACH_SGI_IP12: 413 1.27 pooka sysmask = HPCDEV_IP12; 414 1.27 pooka break; 415 1.27 pooka 416 1.20 sekiya case MACH_SGI_IP20: 417 1.20 sekiya sysmask = HPCDEV_IP20; 418 1.20 sekiya break; 419 1.23 sekiya 420 1.3 thorpej case MACH_SGI_IP22: 421 1.3 thorpej if (mach_subtype == MACH_SGI_IP22_FULLHOUSE) 422 1.3 thorpej sysmask = HPCDEV_IP22; 423 1.3 thorpej else 424 1.3 thorpej sysmask = HPCDEV_IP24; 425 1.3 thorpej break; 426 1.3 thorpej 427 1.3 thorpej default: 428 1.23 sekiya panic("hpc_attach: can't handle HPC on an IP%d", mach_type); 429 1.3 thorpej }; 430 1.1 thorpej 431 1.29 rumble if ((hpctype = hpc_revision(sc, ga)) == 0) 432 1.29 rumble panic("hpc_attach: could not identify HPC revision\n"); 433 1.24 sekiya 434 1.29 rumble /* force big-endian mode */ 435 1.29 rumble if (hpctype == 15) 436 1.29 rumble *(uint32_t *)MIPS_PHYS_TO_KSEG1(ga->ga_addr+HPC1_BIGENDIAN) = 0; 437 1.46 rumble 438 1.46 rumble /* 439 1.46 rumble * All machines have only one HPC on the mainboard itself. ''Extra'' 440 1.46 rumble * HPCs require bus arbiter and other magic to run happily. 441 1.46 rumble */ 442 1.46 rumble isonboard = (ga->ga_addr == HPC_BASE_ADDRESS_0); 443 1.46 rumble isioplus = (ga->ga_addr == HPC_BASE_ADDRESS_1 && hpctype == 3 && 444 1.46 rumble sysmask == HPCDEV_IP24); 445 1.23 sekiya 446 1.46 rumble printf(": SGI HPC%d%s (%s)\n", (hpctype == 3) ? 3 : 1, 447 1.46 rumble (hpctype == 15) ? ".5" : "", (isonboard) ? "onboard" : 448 1.46 rumble (isioplus) ? "IOPLUS mezzanine" : "GIO slot"); 449 1.46 rumble 450 1.52 rumble /* 451 1.52 rumble * Configure the bus arbiter appropriately. 452 1.52 rumble * 453 1.52 rumble * In the case of Challenge S, we must tell the IOPLUS board which 454 1.52 rumble * DMA channel to use (we steal it from one of the slots). SGI permits 455 1.52 rumble * an HPC1.5 in slot 1, in which case IOPLUS must use EXP0, or any 456 1.52 rumble * other DMA-capable board in slot 0, which leaves us to use EXP1. Of 457 1.52 rumble * course, this means that only one GIO board may use DMA. 458 1.52 rumble * 459 1.52 rumble * Note that this never happens on Indigo2. 460 1.52 rumble */ 461 1.52 rumble if (isioplus) { 462 1.52 rumble int arb_slot; 463 1.52 rumble 464 1.52 rumble if (platform.badaddr( 465 1.52 rumble (void *)MIPS_PHYS_TO_KSEG1(HPC_BASE_ADDRESS_2), 4)) 466 1.52 rumble arb_slot = GIO_SLOT_EXP1; 467 1.52 rumble else 468 1.52 rumble arb_slot = GIO_SLOT_EXP0; 469 1.52 rumble 470 1.52 rumble if (gio_arb_config(arb_slot, GIO_ARB_LB | GIO_ARB_MST | 471 1.52 rumble GIO_ARB_64BIT | GIO_ARB_HPC2_64BIT)) { 472 1.52 rumble printf("%s: failed to configure GIO bus arbiter\n", 473 1.65 tsutsui device_xname(sc->sc_dev)); 474 1.52 rumble return; 475 1.52 rumble } 476 1.52 rumble 477 1.65 tsutsui printf("%s: using EXP%d's DMA channel\n", 478 1.65 tsutsui device_xname(sc->sc_dev), 479 1.52 rumble (arb_slot == GIO_SLOT_EXP0) ? 0 : 1); 480 1.52 rumble 481 1.52 rumble bus_space_write_4(ga->ga_iot, ga->ga_ioh, 482 1.52 rumble HPC3_PBUS_CFGPIO_REGS, 0x0003ffff); 483 1.52 rumble 484 1.52 rumble if (arb_slot == GIO_SLOT_EXP0) 485 1.52 rumble bus_space_write_4(ga->ga_iot, ga->ga_ioh, 486 1.52 rumble HPC3_PBUS_CH0_DEVREGS, 0x20202020); 487 1.52 rumble else 488 1.52 rumble bus_space_write_4(ga->ga_iot, ga->ga_ioh, 489 1.52 rumble HPC3_PBUS_CH0_DEVREGS, 0x30303030); 490 1.52 rumble } else if (!isonboard) { 491 1.46 rumble int arb_slot; 492 1.46 rumble 493 1.46 rumble arb_slot = (ga->ga_addr == HPC_BASE_ADDRESS_1) ? 494 1.46 rumble GIO_SLOT_EXP0 : GIO_SLOT_EXP1; 495 1.46 rumble 496 1.46 rumble if (gio_arb_config(arb_slot, GIO_ARB_RT | GIO_ARB_MST)) { 497 1.46 rumble printf("%s: failed to configure GIO bus arbiter\n", 498 1.65 tsutsui device_xname(sc->sc_dev)); 499 1.46 rumble return; 500 1.46 rumble } 501 1.46 rumble } 502 1.1 thorpej 503 1.68 macallan hpc_bus_mem_init(&hpc_mbst, NULL); 504 1.68 macallan hpc_memt = &hpc_mbst; 505 1.68 macallan 506 1.68 macallan sc->sc_ct = normal_memt; 507 1.1 thorpej sc->sc_ch = ga->ga_ioh; 508 1.1 thorpej 509 1.1 thorpej sc->sc_base = ga->ga_addr; 510 1.3 thorpej 511 1.68 macallan hpc_read_eeprom(hpctype, normal_memt, 512 1.53 rumble MIPS_PHYS_TO_KSEG1(sc->sc_base), ha.hpc_eeprom, 513 1.53 rumble sizeof(ha.hpc_eeprom)); 514 1.53 rumble 515 1.45 rumble hd = (hpctype == 3) ? hpc3_devices : hpc1_devices; 516 1.45 rumble for (; hd->hd_name != NULL; hd++) { 517 1.29 rumble if (!(hd->hd_sysmask & sysmask) || hd->hd_base != sc->sc_base) 518 1.5 rafal continue; 519 1.5 rafal 520 1.5 rafal ha.ha_name = hd->hd_name; 521 1.5 rafal ha.ha_devoff = hd->hd_devoff; 522 1.5 rafal ha.ha_dmaoff = hd->hd_dmaoff; 523 1.5 rafal ha.ha_irq = hd->hd_irq; 524 1.5 rafal 525 1.5 rafal /* XXX This is disgusting. */ 526 1.68 macallan ha.ha_st = normal_memt; 527 1.69 macallan if (bus_space_map(normal_memt, sc->sc_base, 0, 528 1.69 macallan BUS_SPACE_MAP_LINEAR, &ha.ha_sh) != 0) 529 1.69 macallan continue; 530 1.5 rafal ha.ha_dmat = &sgimips_default_bus_dma_tag; 531 1.22 sekiya if (hpctype == 3) 532 1.22 sekiya ha.hpc_regs = &hpc3_values; 533 1.22 sekiya else 534 1.22 sekiya ha.hpc_regs = &hpc1_values; 535 1.23 sekiya ha.hpc_regs->revision = hpctype; 536 1.5 rafal 537 1.55 rumble /* XXXgross! avoid complaining in E++ and GIO32 SCSI cases */ 538 1.55 rumble if (hpctype != 3 && sc->sc_base != HPC_BASE_ADDRESS_0) { 539 1.72 thorpej config_found(self, &ha, NULL, 540 1.73 thorpej CFARGS(.submatch = hpc_submatch)); 541 1.55 rumble } else { 542 1.72 thorpej config_found(self, &ha, hpc_print, 543 1.73 thorpej CFARGS(.submatch = hpc_submatch)); 544 1.55 rumble } 545 1.3 thorpej } 546 1.1 thorpej 547 1.26 sekiya #if defined(BLINK) 548 1.28 pooka if (mach_type == MACH_SGI_IP12 || mach_type == MACH_SGI_IP20) 549 1.26 sekiya hpc_blink(sc); 550 1.26 sekiya #endif 551 1.1 thorpej } 552 1.1 thorpej 553 1.40 rumble /* 554 1.40 rumble * HPC revision detection isn't as simple as it should be. Devices probe 555 1.40 rumble * differently depending on their slots, but luckily there is only one 556 1.40 rumble * instance in which we have to decide the major revision (HPC1 vs HPC3). 557 1.40 rumble * 558 1.40 rumble * The HPC is found in the following configurations: 559 1.40 rumble * o Personal Iris 4D/3x: 560 1.40 rumble * One on-board HPC1 or HPC1.5. 561 1.40 rumble * 562 1.40 rumble * o Indigo R3k/R4k: 563 1.40 rumble * One on-board HPC1 or HPC1.5. 564 1.40 rumble * Up to two additional HPC1.5's in GIO slots 0 and 1. 565 1.40 rumble * 566 1.40 rumble * o Indy: 567 1.40 rumble * One on-board HPC3. 568 1.40 rumble * Up to two additional HPC1.5's in GIO slots 0 and 1. 569 1.40 rumble * 570 1.40 rumble * o Challenge S 571 1.40 rumble * One on-board HPC3. 572 1.40 rumble * Up to one additional HPC3 on the IOPLUS board (if installed). 573 1.40 rumble * Up to one additional HPC1.5 in slot 1 of the IOPLUS board. 574 1.40 rumble * 575 1.40 rumble * o Indigo2, Challenge M 576 1.40 rumble * One on-board HPC3. 577 1.40 rumble * 578 1.40 rumble * All we really have to worry about is the IP22 case. 579 1.40 rumble */ 580 1.41 rumble static int 581 1.29 rumble hpc_revision(struct hpc_softc *sc, struct gio_attach_args *ga) 582 1.29 rumble { 583 1.29 rumble 584 1.40 rumble /* No hardware ever supported the last hpc base address. */ 585 1.40 rumble if (ga->ga_addr == HPC_BASE_ADDRESS_3) 586 1.29 rumble return (0); 587 1.29 rumble 588 1.40 rumble if (mach_type == MACH_SGI_IP12 || mach_type == MACH_SGI_IP20) { 589 1.64 tsutsui uint32_t reg; 590 1.29 rumble 591 1.50 rumble if (!platform.badaddr((void *)MIPS_PHYS_TO_KSEG1(ga->ga_addr + 592 1.29 rumble HPC1_BIGENDIAN), 4)) { 593 1.29 rumble reg = *(uint32_t *)MIPS_PHYS_TO_KSEG1(ga->ga_addr + 594 1.29 rumble HPC1_BIGENDIAN); 595 1.29 rumble 596 1.29 rumble if (((reg >> HPC1_REVSHIFT) & HPC1_REVMASK) == 597 1.29 rumble HPC1_REV15) 598 1.40 rumble return (15); 599 1.29 rumble else 600 1.40 rumble return (1); 601 1.40 rumble } 602 1.40 rumble 603 1.40 rumble return (1); 604 1.40 rumble } 605 1.40 rumble 606 1.40 rumble /* 607 1.40 rumble * If IP22, probe slot 0 to determine if HPC1.5 or HPC3. Slot 1 must 608 1.40 rumble * be HPC1.5. 609 1.40 rumble */ 610 1.40 rumble if (mach_type == MACH_SGI_IP22) { 611 1.40 rumble if (ga->ga_addr == HPC_BASE_ADDRESS_0) 612 1.40 rumble return (3); 613 1.40 rumble 614 1.40 rumble if (ga->ga_addr == HPC_BASE_ADDRESS_2) 615 1.40 rumble return (15); 616 1.40 rumble 617 1.40 rumble /* 618 1.40 rumble * Probe for it. We use one of the PBUS registers. Note 619 1.51 rumble * that this probe succeeds with my E++ adapter in slot 1 620 1.51 rumble * (bad), but it appears to always do the right thing in 621 1.51 rumble * slot 0 (good!) and we're only worried about that one 622 1.51 rumble * anyhow. 623 1.40 rumble */ 624 1.50 rumble if (platform.badaddr((void *)MIPS_PHYS_TO_KSEG1(ga->ga_addr + 625 1.40 rumble HPC3_PBUS_CH7_BP), 4)) 626 1.40 rumble return (15); 627 1.40 rumble else 628 1.40 rumble return (3); 629 1.29 rumble } 630 1.29 rumble 631 1.40 rumble return (0); 632 1.29 rumble } 633 1.29 rumble 634 1.41 rumble static int 635 1.67 chs hpc_submatch(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 636 1.1 thorpej { 637 1.1 thorpej struct hpc_attach_args *ha = aux; 638 1.1 thorpej 639 1.3 thorpej if (cf->cf_loc[HPCCF_OFFSET] != HPCCF_OFFSET_DEFAULT && 640 1.12 thorpej (bus_addr_t) cf->cf_loc[HPCCF_OFFSET] != ha->ha_devoff) 641 1.3 thorpej return (0); 642 1.1 thorpej 643 1.8 thorpej return (config_match(parent, cf, aux)); 644 1.3 thorpej } 645 1.3 thorpej 646 1.41 rumble static int 647 1.3 thorpej hpc_print(void *aux, const char *pnp) 648 1.3 thorpej { 649 1.3 thorpej struct hpc_attach_args *ha = aux; 650 1.1 thorpej 651 1.3 thorpej if (pnp) 652 1.3 thorpej printf("%s at %s", ha->ha_name, pnp); 653 1.1 thorpej 654 1.63 matt printf(" offset %#" PRIxVADDR, (vaddr_t)ha->ha_devoff); 655 1.1 thorpej 656 1.3 thorpej return (UNCONF); 657 1.1 thorpej } 658 1.1 thorpej 659 1.26 sekiya #if defined(BLINK) 660 1.26 sekiya static void 661 1.65 tsutsui hpc_blink(void *arg) 662 1.26 sekiya { 663 1.65 tsutsui struct hpc_softc *sc = arg; 664 1.26 sekiya register int s; 665 1.26 sekiya int value; 666 1.26 sekiya 667 1.26 sekiya s = splhigh(); 668 1.26 sekiya 669 1.43 rumble value = *(volatile uint8_t *)MIPS_PHYS_TO_KSEG1(HPC_BASE_ADDRESS_0 + 670 1.43 rumble HPC1_AUX_REGS); 671 1.26 sekiya value ^= HPC1_AUX_CONSLED; 672 1.64 tsutsui *(volatile uint8_t *)MIPS_PHYS_TO_KSEG1(HPC_BASE_ADDRESS_0 + 673 1.43 rumble HPC1_AUX_REGS) = value; 674 1.26 sekiya splx(s); 675 1.26 sekiya 676 1.26 sekiya /* 677 1.26 sekiya * Blink rate is: 678 1.26 sekiya * full cycle every second if completely idle (loadav = 0) 679 1.26 sekiya * full cycle every 2 seconds if loadav = 1 680 1.26 sekiya * full cycle every 3 seconds if loadav = 2 681 1.26 sekiya * etc. 682 1.26 sekiya */ 683 1.26 sekiya s = (((averunnable.ldavg[0] + FSCALE) * hz) >> (FSHIFT + 1)); 684 1.26 sekiya callout_reset(&hpc_blink_ch, s, hpc_blink, sc); 685 1.26 sekiya } 686 1.26 sekiya #endif 687 1.26 sekiya 688 1.42 rumble /* 689 1.42 rumble * Read the eeprom associated with one of the HPC's. 690 1.42 rumble * 691 1.42 rumble * NB: An eeprom is not always present, but the HPC should be able to 692 1.42 rumble * handle this gracefully. Any consumers should validate the data to 693 1.42 rumble * ensure it's reasonable. 694 1.42 rumble */ 695 1.42 rumble static int 696 1.42 rumble hpc_read_eeprom(int hpctype, bus_space_tag_t t, bus_space_handle_t h, 697 1.42 rumble uint8_t *buf, size_t len) 698 1.42 rumble { 699 1.42 rumble struct seeprom_descriptor sd; 700 1.42 rumble bus_space_handle_t bsh; 701 1.42 rumble bus_space_tag_t tag; 702 1.42 rumble bus_size_t offset; 703 1.42 rumble 704 1.42 rumble if (!len || len & 0x1) 705 1.42 rumble return (1); 706 1.42 rumble 707 1.43 rumble offset = (hpctype == 3) ? HPC3_EEPROM_DATA : HPC1_AUX_REGS; 708 1.42 rumble 709 1.68 macallan tag = normal_memt; 710 1.42 rumble if (bus_space_subregion(t, h, offset, 1, &bsh) != 0) 711 1.42 rumble return (1); 712 1.42 rumble 713 1.42 rumble sd.sd_chip = C56_66; 714 1.42 rumble sd.sd_tag = tag; 715 1.42 rumble sd.sd_bsh = bsh; 716 1.42 rumble sd.sd_regsize = 1; 717 1.42 rumble sd.sd_control_offset = 0; 718 1.42 rumble sd.sd_status_offset = 0; 719 1.42 rumble sd.sd_dataout_offset = 0; 720 1.42 rumble sd.sd_DI = 0x10; /* EEPROM -> CPU */ 721 1.42 rumble sd.sd_DO = 0x08; /* CPU -> EEPROM */ 722 1.42 rumble sd.sd_CK = 0x04; 723 1.42 rumble sd.sd_CS = 0x02; 724 1.42 rumble sd.sd_MS = 0; 725 1.42 rumble sd.sd_RDY = 0; 726 1.42 rumble 727 1.42 rumble if (read_seeprom(&sd, (uint16_t *)buf, 0, len / 2) != 1) 728 1.42 rumble return (1); 729 1.42 rumble 730 1.42 rumble bus_space_unmap(t, bsh, 1); 731 1.42 rumble 732 1.42 rumble return (0); 733 1.42 rumble } 734 1.68 macallan 735 1.68 macallan #define CHIP hpc 736 1.68 macallan #define CHIP_MEM /* defined */ 737 1.68 macallan #define CHIP_ALIGN_STRIDE 2 738 1.68 macallan #define CHIP_ACCESS_SIZE 4 739 1.68 macallan #define CHIP_W1_BUS_START(v) 0x00000000UL 740 1.68 macallan #define CHIP_W1_BUS_END(v) 0xffffffffUL 741 1.68 macallan #define CHIP_W1_SYS_START(v) 0x00000000UL 742 1.68 macallan #define CHIP_W1_SYS_END(v) 0xffffffffUL 743 1.68 macallan 744 1.68 macallan #include <mips/mips/bus_space_alignstride_chipdep.c> 745