config root man

Current Path : /usr/src/sys/boot/i386/libfirewire/

FreeBSD hs32.drive.ne.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #1: Wed Jan 14 12:18:08 JST 2015 root@hs32.drive.ne.jp:/sys/amd64/compile/hs32 amd64
Upload File :
Current File : //usr/src/sys/boot/i386/libfirewire/firewire.c

/*-
 * Copyright (c) 2004 Hidetoshi Shimokawa <simokawa@FreeBSD.ORG>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: release/9.1.0/sys/boot/i386/libfirewire/firewire.c 170101 2007-05-29 14:35:57Z simokawa $");

/*
 * FireWire disk device handling.
 * 
 */

#include <stand.h>

#include <machine/bootinfo.h>

#include <stdarg.h>

#include <bootstrap.h>
#include <btxv86.h>
#include <libi386.h>
#include "fwohci.h"
#include <dev/dcons/dcons.h>

/* XXX */
#define BIT4x2(x,y)      uint8_t  y:4, x:4
#define BIT16x2(x,y)    uint32_t y:16, x:16
#define _KERNEL
#include <dev/firewire/iec13213.h>

extern uint32_t dcons_paddr;
extern struct console dconsole;

struct crom_src_buf {
	struct crom_src src;
	struct crom_chunk root;
	struct crom_chunk vendor;
	struct crom_chunk hw;
	/* for dcons */
	struct crom_chunk unit;
	struct crom_chunk spec;
	struct crom_chunk ver;
};

static int	fw_init(void);
static int	fw_strategy(void *devdata, int flag, daddr_t dblk,
		    size_t size, char *buf, size_t *rsize);
static int	fw_open(struct open_file *f, ...);
static int	fw_close(struct open_file *f);
static void	fw_print(int verbose);
static void	fw_cleanup(void);

void		fw_enable(void);

struct devsw fwohci = {
    "FW1394", 	/* 7 chars at most */
    DEVT_NET, 
    fw_init,
    fw_strategy, 
    fw_open, 
    fw_close, 
    noioctl,
    fw_print,
    fw_cleanup
};

static struct fwohci_softc fwinfo[MAX_OHCI];
static int fw_initialized = 0;

static void
fw_probe(int index, struct fwohci_softc *sc)
{
	int err;

	sc->state = FWOHCI_STATE_INIT;
	err = biospci_find_devclass(
		0x0c0010	/* Serial:FireWire:OHCI */,
		index		/* index */,
		&sc->locator);

	if (err != 0) {
		sc->state = FWOHCI_STATE_DEAD;
		return;
	}

	biospci_write_config(sc->locator,
		0x4	/* command */,
		0x6	/* enable bus master and memory mapped I/O */,
		1	/* word */);

	biospci_read_config(sc->locator, 0x00 /*devid*/, 2 /*dword*/,
		&sc->devid);
	biospci_read_config(sc->locator, 0x10 /*base_addr*/, 2 /*dword*/,
		&sc->base_addr);

        sc->handle = (uint32_t)PTOV(sc->base_addr);
	sc->bus_id = OREAD(sc, OHCI_BUS_ID);

	return;
}

static int
fw_init(void) 
{
	int i, avail;
	struct fwohci_softc *sc;

	if (fw_initialized)
		return (0);

	avail = 0;
	for (i = 0; i < MAX_OHCI; i ++) {
		sc = &fwinfo[i];
		fw_probe(i, sc);
		if (sc->state == FWOHCI_STATE_DEAD)
			break;
		avail ++;
			break;
	}
	fw_initialized = 1;

	return (0);
}


/*
 * Print information about OHCI chips
 */
static void
fw_print(int verbose)
{
	int i;
	struct fwohci_softc *sc;

	for (i = 0; i < MAX_OHCI; i ++) {
		sc = &fwinfo[i];
		if (sc->state == FWOHCI_STATE_DEAD)
			break;
		printf("%d: locator=0x%04x devid=0x%08x"
			" base_addr=0x%08x handle=0x%08x bus_id=0x%08x\n",
			i, sc->locator, sc->devid,
			sc->base_addr, sc->handle, sc->bus_id);
	}
}

