<commit_before>/*	$OpenBSD: mbg.c,v 1.10 2006/12/30 23:44:58 mbalmer Exp $ */

/*
 * Copyright (c) 2006 <NAME> <<EMAIL>>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/sensors.h>
#include <sys/syslog.h>
#include <sys/time.h>

#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

struct mbg_softc {
	struct device		sc_dev;
	bus_space_tag_t		sc_iot;
	bus_space_handle_t	sc_ioh;

	struct sensor		sc_timedelta;
	struct sensor		sc_signal;
	struct sensordev	sc_sensordev;
	u_int8_t		sc_status;

	int			(*sc_read)(struct mbg_softc *, int cmd,
				    char *buf, size_t len,
				    struct timespec *tstamp);
};

struct mbg_time {
	u_int8_t		hundreds;
	u_int8_t		sec;
	u_int8_t		min;
	u_int8_t		hour;
	u_int8_t		mday;
	u_int8_t		wday;
	u_int8_t		mon;
	u_int8_t		year;
	u_int8_t		status;
	u_int8_t		signal;
	int8_t			utc_off;
};

/* mbg_time.status bits */
#define MBG_FREERUN		0x01	/* clock running on xtal */
#define MBG_DST_ENA		0x02	/* DST enabled */
#define MBG_SYNC		0x04	/* clock synced at least once */
#define MBG_DST_CHG		0x08	/* DST change announcement */
#define MBG_UTC			0x10	/* special UTC firmware is installed */
#define MBG_LEAP		0x20	/* announcement of a leap second */
#define MBG_IFTM		0x40	/* current time was set from host */
#define MBG_INVALID		0x80	/* time is invalid */
 
/* AMCC S5933 registers */
#define AMCC_OMB1		0x00	/* outgoing mailbox 1 */
#define AMCC_IMB4		0x1c	/* incoming mailbox 4 */
#define AMCC_FIFO		0x20	/* FIFO register */
#define AMCC_INTCSR		0x38	/* interrupt control/status register */
#define AMCC_MCSR		0x3c	/* master control/status register */

/* ASIC registers */
#define ASIC_CFG		0x00
#define ASIC_FEATURES		0x08	/* r/o */
#define ASIC_STATUS		0x10
#define ASIC_CTLSTATUS		0x14
#define ASIC_DATA		0x18
#define ASIC_RES1		0x1c
#define ASIC_ADDON		0x20

/* commands */
#define MBG_GET_TIME		0x00
#define MBG_GET_SYNC_TIME	0x02
#define MBG_GET_HR_TIME		0x03
#define MBG_GET_FW_ID_1		0x40
#define MBG_GET_FW_ID_2		0x41
#define MBG_GET_SERNUM		0x42

/* misc. constants */
#define MBG_FIFO_LEN		16
#define MBG_ID_LEN		(2 * MBG_FIFO_LEN + 1)
#define MBG_BUSY		0x01
#define MBG_SIG_BIAS		55
#define MBG_SIG_MAX		68

int	mbg_probe(struct device *, void *, void *);
void	mbg_attach(struct device *, struct device *, void *);
void	mbg_task(void *);
int	mbg_read_amcc_s5933(struct mbg_softc *, int cmd, char *buf, size_t len,
	    struct timespec *tstamp);
int	mbg_read_asic(struct mbg_softc *, int cmd, char *buf, size_t len,
	    struct timespec *tstamp);

struct cfattach mbg_ca = {
	sizeof(struct mbg_softc), mbg_probe, mbg_attach
};

struct cfdriver mbg_cd = {
	NULL, "mbg", DV_DULL
};

const struct pci_matchid mbg_devices[] = {
	{ PCI_VENDOR_MEINBERG, PCI_PRODUCT_MEINBERG_GPS170 },
	{ PCI_VENDOR_MEINBERG, PCI_PRODUCT_MEINBERG_PCI32 },
	{ PCI_VENDOR_MEINBERG, PCI_PRODUCT_MEINBERG_PCI511 }
};

int
mbg_probe(struct device *parent, void *match, void *aux)
{
	return pci_matchbyid((struct pci_attach_args *)aux, mbg_devices,
	    sizeof(mbg_devices) / sizeof(mbg_devices[0]));
}

