void zscninit(struct consdev *cn) { extern const struct cdevsw zstty_cdevsw; const char* consdev; if ((consdev = arcbios_GetEnvironmentVariable("ConsoleOut")) == NULL) panic("zscninit without valid ARCS ConsoleOut setting!"); if (strlen(consdev) != 9 || strncmp(consdev, "serial", 6) != 0) panic("zscninit with ARCS console not set to serial!"); cons_port = consdev[7] - '0'; #if 0 /* * If your IP12 serial console goes missing after consinit(), * try flipping this the other way 'round. If there are some * IP12 machines that actually require this, we'll be in for * a lot of funnies once again... */ if (mach_type == MACH_SGI_IP12) cons_port = 1 - cons_port; #endif cn->cn_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), cons_port); cn->cn_pri = CN_REMOTE; /* Mark this unit as the console */ zs_consunit = 0; /* SGI hardware wires serial port 1 to channel B, port 2 to A */ if (cons_port == 0) zs_conschan = 1; else zs_conschan = 0; }
int main(int argc, char **argv) { const char *kernel = NULL; const char *bootpath = NULL; char bootfile[PATH_MAX]; void (*entry)(int, char *[], u_int, void *); u_long marks[MARK_MAX]; int win = 0; int i; int ch; /* print a banner */ printf("\n"); printf("%s Bootstrap, Revision %s\n", bootprog_name, bootprog_rev); memset(marks, 0, sizeof marks); /* initialise bootinfo structure early */ bi_init(bootinfo); #ifdef BOOT_DEBUG for (i = 0; i < argc; i++) printf("argv[%d] = %s\n", i, argv[i]); #endif /* Parse arguments, if present. */ while ((ch = getopt(argc, argv, "v")) != -1) { switch (ch) { case 'v': debug = 1; break; } } environment = &argv[1]; bootpath = firmware_getenv("OSLoadPartition"); if (bootpath == NULL) bootpath = arcbios_GetEnvironmentVariable("OSLoadPartition"); if (bootpath == NULL) { /* XXX need to actually do the fixup */ printf("OSLoadPartition is not specified.\n"); return 0; } DPRINTF("bootpath = %s\n", bootpath); /* * Grab OSLoadFilename from ARCS. */ kernel = firmware_getenv("OSLoadFilename"); if (kernel == NULL) kernel = arcbios_GetEnvironmentVariable("OSLoadFilename"); DPRINTF("kernel = %s\n", kernel ? kernel : "<null>"); /* * The first arg is assumed to contain the name of the kernel to boot, * if it a) does not start with a hyphen and b) does not contain * an equals sign. */ for (i = 1; i < argc; i++) { if (((strchr(argv[i], '=')) == NULL) && (argv[i][0] != '-')) { kernel = argv[i]; break; } } if (kernel != NULL) { /* * if the name contains parenthesis, we assume that it * contains the bootpath and ignore anything passed through * the environment */ if (strchr(kernel, '(')) win = loadfile(kernel, marks, LOAD_KERNEL); else { strcpy(bootfile, bootpath); strcat(bootfile, kernel); win = loadfile(bootfile, marks, LOAD_KERNEL); } } else { i = 1; while (kernelnames[i] != NULL) { strcpy(bootfile, bootpath); strcat(bootfile, kernelnames[i]); kernel = kernelnames[i]; win = loadfile(bootfile, marks, LOAD_KERNEL); if (win != -1) break; i++; } } if (win < 0) { printf("Boot failed! Halting...\n"); (void)getchar(); return 0; } strlcpy(bi_bpath.bootpath, kernel, BTINFO_BOOTPATH_LEN); bi_add(&bi_bpath, BTINFO_BOOTPATH, sizeof(bi_bpath)); bi_syms.nsym = marks[MARK_NSYM]; bi_syms.ssym = marks[MARK_SYM]; bi_syms.esym = marks[MARK_END]; bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms)); entry = (void *)marks[MARK_ENTRY]; if (debug) { printf("Starting at %p\n\n", entry); printf("nsym 0x%lx ssym 0x%lx esym 0x%lx\n", marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]); } (*entry)(argc, argv, BOOTINFO_MAGIC, bootinfo); printf("Kernel returned! Halting...\n"); return 0; }
/* * Attach a found zs. * * Match slave number to zs unit number, so that misconfiguration will * not set up the keyboard as ttya, etc. */ static void zs_hpc_attach(device_t parent, device_t self, void *aux) { struct zsc_softc *zsc = device_private(self); struct hpc_attach_args *haa = aux; struct zsc_attach_args zsc_args; struct zs_chanstate *cs; struct zs_channel *ch; int zs_unit, channel, err, s; const char *promconsdev; promconsdev = arcbios_GetEnvironmentVariable("ConsoleOut"); zsc->zsc_dev = self; zsc->zsc_bustag = haa->ha_st; if ((err = bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, 0x10, &zsc->zsc_base)) != 0) { aprint_error(": unable to map 85c30 registers, error = %d\n", err); return; } zs_unit = device_unit(self); aprint_normal("\n"); /* * Initialize software state for each channel. * * Done in reverse order of channels since the first serial port * is actually attached to the *second* channel, and vice versa. * Doing it this way should force a 'zstty*' to attach zstty0 to * channel 1 and zstty1 to channel 0. They couldn't have wired * it up in a more sensible fashion, could they? */ for (channel = 1; channel >= 0; channel--) { zsc_args.channel = channel; ch = &zsc->zsc_cs_store[channel]; cs = zsc->zsc_cs[channel] = (struct zs_chanstate *)ch; zs_lock_init(cs); cs->cs_reg_csr = NULL; cs->cs_reg_data = NULL; cs->cs_channel = channel; cs->cs_private = NULL; cs->cs_ops = &zsops_null; cs->cs_brg_clk = PCLK / 16; if (bus_space_subregion(zsc->zsc_bustag, zsc->zsc_base, zs_chan_offset[channel], sizeof(struct zschan), &ch->cs_regs) != 0) { aprint_error_dev(self, "cannot map regs\n"); return; } ch->cs_bustag = zsc->zsc_bustag; memcpy(cs->cs_creg, zs_init_reg, 16); memcpy(cs->cs_preg, zs_init_reg, 16); zsc_args.hwflags = 0; zsc_args.consdev = NULL; if (zs_consunit == -1 && zs_conschan == -1) { /* * If this channel is being used by the PROM console, * pass the generic zs driver a 'no reset' flag so the * channel gets left in the appropriate state after * attach. * * Note: the channel mappings are swapped. */ if (promconsdev != NULL && strlen(promconsdev) == 9 && strncmp(promconsdev, "serial", 6) == 0 && (promconsdev[7] == '0' || promconsdev[7] == '1')) { if (promconsdev[7] == '1' && channel == 0) zsc_args.hwflags |= ZS_HWFLAG_NORESET; else if (promconsdev[7] == '0' && channel == 1) zsc_args.hwflags |= ZS_HWFLAG_NORESET; } } /* If console, don't stomp speed, let zstty know */ if (zs_unit == zs_consunit && channel == zs_conschan) { zsc_args.consdev = &zs_cn; zsc_args.hwflags = ZS_HWFLAG_CONSOLE; cs->cs_defspeed = zs_get_speed(cs); } else cs->cs_defspeed = zs_defspeed; cs->cs_defcflag = zs_def_cflag; /* Make these correspond to cs_defcflag (-crtscts) */ cs->cs_rr0_dcd = ZSRR0_DCD; cs->cs_rr0_cts = 0; cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; cs->cs_wr5_rts = 0; /* * Clear the master interrupt enable. * The INTENA is common to both channels, * so just do it on the A channel. */ if (channel == 0) { zs_write_reg(cs, 9, 0); } /* * Look for a child driver for this channel. * The child attach will setup the hardware. */ if (!config_found(self, (void *)&zsc_args, zs_print)) { /* No sub-driver. Just reset it. */ uint8_t reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; s = splhigh(); zs_write_reg(cs, 9, reset); splx(s); } } zsc->sc_si = softint_establish(SOFTINT_SERIAL, zssoft, zsc); cpu_intr_establish(haa->ha_irq, IPL_TTY, zshard, NULL); evcnt_attach_dynamic(&zsc->zsc_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(self), "intr"); /* * Set the master interrupt enable and interrupt vector. * (common to both channels, do it on A) */ cs = zsc->zsc_cs[0]; s = splhigh(); /* interrupt vector */ zs_write_reg(cs, 2, zs_init_reg[2]); /* master interrupt control (enable) */ zs_write_reg(cs, 9, zs_init_reg[9]); splx(s); }
static void sq_attach(device_t parent, device_t self, void *aux) { int i, err; const char* macaddr; struct sq_softc *sc = device_private(self); struct hpc_attach_args *haa = aux; struct ifnet *ifp = &sc->sc_ethercom.ec_if; sc->sc_dev = self; sc->sc_hpct = haa->ha_st; sc->hpc_regs = haa->hpc_regs; /* HPC register definitions */ if ((err = bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_dmaoff, sc->hpc_regs->enet_regs_size, &sc->sc_hpch)) != 0) { printf(": unable to map HPC DMA registers, error = %d\n", err); goto fail_0; } sc->sc_regt = haa->ha_st; if ((err = bus_space_subregion(haa->ha_st, haa->ha_sh, haa->ha_devoff, sc->hpc_regs->enet_devregs_size, &sc->sc_regh)) != 0) { printf(": unable to map Seeq registers, error = %d\n", err); goto fail_0; } sc->sc_dmat = haa->ha_dmat; if ((err = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct sq_control), PAGE_SIZE, PAGE_SIZE, &sc->sc_cdseg, 1, &sc->sc_ncdseg, BUS_DMA_NOWAIT)) != 0) { printf(": unable to allocate control data, error = %d\n", err); goto fail_0; } if ((err = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg, sizeof(struct sq_control), (void **)&sc->sc_control, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { printf(": unable to map control data, error = %d\n", err); goto fail_1; } if ((err = bus_dmamap_create(sc->sc_dmat, sizeof(struct sq_control), 1, sizeof(struct sq_control), PAGE_SIZE, BUS_DMA_NOWAIT, &sc->sc_cdmap)) != 0) { printf(": unable to create DMA map for control data, error " "= %d\n", err); goto fail_2; } if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cdmap, sc->sc_control, sizeof(struct sq_control), NULL, BUS_DMA_NOWAIT)) != 0) { printf(": unable to load DMA map for control data, error " "= %d\n", err); goto fail_3; } memset(sc->sc_control, 0, sizeof(struct sq_control)); /* Create transmit buffer DMA maps */ for (i = 0; i < SQ_NTXDESC; i++) { if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_txmap[i])) != 0) { printf(": unable to create tx DMA map %d, error = %d\n", i, err); goto fail_4; } } /* Create receive buffer DMA maps */ for (i = 0; i < SQ_NRXDESC; i++) { if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_rxmap[i])) != 0) { printf(": unable to create rx DMA map %d, error = %d\n", i, err); goto fail_5; } } /* Pre-allocate the receive buffers. */ for (i = 0; i < SQ_NRXDESC; i++) { if ((err = sq_add_rxbuf(sc, i)) != 0) { printf(": unable to allocate or map rx buffer %d\n," " error = %d\n", i, err); goto fail_6; } } memcpy(sc->sc_enaddr, &haa->hpc_eeprom[SQ_HPC_EEPROM_ENADDR], ETHER_ADDR_LEN); /* * If our mac address is bogus, obtain it from ARCBIOS. This will * be true of the onboard HPC3 on IP22, since there is no eeprom, * but rather the DS1386 RTC's battery-backed ram is used. */ if (sc->sc_enaddr[0] != SGI_OUI_0 || sc->sc_enaddr[1] != SGI_OUI_1 || sc->sc_enaddr[2] != SGI_OUI_2) { macaddr = arcbios_GetEnvironmentVariable("eaddr"); if (macaddr == NULL) { printf(": unable to get MAC address!\n"); goto fail_6; } ether_aton_r(sc->sc_enaddr, sizeof(sc->sc_enaddr), macaddr); } evcnt_attach_dynamic(&sc->sq_intrcnt, EVCNT_TYPE_INTR, NULL, device_xname(self), "intr"); if ((cpu_intr_establish(haa->ha_irq, IPL_NET, sq_intr, sc)) == NULL) { printf(": unable to establish interrupt!\n"); goto fail_6; } /* Reset the chip to a known state. */ sq_reset(sc); /* * Determine if we're an 8003 or 80c03 by setting the first * MAC address register to non-zero, and then reading it back. * If it's zero, we have an 80c03, because we will have read * the TxCollLSB register. */ sq_seeq_write(sc, SEEQ_TXCOLLS0, 0xa5); if (sq_seeq_read(sc, SEEQ_TXCOLLS0) == 0) sc->sc_type = SQ_TYPE_80C03; else sc->sc_type = SQ_TYPE_8003; sq_seeq_write(sc, SEEQ_TXCOLLS0, 0x00); printf(": SGI Seeq %s\n", sc->sc_type == SQ_TYPE_80C03 ? "80c03" : "8003"); printf("%s: Ethernet address %s\n", device_xname(self), ether_sprintf(sc->sc_enaddr)); strcpy(ifp->if_xname, device_xname(self)); ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; ifp->if_init = sq_init; ifp->if_stop = sq_stop; ifp->if_start = sq_start; ifp->if_ioctl = sq_ioctl; ifp->if_watchdog = sq_watchdog; ifp->if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_MULTICAST; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); ether_ifattach(ifp, sc->sc_enaddr); memset(&sc->sq_trace, 0, sizeof(sc->sq_trace)); /* Done! */ return; /* * Free any resources we've allocated during the failed attach * attempt. Do this in reverse order and fall through. */ fail_6: for (i = 0; i < SQ_NRXDESC; i++) { if (sc->sc_rxmbuf[i] != NULL) { bus_dmamap_unload(sc->sc_dmat, sc->sc_rxmap[i]); m_freem(sc->sc_rxmbuf[i]); } } fail_5: for (i = 0; i < SQ_NRXDESC; i++) { if (sc->sc_rxmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxmap[i]); } fail_4: for (i = 0; i < SQ_NTXDESC; i++) { if (sc->sc_txmap[i] != NULL) bus_dmamap_destroy(sc->sc_dmat, sc->sc_txmap[i]); } bus_dmamap_unload(sc->sc_dmat, sc->sc_cdmap); fail_3: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cdmap); fail_2: bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control, sizeof(struct sq_control)); fail_1: bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg); fail_0: return; }