static int 
fw_open(struct open_file *f, ...)
{
#if 0
    va_list			ap;
    struct i386_devdesc		*dev;
    struct open_disk		*od;
    int				error;

    va_start(ap, f);
    dev = va_arg(ap, struct i386_devdesc *);
    va_end(ap);
#endif

    return (ENXIO);
}

static int
fw_close(struct open_file *f)
{
    return (0);
}

static void 
fw_cleanup()
{
    struct dcons_buf *db;

    /* invalidate dcons buffer */
    if (dcons_paddr) {
	db = (struct dcons_buf *)PTOV(dcons_paddr);
	db->magic = 0;
    }
}

static int 
fw_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize)
{
	return (EIO);
}

static void
fw_init_crom(struct fwohci_softc *sc)
{
	struct crom_src *src;

	printf("fw_init_crom\n");
	sc->crom_src_buf = (struct crom_src_buf *)
		malloc(sizeof(struct crom_src_buf));
	if (sc->crom_src_buf == NULL)
		return;

	src = &sc->crom_src_buf->src;
	bzero(src, sizeof(struct crom_src));

	/* BUS info sample */
	src->hdr.info_len = 4;

	src->businfo.bus_name = CSR_BUS_NAME_IEEE1394;

	src->businfo.irmc = 1;
	src->businfo.cmc = 1;
	src->businfo.isc = 1;
	src->businfo.bmc = 1;
	src->businfo.pmc = 0;
	src->businfo.cyc_clk_acc = 100;
	src->businfo.max_rec = sc->maxrec;
	src->businfo.max_rom = MAXROM_4;
	src->businfo.generation = 1;
	src->businfo.link_spd = sc->speed;

	src->businfo.eui64.hi = sc->eui.hi;
	src->businfo.eui64.lo = sc->eui.lo;

	STAILQ_INIT(&src->chunk_list);

	sc->crom_src = src;
	sc->crom_root = &sc->crom_src_buf->root;
}

static void
fw_reset_crom(struct fwohci_softc *sc)
{
	struct crom_src_buf *buf;
	struct crom_src *src;
	struct crom_chunk *root;

	printf("fw_reset\n");
	if (sc->crom_src_buf == NULL)
		fw_init_crom(sc);

	buf = sc->crom_src_buf;
	src = sc->crom_src;
	root = sc->crom_root;

	STAILQ_INIT(&src->chunk_list);

	bzero(root, sizeof(struct crom_chunk));
	crom_add_chunk(src, NULL, root, 0);
	crom_add_entry(root, CSRKEY_NCAP, 0x0083c0); /* XXX */
	/* private company_id */
	crom_add_entry(root, CSRKEY_VENDOR, CSRVAL_VENDOR_PRIVATE);
#ifdef __DragonFly__
	crom_add_simple_text(src, root, &buf->vendor, "DragonFly Project");
#else
	crom_add_simple_text(src, root, &buf->vendor, "FreeBSD Project");
#endif
}


#define ADDR_HI(x)	(((x) >> 24) & 0xffffff)
#define ADDR_LO(x)	((x) & 0xffffff)

static void
dcons_crom(struct fwohci_softc *sc)
{
	struct crom_src_buf *buf;
	struct crom_src *src;
	struct crom_chunk *root;

	buf = sc->crom_src_buf;
	src = sc->crom_src;
	root = sc->crom_root;

	bzero(&buf->unit, sizeof(struct crom_chunk));

	crom_add_chunk(src, root, &buf->unit, CROM_UDIR);
	crom_add_entry(&buf->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE);
	crom_add_simple_text(src, &buf->unit, &buf->spec, "FreeBSD");
	crom_add_entry(&buf->unit, CSRKEY_VER, DCONS_CSR_VAL_VER);
	crom_add_simple_text(src, &buf->unit, &buf->ver, "dcons");
	crom_add_entry(&buf->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr));
	crom_add_entry(&buf->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr));
}