void
mbg_attach(struct device *parent, struct device *self, void *aux)
{
	struct mbg_softc *sc = (struct mbg_softc *)self;
	struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
	struct mbg_time tframe;
	pcireg_t memtype;
	bus_size_t iosize;
	char fw_id[MBG_ID_LEN];

	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
	if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &sc->sc_iot,
	    &sc->sc_ioh, NULL, &iosize, 0)) {
		printf(": PCI %s region not found\n",
		    memtype == PCI_MAPREG_TYPE_IO ? "I/O" : "memory");
		return;
	}

	switch (PCI_PRODUCT(pa->pa_id)) {
	case PCI_PRODUCT_MEINBERG_PCI32:
		strlcpy(sc->sc_timedelta.desc, "PCI32",
		    sizeof(sc->sc_timedelta.desc));
		sc->sc_read = mbg_read_amcc_s5933;
		break;
	case PCI_PRODUCT_MEINBERG_PCI511:
		strlcpy(sc->sc_timedelta.desc, "PCI511",
		    sizeof(sc->sc_timedelta.desc));
		sc->sc_read = mbg_read_asic;
		break;
	case PCI_PRODUCT_MEINBERG_GPS170:
		strlcpy(sc->sc_timedelta.desc, "GPS170",
		    sizeof(sc->sc_timedelta.desc));
		sc->sc_read = mbg_read_asic;
		break;
	default:
		/* this can not normally happen, but then there is murphy */
		panic(": unsupported product 0x%04x", PCI_PRODUCT(pa->pa_id));
		break;
	}	

	if (sc->sc_read(sc, MBG_GET_FW_ID_1, fw_id, MBG_FIFO_LEN, NULL) ||
	    sc->sc_read(sc, MBG_GET_FW_ID_2, &fw_id[MBG_FIFO_LEN], MBG_FIFO_LEN,
	    NULL))
		printf(": firmware unknown, ");
	else {
		fw_id[MBG_ID_LEN - 1] = '\0';
		printf(": firmware %s, ", fw_id);
	}

	if (sc->sc_read(sc, MBG_GET_TIME, (char *)&tframe,
	    sizeof(struct mbg_time), NULL)) {
		printf("unknown status\n");
		sc->sc_status = 0;
	} else {
		if (tframe.status & MBG_FREERUN)
			printf("free running on xtal\n");
		else if (tframe.status & MBG_SYNC)
			printf("synchronised\n");
		else if (tframe.status & MBG_INVALID)
			printf("invalid\n");
		sc->sc_status = tframe.status;
	}<commit_msg>Use the value returned by pci_findproduct() as the timedelta sensor description instead of using static strings.<commit_after>/*	$OpenBSD: mbg.c,v 1.11 2007/01/02 19:25:02 mbalmer Exp $ */

/*
 * Copyright (c) 2006 <NAME> <<EMAIL>>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/types.h>
#include <sys/param.h>
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/sensors.h>
#include <sys/syslog.h>
#include <sys/time.h>

#include <machine/bus.h>

#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcidevs.h>

struct mbg_softc {
	struct device		sc_dev;
	bus_space_tag_t		sc_iot;
	bus_space_handle_t	sc_ioh;

	struct sensor		sc_timedelta;
	struct sensor		sc_signal;
	struct sensordev	sc_sensordev;
	u_int8_t		sc_status;

	int			(*sc_read)(struct mbg_softc *, int cmd,
				    char *buf, size_t len,
				    struct timespec *tstamp);
};

struct mbg_time {
	u_int8_t		hundreds;
	u_int8_t		sec;
	u_int8_t		min;
	u_int8_t		hour;
	u_int8_t		mday;
	u_int8_t		wday;
	u_int8_t		mon;
	u_int8_t		year;
	u_int8_t		status;
	u_int8_t		signal;
	int8_t			utc_off;
};

/* mbg_time.status bits */
#define MBG_FREERUN		0x01	/* clock running on xtal */
#define MBG_DST_ENA		0x02	/* DST enabled */
#define MBG_SYNC		0x04	/* clock synced at least once */
#define MBG_DST_CHG		0x08	/* DST change announcement */
#define MBG_UTC			0x10	/* special UTC firmware is installed */
#define MBG_LEAP		0x20	/* announcement of a leap second */
#define MBG_IFTM		0x40	/* current time was set from host */
#define MBG_INVALID		0x80	/* time is invalid */
 
/* AMCC S5933 registers */
#define AMCC_OMB1		0x00	/* outgoing mailbox 1 */
#define AMCC_IMB4		0x1c	/* incoming mailbox 4 */
#define AMCC_FIFO		0x20	/* FIFO register */
#define AMCC_INTCSR		0x38	/* interrupt control/status register */
#define AMCC_MCSR		0x3c	/* master control/status register */

/* ASIC registers */
#define ASIC_CFG		0x00
#define ASIC_FEATURES		0x08	/* r/o */
#define ASIC_STATUS		0x10
#define ASIC_CTLSTATUS		0x14
#define ASIC_DATA		0x18
#define ASIC_RES1		0x1c
#define ASIC_ADDON		0x20

