dec_6600.c revision 1.35
11.35Sthorpej/* $NetBSD: dec_6600.c,v 1.35 2020/09/04 03:41:49 thorpej Exp $ */ 21.1Sross 31.1Sross/* 41.1Sross * Copyright (c) 1995, 1996, 1997 Carnegie-Mellon University. 51.1Sross * All rights reserved. 61.1Sross * 71.1Sross * Author: Chris G. Demetriou 81.33Smatt * 91.1Sross * Permission to use, copy, modify and distribute this software and 101.1Sross * its documentation is hereby granted, provided that both the copyright 111.1Sross * notice and this permission notice appear in all copies of the 121.1Sross * software, derivative works or modified versions, and any portions 131.1Sross * thereof, and that both notices appear in supporting documentation. 141.33Smatt * 151.33Smatt * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 161.33Smatt * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 171.1Sross * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 181.33Smatt * 191.1Sross * Carnegie Mellon requests users of this software to return to 201.1Sross * 211.1Sross * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 221.1Sross * School of Computer Science 231.1Sross * Carnegie Mellon University 241.1Sross * Pittsburgh PA 15213-3890 251.1Sross * 261.1Sross * any improvements or extensions that they make and grant Carnegie the 271.1Sross * rights to redistribute these changes. 281.1Sross */ 291.1Sross 301.11Slukem#include "opt_kgdb.h" 311.11Slukem 321.1Sross#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 331.1Sross 341.35Sthorpej__KERNEL_RCSID(0, "$NetBSD: dec_6600.c,v 1.35 2020/09/04 03:41:49 thorpej Exp $"); 351.1Sross 361.1Sross#include <sys/param.h> 371.1Sross#include <sys/systm.h> 381.1Sross#include <sys/device.h> 391.35Sthorpej#include <sys/lwp.h> 401.1Sross#include <sys/termios.h> 411.35Sthorpej 421.14Sgehenna#include <sys/conf.h> 431.1Sross#include <dev/cons.h> 441.1Sross 451.1Sross#include <machine/rpb.h> 461.1Sross#include <machine/autoconf.h> 471.14Sgehenna#include <machine/cpuconf.h> 481.32Sdyoung#include <sys/bus.h> 491.30Shans#include <machine/alpha.h> 501.30Shans#include <machine/logout.h> 511.1Sross 521.1Sross#include <dev/ic/comreg.h> 531.1Sross#include <dev/ic/comvar.h> 541.1Sross 551.2Sthorpej#include <dev/isa/isareg.h> 561.1Sross#include <dev/isa/isavar.h> 571.6Ssoda#include <dev/ic/i8042reg.h> 581.2Sthorpej#include <dev/ic/pckbcvar.h> 591.1Sross#include <dev/pci/pcireg.h> 601.1Sross#include <dev/pci/pcivar.h> 611.1Sross 621.1Sross#include <alpha/pci/tsreg.h> 631.1Sross#include <alpha/pci/tsvar.h> 641.1Sross 651.1Sross#include <dev/scsipi/scsi_all.h> 661.1Sross#include <dev/scsipi/scsipi_all.h> 671.1Sross#include <dev/scsipi/scsiconf.h> 681.3Sveego#include <dev/ata/atavar.h> 691.1Sross 701.29Smhitch#include <dev/ic/mlxio.h> 711.29Smhitch#include <dev/ic/mlxvar.h> 721.29Smhitch 731.29Smhitch#include <dev/i2o/i2o.h> 741.29Smhitch#include <dev/i2o/iopio.h> 751.29Smhitch#include <dev/i2o/iopvar.h> 761.29Smhitch 771.1Sross#include "pckbd.h" 781.1Sross 791.1Sross#ifndef CONSPEED 801.1Sross#define CONSPEED TTYDEF_SPEED 811.1Sross#endif 821.1Sross 831.1Sross#define DR_VERBOSE(f) while (0) 841.1Sross 851.1Srossstatic int comcnrate __attribute__((unused)) = CONSPEED; 861.1Sross 871.27Sdslvoid dec_6600_init(void); 881.27Sdslstatic void dec_6600_cons_init(void); 891.31Smattstatic void dec_6600_device_register(device_t, void *); 901.30Shansstatic void dec_6600_mcheck(unsigned long, struct ev6_logout_area *); 911.30Shansstatic void dec_6600_mcheck_sys(unsigned int, struct ev6_logout_area *); 921.30Shansstatic void dec_6600_mcheck_handler(unsigned long, struct trapframe *, 931.30Shans unsigned long, unsigned long); 941.1Sross 951.9Sthorpej#ifdef KGDB 961.9Sthorpej#include <machine/db_machdep.h> 971.9Sthorpej 981.9Sthorpejstatic const char *kgdb_devlist[] = { 991.9Sthorpej "com", 1001.9Sthorpej NULL, 1011.9Sthorpej}; 1021.9Sthorpej#endif /* KGDB */ 1031.9Sthorpej 1041.1Srossvoid 1051.33Smattdec_6600_init(void) 1061.1Sross{ 1071.1Sross 1081.1Sross platform.family = "6600"; 1091.1Sross 1101.1Sross if ((platform.model = alpha_dsr_sysname()) == NULL) { 1111.1Sross /* XXX Don't know the system variations, yet. */ 1121.1Sross platform.model = alpha_unknown_sysname(); 1131.1Sross } 1141.1Sross 1151.1Sross platform.iobus = "tsc"; 1161.1Sross platform.cons_init = dec_6600_cons_init; 1171.1Sross platform.device_register = dec_6600_device_register; 1181.30Shans platform.mcheck_handler = dec_6600_mcheck_handler; 1191.30Shans 1201.30Shans /* enable Cchip and Pchip error interrupts */ 1211.30Shans STQP(TS_C_DIM0) = 0xe000000000000000; 1221.30Shans STQP(TS_C_DIM1) = 0xe000000000000000; 1231.1Sross} 1241.1Sross 1251.1Srossstatic void 1261.33Smattdec_6600_cons_init(void) 1271.1Sross{ 1281.1Sross struct ctb *ctb; 1291.33Smatt uint64_t ctbslot; 1301.1Sross struct tsp_config *tsp; 1311.1Sross 1321.26Syamt ctb = (struct ctb *)(((char *)hwrpb) + hwrpb->rpb_ctb_off); 1331.1Sross ctbslot = ctb->ctb_turboslot; 1341.1Sross 1351.8Sthorpej /* Console hose defaults to hose 0. */ 1361.8Sthorpej tsp_console_hose = 0; 1371.8Sthorpej 1381.8Sthorpej tsp = tsp_init(0, tsp_console_hose); 1391.1Sross 1401.1Sross switch (ctb->ctb_term_type) { 1411.33Smatt case CTB_PRINTERPORT: 1421.1Sross /* serial console ... */ 1431.1Sross assert(CTB_TURBOSLOT_HOSE(ctbslot) == 0); 1441.1Sross /* XXX */ 1451.1Sross { 1461.1Sross /* 1471.1Sross * Delay to allow PROM putchars to complete. 1481.1Sross * FIFO depth * character time, 1491.1Sross * character time = (1000000 / (defaultrate / 10)) 1501.1Sross */ 1511.1Sross DELAY(160000000 / comcnrate); 1521.1Sross 1531.1Sross if(comcnattach(&tsp->pc_iot, 0x3f8, comcnrate, 1541.18Sthorpej COM_FREQ, COM_TYPE_NORMAL, 1551.1Sross (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8)) 1561.1Sross panic("can't init serial console"); 1571.1Sross 1581.1Sross break; 1591.1Sross } 1601.1Sross 1611.12Sthorpej case CTB_GRAPHICS: 1621.1Sross#if NPCKBD > 0 1631.1Sross /* display console ... */ 1641.1Sross /* XXX */ 1651.6Ssoda (void) pckbc_cnattach(&tsp->pc_iot, IO_KBD, KBCMDP, 1661.34Sjdc PCKBC_KBD_SLOT, 0); 1671.1Sross 1681.1Sross if (CTB_TURBOSLOT_TYPE(ctbslot) == 1691.1Sross CTB_TURBOSLOT_TYPE_ISA) 1701.1Sross isa_display_console(&tsp->pc_iot, &tsp->pc_memt); 1711.1Sross else { 1721.1Sross /* The display PCI might be different */ 1731.8Sthorpej tsp_console_hose = CTB_TURBOSLOT_HOSE(ctbslot); 1741.8Sthorpej tsp = tsp_init(0, tsp_console_hose); 1751.1Sross pci_display_console(&tsp->pc_iot, &tsp->pc_memt, 1761.1Sross &tsp->pc_pc, CTB_TURBOSLOT_BUS(ctbslot), 1771.1Sross CTB_TURBOSLOT_SLOT(ctbslot), 0); 1781.1Sross } 1791.1Sross#else 1801.1Sross panic("not configured to use display && keyboard console"); 1811.1Sross#endif 1821.1Sross break; 1831.1Sross 1841.1Sross default: 1851.1Sross printf("ctb_term_type = 0x%lx ctb_turboslot = 0x%lx" 1861.1Sross " hose = %ld\n", ctb->ctb_term_type, ctbslot, 1871.1Sross CTB_TURBOSLOT_HOSE(ctbslot)); 1881.1Sross 1891.17Sprovos panic("consinit: unknown console type %ld", 1901.1Sross ctb->ctb_term_type); 1911.1Sross } 1921.9Sthorpej#ifdef KGDB 1931.9Sthorpej /* Attach the KGDB device. */ 1941.9Sthorpej alpha_kgdb_init(kgdb_devlist, &tsp->pc_iot); 1951.9Sthorpej#endif /* KGDB */ 1961.1Sross} 1971.1Sross 1981.1Srossstatic void 1991.31Smattdec_6600_device_register(device_t dev, void *aux) 2001.1Sross{ 2011.21Smycroft static int found, initted, diskboot, netboot; 2021.31Smatt static device_t primarydev, pcidev, ctrlrdev; 2031.1Sross struct bootdev_data *b = bootdev_data; 2041.31Smatt device_t parent = device_parent(dev); 2051.1Sross 2061.1Sross if (found) 2071.1Sross return; 2081.1Sross 2091.1Sross if (!initted) { 2101.21Smycroft diskboot = (strcasecmp(b->protocol, "SCSI") == 0) || 2111.29Smhitch (strcasecmp(b->protocol, "RAID") == 0) || 2121.29Smhitch (strcasecmp(b->protocol, "I2O") == 0) || 2131.21Smycroft (strcasecmp(b->protocol, "IDE") == 0); 2141.21Smycroft netboot = (strcasecmp(b->protocol, "BOOTP") == 0) || 2151.21Smycroft (strcasecmp(b->protocol, "MOP") == 0); 2161.21Smycroft DR_VERBOSE(printf("diskboot = %d, netboot = %d\n", diskboot, 2171.21Smycroft netboot)); 2181.1Sross initted = 1; 2191.1Sross } 2201.21Smycroft 2211.1Sross if (primarydev == NULL) { 2221.24Sthorpej if (!device_is_a(dev, "tsp")) 2231.1Sross return; 2241.1Sross else { 2251.1Sross struct tsp_attach_args *tsp = aux; 2261.1Sross 2271.1Sross if (b->bus != tsp->tsp_slot) 2281.1Sross return; 2291.1Sross primarydev = dev; 2301.1Sross DR_VERBOSE(printf("\nprimarydev = %s\n", 2311.31Smatt device_xname(dev))); 2321.1Sross return; 2331.1Sross } 2341.1Sross } 2351.21Smycroft 2361.1Sross if (pcidev == NULL) { 2371.24Sthorpej if (!device_is_a(dev, "pci")) 2381.1Sross return; 2391.21Smycroft /* 2401.21Smycroft * Try to find primarydev anywhere in the ancestry. This is 2411.21Smycroft * necessary if the PCI bus is hidden behind a bridge. 2421.21Smycroft */ 2431.21Smycroft while (parent) { 2441.21Smycroft if (parent == primarydev) 2451.21Smycroft break; 2461.23Sthorpej parent = device_parent(parent); 2471.21Smycroft } 2481.21Smycroft if (!parent) 2491.1Sross return; 2501.1Sross else { 2511.1Sross struct pcibus_attach_args *pba = aux; 2521.1Sross 2531.1Sross if ((b->slot / 1000) != pba->pba_bus) 2541.1Sross return; 2551.1Sross 2561.1Sross pcidev = dev; 2571.31Smatt DR_VERBOSE(printf("\npcidev = %s\n", device_xname(dev))); 2581.1Sross return; 2591.1Sross } 2601.1Sross } 2611.21Smycroft 2621.21Smycroft if (ctrlrdev == NULL) { 2631.1Sross if (parent != pcidev) 2641.1Sross return; 2651.1Sross else { 2661.1Sross struct pci_attach_args *pa = aux; 2671.21Smycroft int slot; 2681.1Sross 2691.21Smycroft slot = pa->pa_bus * 1000 + pa->pa_function * 100 + 2701.21Smycroft pa->pa_device; 2711.21Smycroft if (b->slot != slot) 2721.1Sross return; 2731.1Sross 2741.21Smycroft if (netboot) { 2751.21Smycroft booted_device = dev; 2761.21Smycroft DR_VERBOSE(printf("\nbooted_device = %s\n", 2771.31Smatt device_xname(dev))); 2781.21Smycroft found = 1; 2791.21Smycroft } else { 2801.21Smycroft ctrlrdev = dev; 2811.21Smycroft DR_VERBOSE(printf("\nctrlrdev = %s\n", 2821.31Smatt device_xname(dev))); 2831.21Smycroft } 2841.1Sross return; 2851.1Sross } 2861.1Sross } 2871.21Smycroft 2881.21Smycroft if (!diskboot) 2891.21Smycroft return; 2901.21Smycroft 2911.24Sthorpej if (device_is_a(dev, "sd") || 2921.24Sthorpej device_is_a(dev, "st") || 2931.24Sthorpej device_is_a(dev, "cd")) { 2941.1Sross struct scsipibus_attach_args *sa = aux; 2951.21Smycroft struct scsipi_periph *periph = sa->sa_periph; 2961.21Smycroft int unit; 2971.1Sross 2981.23Sthorpej if (device_parent(parent) != ctrlrdev) 2991.1Sross return; 3001.1Sross 3011.21Smycroft unit = periph->periph_target * 100 + periph->periph_lun; 3021.21Smycroft if (b->unit != unit) 3031.1Sross return; 3041.21Smycroft if (b->channel != periph->periph_channel->chan_channel) 3051.1Sross return; 3061.1Sross 3071.1Sross /* we've found it! */ 3081.1Sross booted_device = dev; 3091.31Smatt DR_VERBOSE(printf("\nbooted_device = %s\n", device_xname(dev))); 3101.1Sross found = 1; 3111.1Sross } 3121.1Sross 3131.29Smhitch if (device_is_a(dev, "ld") && device_is_a(parent, "iop")) { 3141.29Smhitch /* 3151.29Smhitch * Argh! The attach arguments for ld devices is not 3161.29Smhitch * consistent, so each supported raid controller requires 3171.29Smhitch * different checks. 3181.29Smhitch */ 3191.29Smhitch struct iop_attach_args *iopa = aux; 3201.29Smhitch 3211.29Smhitch if (parent != ctrlrdev) 3221.29Smhitch return; 3231.29Smhitch 3241.29Smhitch if (b->unit != iopa->ia_tid) 3251.29Smhitch return; 3261.29Smhitch /* we've found it! */ 3271.29Smhitch booted_device = dev; 3281.31Smatt DR_VERBOSE(printf("\nbooted_device = %s\n", device_xname(dev))); 3291.29Smhitch found = 1; 3301.29Smhitch } 3311.29Smhitch 3321.29Smhitch if (device_is_a(dev, "ld") && device_is_a(parent, "mlx")) { 3331.29Smhitch /* 3341.29Smhitch * Argh! The attach arguments for ld devices is not 3351.29Smhitch * consistent, so each supported raid controller requires 3361.29Smhitch * different checks. 3371.29Smhitch */ 3381.29Smhitch struct mlx_attach_args *mlxa = aux; 3391.29Smhitch 3401.29Smhitch if (parent != ctrlrdev) 3411.29Smhitch return; 3421.29Smhitch 3431.29Smhitch if (b->unit != mlxa->mlxa_unit) 3441.29Smhitch return; 3451.29Smhitch /* we've found it! */ 3461.29Smhitch booted_device = dev; 3471.31Smatt DR_VERBOSE(printf("\nbooted_device = %s\n", device_xname(dev))); 3481.29Smhitch found = 1; 3491.29Smhitch } 3501.29Smhitch 3511.1Sross /* 3521.1Sross * Support to boot from IDE drives. 3531.1Sross */ 3541.24Sthorpej if (device_is_a(dev, "wd")) { 3551.13Sbouyer struct ata_device *adev = aux; 3561.21Smycroft 3571.24Sthorpej if (!device_is_a(parent, "atabus")) 3581.1Sross return; 3591.23Sthorpej if (device_parent(parent) != ctrlrdev) 3601.21Smycroft return; 3611.21Smycroft 3621.3Sveego DR_VERBOSE(printf("\nAtapi info: drive: %d, channel %d\n", 3631.13Sbouyer adev->adev_drv_data->drive, adev->adev_channel)); 3641.3Sveego DR_VERBOSE(printf("Bootdev info: unit: %d, channel: %d\n", 3651.3Sveego b->unit, b->channel)); 3661.13Sbouyer if (b->unit != adev->adev_drv_data->drive || 3671.13Sbouyer b->channel != adev->adev_channel) 3681.3Sveego return; 3691.1Sross 3701.1Sross /* we've found it! */ 3711.1Sross booted_device = dev; 3721.31Smatt DR_VERBOSE(printf("booted_device = %s\n", device_xname(dev))); 3731.1Sross found = 1; 3741.1Sross } 3751.1Sross} 3761.30Shans 3771.30Shans 3781.30Shansstatic void 3791.30Shansdec_6600_mcheck(unsigned long vector, struct ev6_logout_area *la) 3801.30Shans{ 3811.30Shans const char *t = "Unknown", *c = ""; 3821.30Shans 3831.30Shans if (vector == ALPHA_SYS_ERROR || vector == ALPHA_PROC_ERROR) 3841.30Shans c = " Correctable"; 3851.30Shans 3861.30Shans switch (vector) { 3871.30Shans case ALPHA_SYS_ERROR: 3881.30Shans case ALPHA_SYS_MCHECK: 3891.30Shans t = "System"; 3901.30Shans break; 3911.30Shans 3921.30Shans case ALPHA_PROC_ERROR: 3931.30Shans case ALPHA_PROC_MCHECK: 3941.30Shans t = "Processor"; 3951.30Shans break; 3961.30Shans 3971.30Shans case ALPHA_ENV_MCHECK: 3981.30Shans t = "Environmental"; 3991.30Shans break; 4001.30Shans } 4011.30Shans 4021.30Shans printf("\n%s%s Machine Check (%lx): " 4031.30Shans "Rev 0x%x, Code 0x%x, Flags 0x%x\n\n", 4041.30Shans t, c, vector, la->mchk_rev, la->mchk_code, la->la.la_flags); 4051.30Shans} 4061.30Shans 4071.30Shansstatic void 4081.30Shansdec_6600_mcheck_sys(unsigned int indent, struct ev6_logout_area *la) 4091.30Shans{ 4101.33Smatt struct ev6_logout_sys *ls = 4111.30Shans (struct ev6_logout_sys *)ALPHA_LOGOUT_SYSTEM_AREA(&la->la); 4121.30Shans 4131.30Shans#define FMT "%-30s = 0x%016lx\n" 4141.30Shans 4151.30Shans IPRINTF(indent, FMT, "Software Error Summary Flags", ls->flags); 4161.30Shans 4171.30Shans IPRINTF(indent, FMT, "CPU Device Interrupt Requests", ls->dir); 4181.30Shans tsc_print_dir(indent + 1, ls->dir); 4191.30Shans 4201.30Shans IPRINTF(indent, FMT, "Cchip Miscellaneous Register", ls->misc); 4211.30Shans tsc_print_misc(indent + 1, ls->misc); 4221.30Shans 4231.30Shans IPRINTF(indent, FMT, "Pchip 0 Error Register", ls->p0_error); 4241.30Shans if (ls->flags & 0x5) 4251.30Shans tsp_print_error(indent + 1, ls->p0_error); 4261.30Shans 4271.30Shans IPRINTF(indent, FMT, "Pchip 1 Error Register", ls->p1_error); 4281.30Shans if (ls->flags & 0x6) 4291.30Shans tsp_print_error(indent + 1, ls->p1_error); 4301.30Shans} 4311.30Shans 4321.30Shansstatic void 4331.30Shansdec_6600_mcheck_handler(unsigned long mces, struct trapframe *framep, 4341.30Shans unsigned long vector, unsigned long param) 4351.30Shans{ 4361.30Shans struct mchkinfo *mcp; 4371.30Shans struct ev6_logout_area *la = (struct ev6_logout_area *)param; 4381.30Shans 4391.30Shans /* 4401.30Shans * If we expected a machine check, just go handle it in common code. 4411.30Shans */ 4421.30Shans mcp = &curcpu()->ci_mcinfo; 4431.33Smatt if (mcp->mc_expected) 4441.30Shans machine_check(mces, framep, vector, param); 4451.30Shans 4461.30Shans dec_6600_mcheck(vector, la); 4471.30Shans 4481.30Shans switch (vector) { 4491.30Shans case ALPHA_SYS_ERROR: 4501.30Shans case ALPHA_SYS_MCHECK: 4511.30Shans dec_6600_mcheck_sys(1, la); 4521.30Shans break; 4531.30Shans 4541.30Shans } 4551.30Shans 4561.30Shans machine_check(mces, framep, vector, param); 4571.30Shans} 458