void
fw_crom(struct fwohci_softc *sc)
{
	struct crom_src *src;
	void *newrom;

	fw_reset_crom(sc);
	dcons_crom(sc);

	newrom = malloc(CROMSIZE);
	src = &sc->crom_src_buf->src;
	crom_load(src, (uint32_t *)newrom, CROMSIZE);
	if (bcmp(newrom, sc->config_rom, CROMSIZE) != 0) {
		/* bump generation and reload */
		src->businfo.generation ++;
		/* generation must be between 0x2 and 0xF */
		if (src->businfo.generation < 2)
			src->businfo.generation ++;
		crom_load(src, (uint32_t *)newrom, CROMSIZE);
		bcopy(newrom, (void *)sc->config_rom, CROMSIZE);
	}
	free(newrom);
}

static int
fw_busreset(struct fwohci_softc *sc)
{
	int count;

	if (sc->state < FWOHCI_STATE_ENABLED) {
		printf("fwohci not enabled\n");
		return(CMD_OK);
	}
	fw_crom(sc);
	fwohci_ibr(sc);
	count = 0;
	while (sc->state< FWOHCI_STATE_NORMAL) {
		fwohci_poll(sc);
		count ++;
		if (count > 1000) {
			printf("give up to wait bus initialize\n");
			return (-1);
		}
	}
	printf("poll count = %d\n", count);
	return (0);
}

void
fw_enable(void)
{
	struct fwohci_softc *sc;
	int i;

	if (fw_initialized == 0)
		fw_init();

	for (i = 0; i < MAX_OHCI; i ++) {
		sc = &fwinfo[i];
		if (sc->state != FWOHCI_STATE_INIT)
			break;

		sc->config_rom = (uint32_t *)
			(((uint32_t)sc->config_rom_buf
				+ (CROMSIZE - 1)) & ~(CROMSIZE - 1));
#if 0
		printf("configrom: %08p %08p\n",
			sc->config_rom_buf, sc->config_rom);
#endif
		if (fwohci_init(sc, 0) == 0) {
			sc->state = FWOHCI_STATE_ENABLED;
			fw_busreset(sc);
		} else
			sc->state = FWOHCI_STATE_DEAD;
	}
}

void
fw_poll(void)
{
	struct fwohci_softc *sc;
	int i;

	if (fw_initialized == 0)
		return;

	for (i = 0; i < MAX_OHCI; i ++) {
		sc = &fwinfo[i];
		if (sc->state < FWOHCI_STATE_ENABLED)
			break;
		fwohci_poll(sc);
	}
}

#if 0 /* for debug */
static int
fw_busreset_cmd(int argc, char *argv[])
{
	struct fwohci_softc *sc;
	int i;

	for (i = 0; i < MAX_OHCI; i ++) {
		sc = &fwinfo[i];
		if (sc->state < FWOHCI_STATE_INIT)
			break;
		fw_busreset(sc);
	}
	return(CMD_OK);
}

static int
fw_poll_cmd(int argc, char *argv[])
{
	fw_poll();
	return(CMD_OK);
}

static int
fw_enable_cmd(int argc, char *argv[])
{
	fw_print(0);
	fw_enable();
	return(CMD_OK);
}


static int
dcons_enable(int argc, char *argv[])
{
	dconsole.c_init(0);
	fw_enable();
	dconsole.c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
	return(CMD_OK);
}

static int
dcons_read(int argc, char *argv[])
{
	char c;
	while (dconsole.c_ready()) {
		c = dconsole.c_in();
		printf("%c", c);
	}
	printf("\r\n");
	return(CMD_OK);
}

static int
dcons_write(int argc, char *argv[])
{
	int len, i;
	if (argc < 2)
		return(CMD_OK);

	len = strlen(argv[1]);
	for (i = 0; i < len; i ++)
		dconsole.c_out(argv[1][i]);
	dconsole.c_out('\r');
	dconsole.c_out('\n');
	return(CMD_OK);
}
COMMAND_SET(firewire, "firewire", "enable firewire", fw_enable_cmd);
COMMAND_SET(fwbusreset, "fwbusreset", "firewire busreset", fw_busreset_cmd);
COMMAND_SET(fwpoll, "fwpoll", "firewire poll", fw_poll_cmd);
COMMAND_SET(dcons, "dcons", "enable dcons", dcons_enable);
COMMAND_SET(dread, "dread", "read from dcons", dcons_read);
COMMAND_SET(dwrite, "dwrite", "write to dcons", dcons_write);
#endif

Man Man