/* commands */
#define MBG_GET_TIME		0x00
#define MBG_GET_SYNC_TIME	0x02
#define MBG_GET_HR_TIME		0x03
#define MBG_GET_FW_ID_1		0x40
#define MBG_GET_FW_ID_2		0x41
#define MBG_GET_SERNUM		0x42

/* misc. constants */
#define MBG_FIFO_LEN		16
#define MBG_ID_LEN		(2 * MBG_FIFO_LEN + 1)
#define MBG_BUSY		0x01
#define MBG_SIG_BIAS		55
#define MBG_SIG_MAX		68

int	mbg_probe(struct device *, void *, void *);
void	mbg_attach(struct device *, struct device *, void *);
void	mbg_task(void *);
int	mbg_read_amcc_s5933(struct mbg_softc *, int cmd, char *buf, size_t len,
	    struct timespec *tstamp);
int	mbg_read_asic(struct mbg_softc *, int cmd, char *buf, size_t len,
	    struct timespec *tstamp);

struct cfattach mbg_ca = {
	sizeof(struct mbg_softc), mbg_probe, mbg_attach
};

struct cfdriver mbg_cd = {
	NULL, "mbg", DV_DULL
};

const struct pci_matchid mbg_devices[] = {
	{ PCI_VENDOR_MEINBERG, PCI_PRODUCT_MEINBERG_GPS170 },
	{ PCI_VENDOR_MEINBERG, PCI_PRODUCT_MEINBERG_PCI32 },
	{ PCI_VENDOR_MEINBERG, PCI_PRODUCT_MEINBERG_PCI511 }
};

int
mbg_probe(struct device *parent, void *match, void *aux)
{
	return pci_matchbyid((struct pci_attach_args *)aux, mbg_devices,
	    sizeof(mbg_devices) / sizeof(mbg_devices[0]));
}

void
mbg_attach(struct device *parent, struct device *self, void *aux)
{
	struct mbg_softc *sc = (struct mbg_softc *)self;
	struct pci_attach_args *const pa = (struct pci_attach_args *)aux;
	struct mbg_time tframe;
	pcireg_t memtype;
	bus_size_t iosize;
	char fw_id[MBG_ID_LEN];
	const char *desc;

	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
	if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &sc->sc_iot,
	    &sc->sc_ioh, NULL, &iosize, 0)) {
		printf(": PCI %s region not found\n",
		    memtype == PCI_MAPREG_TYPE_IO ? "I/O" : "memory");
		return;
	}

	if ((desc = pci_findproduct(pa->pa_id)) == NULL)
		desc = "Radio clock";
	strlcpy(sc->sc_timedelta.desc, desc, sizeof(sc->sc_timedelta.desc));

	switch (PCI_PRODUCT(pa->pa_id)) {
	case PCI_PRODUCT_MEINBERG_PCI32:
		sc->sc_read = mbg_read_amcc_s5933;
		break;
	case PCI_PRODUCT_MEINBERG_PCI511:
		/* FALLTHROUGH */
	case PCI_PRODUCT_MEINBERG_GPS170:
		sc->sc_read = mbg_read_asic;
		break;
	default:
		/* this can not normally happen, but then there is murphy */
		panic(": unsupported product 0x%04x", PCI_PRODUCT(pa->pa_id));
		break;
	}	
	if (sc->sc_read(sc, MBG_GET_FW_ID_1, fw_id, MBG_FIFO_LEN, NULL) ||
	    sc->sc_read(sc, MBG_GET_FW_ID_2, &fw_id[MBG_FIFO_LEN], MBG_FIFO_LEN,
	    NULL))
		printf(": firmware unknown, ");
	else {
		fw_id[MBG_ID_LEN - 1] = '\0';
		printf(": firmware %s, ", fw_id);
	}

	if (sc->sc_read(sc, MBG_GET_TIME, (char *)&tframe,
	    sizeof(struct mbg_time), NULL)) {
		printf("unknown status\n");
		sc->sc_status = 0;
	} else {
		if (tframe.status & MBG_FREERUN)
			printf("free running on xtal\n");
		else if (tframe.status & MBG_SYNC)
			printf("synchronised\n");
		else if (tframe.status & MBG_INVALID)
			printf("invalid\n");
		sc->sc_status = tframe.status;
	}
{'fraction_non_alphanumeric': 0.1117323241011526, 'fraction_numerical': 0.029072767933941167, 'mean_word_length': 4.313985374771481, 'pattern_counts': {'":': 8, '<': 35, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '860106', 'n_tokens_mistral': 5100, 'n_tokens_neox': 4799, 'n_words': 1191}