dec_6600.c revision 1.31
11.31Smatt/* $NetBSD: dec_6600.c,v 1.31 2011/06/14 15:34:22 matt 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.1Sross * 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.1Sross * 151.1Sross * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 161.1Sross * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 171.1Sross * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 181.1Sross * 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.31Smatt__KERNEL_RCSID(0, "$NetBSD: dec_6600.c,v 1.31 2011/06/14 15:34:22 matt Exp $"); 351.1Sross 361.1Sross#include <sys/param.h> 371.1Sross#include <sys/systm.h> 381.1Sross#include <sys/device.h> 391.1Sross#include <sys/termios.h> 401.14Sgehenna#include <sys/conf.h> 411.1Sross#include <dev/cons.h> 421.1Sross 431.1Sross#include <machine/rpb.h> 441.1Sross#include <machine/autoconf.h> 451.14Sgehenna#include <machine/cpuconf.h> 461.1Sross#include <machine/bus.h> 471.30Shans#include <machine/alpha.h> 481.30Shans#include <machine/logout.h> 491.1Sross 501.1Sross#include <dev/ic/comreg.h> 511.1Sross#include <dev/ic/comvar.h> 521.1Sross 531.2Sthorpej#include <dev/isa/isareg.h> 541.1Sross#include <dev/isa/isavar.h> 551.6Ssoda#include <dev/ic/i8042reg.h> 561.2Sthorpej#include <dev/ic/pckbcvar.h> 571.1Sross#include <dev/pci/pcireg.h> 581.1Sross#include <dev/pci/pcivar.h> 591.1Sross 601.1Sross#include <alpha/pci/tsreg.h> 611.1Sross#include <alpha/pci/tsvar.h> 621.1Sross 631.1Sross#include <dev/scsipi/scsi_all.h> 641.1Sross#include <dev/scsipi/scsipi_all.h> 651.1Sross#include <dev/scsipi/scsiconf.h> 661.3Sveego#include <dev/ata/atavar.h> 671.1Sross 681.29Smhitch#include <dev/ic/mlxio.h> 691.29Smhitch#include <dev/ic/mlxvar.h> 701.29Smhitch 711.29Smhitch#include <dev/i2o/i2o.h> 721.29Smhitch#include <dev/i2o/iopio.h> 731.29Smhitch#include <dev/i2o/iopvar.h> 741.29Smhitch 751.1Sross#include "pckbd.h" 761.1Sross 771.1Sross#ifndef CONSPEED 781.1Sross#define CONSPEED TTYDEF_SPEED 791.1Sross#endif 801.1Sross 811.1Sross#define DR_VERBOSE(f) while (0) 821.1Sross 831.1Srossstatic int comcnrate __attribute__((unused)) = CONSPEED; 841.1Sross 851.27Sdslvoid dec_6600_init(void); 861.27Sdslstatic void dec_6600_cons_init(void); 871.31Smattstatic void dec_6600_device_register(device_t, void *); 881.30Shansstatic void dec_6600_mcheck(unsigned long, struct ev6_logout_area *); 891.30Shansstatic void dec_6600_mcheck_sys(unsigned int, struct ev6_logout_area *); 901.30Shansstatic void dec_6600_mcheck_handler(unsigned long, struct trapframe *, 911.30Shans unsigned long, unsigned long); 921.1Sross 931.9Sthorpej#ifdef KGDB 941.9Sthorpej#include <machine/db_machdep.h> 951.9Sthorpej 961.9Sthorpejstatic const char *kgdb_devlist[] = { 971.9Sthorpej "com", 981.9Sthorpej NULL, 991.9Sthorpej}; 1001.9Sthorpej#endif /* KGDB */ 1011.9Sthorpej 1021.1Srossvoid 1031.1Srossdec_6600_init() 1041.1Sross{ 1051.1Sross 1061.1Sross platform.family = "6600"; 1071.1Sross 1081.1Sross if ((platform.model = alpha_dsr_sysname()) == NULL) { 1091.1Sross /* XXX Don't know the system variations, yet. */ 1101.1Sross platform.model = alpha_unknown_sysname(); 1111.1Sross } 1121.1Sross 1131.1Sross platform.iobus = "tsc"; 1141.1Sross platform.cons_init = dec_6600_cons_init; 1151.1Sross platform.device_register = dec_6600_device_register; 1161.30Shans platform.mcheck_handler = dec_6600_mcheck_handler; 1171.30Shans 1181.30Shans /* enable Cchip and Pchip error interrupts */ 1191.30Shans STQP(TS_C_DIM0) = 0xe000000000000000; 1201.30Shans STQP(TS_C_DIM1) = 0xe000000000000000; 1211.1Sross} 1221.1Sross 1231.1Srossstatic void 1241.1Srossdec_6600_cons_init() 1251.1Sross{ 1261.1Sross struct ctb *ctb; 1271.1Sross u_int64_t ctbslot; 1281.1Sross struct tsp_config *tsp; 1291.1Sross 1301.26Syamt ctb = (struct ctb *)(((char *)hwrpb) + hwrpb->rpb_ctb_off); 1311.1Sross ctbslot = ctb->ctb_turboslot; 1321.1Sross 1331.8Sthorpej /* Console hose defaults to hose 0. */ 1341.8Sthorpej tsp_console_hose = 0; 1351.8Sthorpej 1361.8Sthorpej tsp = tsp_init(0, tsp_console_hose); 1371.1Sross 1381.1Sross switch (ctb->ctb_term_type) { 1391.12Sthorpej case CTB_PRINTERPORT: 1401.1Sross /* serial console ... */ 1411.1Sross assert(CTB_TURBOSLOT_HOSE(ctbslot) == 0); 1421.1Sross /* XXX */ 1431.1Sross { 1441.1Sross /* 1451.1Sross * Delay to allow PROM putchars to complete. 1461.1Sross * FIFO depth * character time, 1471.1Sross * character time = (1000000 / (defaultrate / 10)) 1481.1Sross */ 1491.1Sross DELAY(160000000 / comcnrate); 1501.1Sross 1511.1Sross if(comcnattach(&tsp->pc_iot, 0x3f8, comcnrate, 1521.18Sthorpej COM_FREQ, COM_TYPE_NORMAL, 1531.1Sross (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8)) 1541.1Sross panic("can't init serial console"); 1551.1Sross 1561.1Sross break; 1571.1Sross } 1581.1Sross 1591.12Sthorpej case CTB_GRAPHICS: 1601.1Sross#if NPCKBD > 0 1611.1Sross /* display console ... */ 1621.1Sross /* XXX */ 1631.6Ssoda (void) pckbc_cnattach(&tsp->pc_iot, IO_KBD, KBCMDP, 1641.6Ssoda PCKBC_KBD_SLOT); 1651.1Sross 1661.1Sross if (CTB_TURBOSLOT_TYPE(ctbslot) == 1671.1Sross CTB_TURBOSLOT_TYPE_ISA) 1681.1Sross isa_display_console(&tsp->pc_iot, &tsp->pc_memt); 1691.1Sross else { 1701.1Sross /* The display PCI might be different */ 1711.8Sthorpej tsp_console_hose = CTB_TURBOSLOT_HOSE(ctbslot); 1721.8Sthorpej tsp = tsp_init(0, tsp_console_hose); 1731.1Sross pci_display_console(&tsp->pc_iot, &tsp->pc_memt, 1741.1Sross &tsp->pc_pc, CTB_TURBOSLOT_BUS(ctbslot), 1751.1Sross CTB_TURBOSLOT_SLOT(ctbslot), 0); 1761.1Sross } 1771.1Sross#else 1781.1Sross panic("not configured to use display && keyboard console"); 1791.1Sross#endif 1801.1Sross break; 1811.1Sross 1821.1Sross default: 1831.1Sross printf("ctb_term_type = 0x%lx ctb_turboslot = 0x%lx" 1841.1Sross " hose = %ld\n", ctb->ctb_term_type, ctbslot, 1851.1Sross CTB_TURBOSLOT_HOSE(ctbslot)); 1861.1Sross 1871.17Sprovos panic("consinit: unknown console type %ld", 1881.1Sross ctb->ctb_term_type); 1891.1Sross } 1901.9Sthorpej#ifdef KGDB 1911.9Sthorpej /* Attach the KGDB device. */ 1921.9Sthorpej alpha_kgdb_init(kgdb_devlist, &tsp->pc_iot); 1931.9Sthorpej#endif /* KGDB */ 1941.1Sross} 1951.1Sross 1961.1Srossstatic void 1971.31Smattdec_6600_device_register(device_t dev, void *aux) 1981.1Sross{ 1991.21Smycroft static int found, initted, diskboot, netboot; 2001.31Smatt static device_t primarydev, pcidev, ctrlrdev; 2011.1Sross struct bootdev_data *b = bootdev_data; 2021.31Smatt device_t parent = device_parent(dev); 2031.1Sross 2041.1Sross if (found) 2051.1Sross return; 2061.1Sross 2071.1Sross if (!initted) { 2081.21Smycroft diskboot = (strcasecmp(b->protocol, "SCSI") == 0) || 2091.29Smhitch (strcasecmp(b->protocol, "RAID") == 0) || 2101.29Smhitch (strcasecmp(b->protocol, "I2O") == 0) || 2111.21Smycroft (strcasecmp(b->protocol, "IDE") == 0); 2121.21Smycroft netboot = (strcasecmp(b->protocol, "BOOTP") == 0) || 2131.21Smycroft (strcasecmp(b->protocol, "MOP") == 0); 2141.21Smycroft DR_VERBOSE(printf("diskboot = %d, netboot = %d\n", diskboot, 2151.21Smycroft netboot)); 2161.1Sross initted = 1; 2171.1Sross } 2181.21Smycroft 2191.1Sross if (primarydev == NULL) { 2201.24Sthorpej if (!device_is_a(dev, "tsp")) 2211.1Sross return; 2221.1Sross else { 2231.1Sross struct tsp_attach_args *tsp = aux; 2241.1Sross 2251.1Sross if (b->bus != tsp->tsp_slot) 2261.1Sross return; 2271.1Sross primarydev = dev; 2281.1Sross DR_VERBOSE(printf("\nprimarydev = %s\n", 2291.31Smatt device_xname(dev))); 2301.1Sross return; 2311.1Sross } 2321.1Sross } 2331.21Smycroft 2341.1Sross if (pcidev == NULL) { 2351.24Sthorpej if (!device_is_a(dev, "pci")) 2361.1Sross return; 2371.21Smycroft /* 2381.21Smycroft * Try to find primarydev anywhere in the ancestry. This is 2391.21Smycroft * necessary if the PCI bus is hidden behind a bridge. 2401.21Smycroft */ 2411.21Smycroft while (parent) { 2421.21Smycroft if (parent == primarydev) 2431.21Smycroft break; 2441.23Sthorpej parent = device_parent(parent); 2451.21Smycroft } 2461.21Smycroft if (!parent) 2471.1Sross return; 2481.1Sross else { 2491.1Sross struct pcibus_attach_args *pba = aux; 2501.1Sross 2511.1Sross if ((b->slot / 1000) != pba->pba_bus) 2521.1Sross return; 2531.1Sross 2541.1Sross pcidev = dev; 2551.31Smatt DR_VERBOSE(printf("\npcidev = %s\n", device_xname(dev))); 2561.1Sross return; 2571.1Sross } 2581.1Sross } 2591.21Smycroft 2601.21Smycroft if (ctrlrdev == NULL) { 2611.1Sross if (parent != pcidev) 2621.1Sross return; 2631.1Sross else { 2641.1Sross struct pci_attach_args *pa = aux; 2651.21Smycroft int slot; 2661.1Sross 2671.21Smycroft slot = pa->pa_bus * 1000 + pa->pa_function * 100 + 2681.21Smycroft pa->pa_device; 2691.21Smycroft if (b->slot != slot) 2701.1Sross return; 2711.1Sross 2721.21Smycroft if (netboot) { 2731.21Smycroft booted_device = dev; 2741.21Smycroft DR_VERBOSE(printf("\nbooted_device = %s\n", 2751.31Smatt device_xname(dev))); 2761.21Smycroft found = 1; 2771.21Smycroft } else { 2781.21Smycroft ctrlrdev = dev; 2791.21Smycroft DR_VERBOSE(printf("\nctrlrdev = %s\n", 2801.31Smatt device_xname(dev))); 2811.21Smycroft } 2821.1Sross return; 2831.1Sross } 2841.1Sross } 2851.21Smycroft 2861.21Smycroft if (!diskboot) 2871.21Smycroft return; 2881.21Smycroft 2891.24Sthorpej if (device_is_a(dev, "sd") || 2901.24Sthorpej device_is_a(dev, "st") || 2911.24Sthorpej device_is_a(dev, "cd")) { 2921.1Sross struct scsipibus_attach_args *sa = aux; 2931.21Smycroft struct scsipi_periph *periph = sa->sa_periph; 2941.21Smycroft int unit; 2951.1Sross 2961.23Sthorpej if (device_parent(parent) != ctrlrdev) 2971.1Sross return; 2981.1Sross 2991.21Smycroft unit = periph->periph_target * 100 + periph->periph_lun; 3001.21Smycroft if (b->unit != unit) 3011.1Sross return; 3021.21Smycroft if (b->channel != periph->periph_channel->chan_channel) 3031.1Sross return; 3041.1Sross 3051.1Sross /* we've found it! */ 3061.1Sross booted_device = dev; 3071.31Smatt DR_VERBOSE(printf("\nbooted_device = %s\n", device_xname(dev))); 3081.1Sross found = 1; 3091.1Sross } 3101.1Sross 3111.29Smhitch if (device_is_a(dev, "ld") && device_is_a(parent, "iop")) { 3121.29Smhitch /* 3131.29Smhitch * Argh! The attach arguments for ld devices is not 3141.29Smhitch * consistent, so each supported raid controller requires 3151.29Smhitch * different checks. 3161.29Smhitch */ 3171.29Smhitch struct iop_attach_args *iopa = aux; 3181.29Smhitch 3191.29Smhitch if (parent != ctrlrdev) 3201.29Smhitch return; 3211.29Smhitch 3221.29Smhitch if (b->unit != iopa->ia_tid) 3231.29Smhitch return; 3241.29Smhitch /* we've found it! */ 3251.29Smhitch booted_device = dev; 3261.31Smatt DR_VERBOSE(printf("\nbooted_device = %s\n", device_xname(dev))); 3271.29Smhitch found = 1; 3281.29Smhitch } 3291.29Smhitch 3301.29Smhitch if (device_is_a(dev, "ld") && device_is_a(parent, "mlx")) { 3311.29Smhitch /* 3321.29Smhitch * Argh! The attach arguments for ld devices is not 3331.29Smhitch * consistent, so each supported raid controller requires 3341.29Smhitch * different checks. 3351.29Smhitch */ 3361.29Smhitch struct mlx_attach_args *mlxa = aux; 3371.29Smhitch 3381.29Smhitch if (parent != ctrlrdev) 3391.29Smhitch return; 3401.29Smhitch 3411.29Smhitch if (b->unit != mlxa->mlxa_unit) 3421.29Smhitch return; 3431.29Smhitch /* we've found it! */ 3441.29Smhitch booted_device = dev; 3451.31Smatt DR_VERBOSE(printf("\nbooted_device = %s\n", device_xname(dev))); 3461.29Smhitch found = 1; 3471.29Smhitch } 3481.29Smhitch 3491.1Sross /* 3501.1Sross * Support to boot from IDE drives. 3511.1Sross */ 3521.24Sthorpej if (device_is_a(dev, "wd")) { 3531.13Sbouyer struct ata_device *adev = aux; 3541.21Smycroft 3551.24Sthorpej if (!device_is_a(parent, "atabus")) 3561.1Sross return; 3571.23Sthorpej if (device_parent(parent) != ctrlrdev) 3581.21Smycroft return; 3591.21Smycroft 3601.3Sveego DR_VERBOSE(printf("\nAtapi info: drive: %d, channel %d\n", 3611.13Sbouyer adev->adev_drv_data->drive, adev->adev_channel)); 3621.3Sveego DR_VERBOSE(printf("Bootdev info: unit: %d, channel: %d\n", 3631.3Sveego b->unit, b->channel)); 3641.13Sbouyer if (b->unit != adev->adev_drv_data->drive || 3651.13Sbouyer b->channel != adev->adev_channel) 3661.3Sveego return; 3671.1Sross 3681.1Sross /* we've found it! */ 3691.1Sross booted_device = dev; 3701.31Smatt DR_VERBOSE(printf("booted_device = %s\n", device_xname(dev))); 3711.1Sross found = 1; 3721.1Sross } 3731.1Sross} 3741.30Shans 3751.30Shans 3761.30Shansstatic void 3771.30Shansdec_6600_mcheck(unsigned long vector, struct ev6_logout_area *la) 3781.30Shans{ 3791.30Shans const char *t = "Unknown", *c = ""; 3801.30Shans 3811.30Shans if (vector == ALPHA_SYS_ERROR || vector == ALPHA_PROC_ERROR) 3821.30Shans c = " Correctable"; 3831.30Shans 3841.30Shans switch (vector) { 3851.30Shans case ALPHA_SYS_ERROR: 3861.30Shans case ALPHA_SYS_MCHECK: 3871.30Shans t = "System"; 3881.30Shans break; 3891.30Shans 3901.30Shans case ALPHA_PROC_ERROR: 3911.30Shans case ALPHA_PROC_MCHECK: 3921.30Shans t = "Processor"; 3931.30Shans break; 3941.30Shans 3951.30Shans case ALPHA_ENV_MCHECK: 3961.30Shans t = "Environmental"; 3971.30Shans break; 3981.30Shans } 3991.30Shans 4001.30Shans printf("\n%s%s Machine Check (%lx): " 4011.30Shans "Rev 0x%x, Code 0x%x, Flags 0x%x\n\n", 4021.30Shans t, c, vector, la->mchk_rev, la->mchk_code, la->la.la_flags); 4031.30Shans} 4041.30Shans 4051.30Shansstatic void 4061.30Shansdec_6600_mcheck_sys(unsigned int indent, struct ev6_logout_area *la) 4071.30Shans{ 4081.30Shans struct ev6_logout_sys *ls = 4091.30Shans (struct ev6_logout_sys *)ALPHA_LOGOUT_SYSTEM_AREA(&la->la); 4101.30Shans 4111.30Shans#define FMT "%-30s = 0x%016lx\n" 4121.30Shans 4131.30Shans IPRINTF(indent, FMT, "Software Error Summary Flags", ls->flags); 4141.30Shans 4151.30Shans IPRINTF(indent, FMT, "CPU Device Interrupt Requests", ls->dir); 4161.30Shans tsc_print_dir(indent + 1, ls->dir); 4171.30Shans 4181.30Shans IPRINTF(indent, FMT, "Cchip Miscellaneous Register", ls->misc); 4191.30Shans tsc_print_misc(indent + 1, ls->misc); 4201.30Shans 4211.30Shans IPRINTF(indent, FMT, "Pchip 0 Error Register", ls->p0_error); 4221.30Shans if (ls->flags & 0x5) 4231.30Shans tsp_print_error(indent + 1, ls->p0_error); 4241.30Shans 4251.30Shans IPRINTF(indent, FMT, "Pchip 1 Error Register", ls->p1_error); 4261.30Shans if (ls->flags & 0x6) 4271.30Shans tsp_print_error(indent + 1, ls->p1_error); 4281.30Shans} 4291.30Shans 4301.30Shansstatic void 4311.30Shansdec_6600_mcheck_handler(unsigned long mces, struct trapframe *framep, 4321.30Shans unsigned long vector, unsigned long param) 4331.30Shans{ 4341.30Shans struct mchkinfo *mcp; 4351.30Shans struct ev6_logout_area *la = (struct ev6_logout_area *)param; 4361.30Shans 4371.30Shans /* 4381.30Shans * If we expected a machine check, just go handle it in common code. 4391.30Shans */ 4401.30Shans mcp = &curcpu()->ci_mcinfo; 4411.30Shans if (mcp->mc_expected) 4421.30Shans machine_check(mces, framep, vector, param); 4431.30Shans 4441.30Shans dec_6600_mcheck(vector, la); 4451.30Shans 4461.30Shans switch (vector) { 4471.30Shans case ALPHA_SYS_ERROR: 4481.30Shans case ALPHA_SYS_MCHECK: 4491.30Shans dec_6600_mcheck_sys(1, la); 4501.30Shans break; 4511.30Shans 4521.30Shans } 4531.30Shans 4541.30Shans machine_check(mces, framep, vector, param); 4551.30Shans} 456