Provide attaching hpc devices with the eeprom contents, should a chip be

connected to the HPC. The only real reason for doing this is to get the
mac addresses off of E++ ethernet boards and the Challenge S IOPLUS board.
If no eeprom is present, we read in invalid data and take some default
action (query ARCBIOS).
This commit is contained in:
rumble 2006-12-22 08:17:14 +00:00
parent 0ff4104d82
commit 121e1e9bfa
4 changed files with 88 additions and 14 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: hpc.c,v 1.41 2006/12/22 05:26:01 rumble Exp $ */
/* $NetBSD: hpc.c,v 1.42 2006/12/22 08:17:14 rumble Exp $ */
/*
* Copyright (c) 2000 Soren S. Jorvang
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.41 2006/12/22 05:26:01 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.42 2006/12/22 08:17:14 rumble Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -55,6 +55,8 @@ __KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.41 2006/12/22 05:26:01 rumble Exp $");
#include <sgimips/hpc/hpcreg.h>
#include <sgimips/ioc/iocreg.h>
#include <dev/ic/smc93cx6var.h>
#include "locators.h"
static const struct hpc_device {
@ -339,6 +341,9 @@ static struct callout hpc_blink_ch = CALLOUT_INITIALIZER;
static void hpc_blink(void *);
#endif
static int hpc_read_eeprom(int, bus_space_tag_t, bus_space_handle_t,
uint8_t *, size_t);
CFATTACH_DECL(hpc, sizeof(struct hpc_softc),
hpc_match, hpc_attach, NULL, NULL);
@ -417,6 +422,8 @@ hpc_attach(struct device *parent, struct device *self, void *aux)
else
ha.hpc_regs = &hpc1_values;
ha.hpc_regs->revision = hpctype;
hpc_read_eeprom(hpctype, ha.ha_st, ha.ha_sh, ha.hpc_eeprom,
sizeof(ha.hpc_eeprom));
(void) config_found_sm_loc(self, "hpc", NULL, &ha, hpc_print,
hpc_submatch);
@ -592,3 +599,49 @@ hpc_blink(void *self)
}
#endif
/*
* Read the eeprom associated with one of the HPC's.
*
* NB: An eeprom is not always present, but the HPC should be able to
* handle this gracefully. Any consumers should validate the data to
* ensure it's reasonable.
*/
static int
hpc_read_eeprom(int hpctype, bus_space_tag_t t, bus_space_handle_t h,
uint8_t *buf, size_t len)
{
struct seeprom_descriptor sd;
bus_space_handle_t bsh;
bus_space_tag_t tag;
bus_size_t offset;
if (!len || len & 0x1)
return (1);
offset = (hpctype == 3) ? HPC3_EEPROM_DATA : HPC1_AUX_EEPROM;
tag = SGIMIPS_BUS_SPACE_NORMAL;
if (bus_space_subregion(t, h, offset, 1, &bsh) != 0)
return (1);
sd.sd_chip = C56_66;
sd.sd_tag = tag;
sd.sd_bsh = bsh;
sd.sd_regsize = 1;
sd.sd_control_offset = 0;
sd.sd_status_offset = 0;
sd.sd_dataout_offset = 0;
sd.sd_DI = 0x10; /* EEPROM -> CPU */
sd.sd_DO = 0x08; /* CPU -> EEPROM */
sd.sd_CK = 0x04;
sd.sd_CS = 0x02;
sd.sd_MS = 0;
sd.sd_RDY = 0;
if (read_seeprom(&sd, (uint16_t *)buf, 0, len / 2) != 1)
return (1);
bus_space_unmap(t, bsh, 1);
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: hpcreg.h,v 1.15 2006/12/22 05:08:56 rumble Exp $ */
/* $NetBSD: hpcreg.h,v 1.16 2006/12/22 08:17:14 rumble Exp $ */
/*
* Copyright (c) 2001 Rafal K. Boni
@ -253,7 +253,8 @@ struct hpc_dma_desc {
#define HPC3_GIO_MISC 0x00030004 /* GIO64 misc register */
#define HPC3_EEPROM_DATA 0x00030008 /* Serial EEPROM data reg. */
#define HPC3_EEPROM_DATA 0x0003000b /* Serial EEPROM data reg. */
/* (byte) */
#define HPC3_GIO_BUSERR 0x00030010 /* GIO64 bus error intr stat */
@ -455,8 +456,8 @@ struct hpc_dma_desc {
#define HPC1_LPT_DMACFG 0x00000014 /* DMA Configuration */
#define HPC1_LPT_DEVREGS 0x00000132 /* Ext. Parallel Registers */
#define HPC1_LPT_DEVREGS_SIZE 0x00000001 /* Size of External Registers */
#define HPC1_AUX_REGS 0x1fb801bc /* Serial EEPROM/LED Control */
#define HPC1_AUX_REGS_SIZE 0x00000001 /* One Byte */
#define HPC1_AUX_LED 0x000001bc /* LED Control (byte) */
#define HPC1_AUX_CONSLED 0x01 /* Console LED */
#define HPC1_AUX_EEPROM 0x000001bf /* Serial EEPROM Control(byte)*/
#endif /* _ARCH_SGIMIPS_HPC_HPCREG_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: hpcvar.h,v 1.8 2005/12/11 12:18:53 christos Exp $ */
/* $NetBSD: hpcvar.h,v 1.9 2006/12/22 08:17:14 rumble Exp $ */
/*
* Copyright (c) 2001 Rafal K. Boni
@ -114,6 +114,8 @@ struct hpc_attach_args {
bus_dma_tag_t ha_dmat; /* HPC DMA tag */
struct hpc_values *hpc_regs; /* HPC register definitions */
uint8_t hpc_eeprom[256];/* HPC eeprom contents */
};
#endif /* _ARCH_SGIMIPS_HPC_HPCVAR_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_sq.c,v 1.29 2005/12/11 12:18:53 christos Exp $ */
/* $NetBSD: if_sq.c,v 1.30 2006/12/22 08:17:14 rumble Exp $ */
/*
* Copyright (c) 2001 Rafal K. Boni
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_sq.c,v 1.29 2005/12/11 12:18:53 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_sq.c,v 1.30 2006/12/22 08:17:14 rumble Exp $");
#include "bpfilter.h"
@ -137,6 +137,13 @@ CFATTACH_DECL(sq, sizeof(struct sq_softc),
#define sq_hpc_write(sc, off, val) \
bus_space_write_4(sc->sc_hpct, sc->sc_hpch, off, val)
/* MAC address offset for non-onboard implementations */
#define SQ_HPC_EEPROM_ENADDR 250
#define SGI_OUI_0 0x08
#define SGI_OUI_1 0x00
#define SGI_OUI_2 0x69
static int
sq_match(struct device *parent, struct cfdata *cf, void *aux)
{
@ -243,9 +250,22 @@ sq_attach(struct device *parent, struct device *self, void *aux)
}
}
if ((macaddr = ARCBIOS->GetEnvironmentVariable("eaddr")) == NULL) {
printf(": unable to get MAC address!\n");
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;
}
enaddr_aton(macaddr, sc->sc_enaddr);
}
evcnt_attach_dynamic(&sc->sq_intrcnt, EVCNT_TYPE_INTR, NULL,
@ -275,8 +295,6 @@ sq_attach(struct device *parent, struct device *self, void *aux)
printf(": SGI Seeq %s\n",
sc->sc_type == SQ_TYPE_80C03 ? "80c03" : "8003");
enaddr_aton(macaddr, sc->sc_enaddr);
printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
ether_sprintf(sc->sc_enaddr));