NetBSD-5.0.2/sys/arch/sandpoint/stand/netboot/pciide.c

Compare this file to the similar file:
Show the results in this format:

/* $NetBSD: pciide.c,v 1.7 2008/05/14 23:14:11 nisimura Exp $ */

/*-
 * Copyright (c) 2008 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Tohru Nishimura.
 *
 * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/param.h>
#include <sys/disklabel.h>

#include <dev/ic/wdcreg.h>
#include <dev/ata/atareg.h>

#include <lib/libsa/stand.h>
#include "globals.h"

/*
 * - no vtophys() translation, vaddr_t == paddr_t. 
 */
#define DEVTOV(pa) 		(uint32_t)(pa)

/*
 * cmdide
 * iteide
 * viaide
 * slide
 */

int pciide_match(unsigned, void *);
void *pciide_init(unsigned, void *);

#define PCIIDE_INTERFACE_PCI(chan)	(0x01 << (2 * (chan)))

/* native: PCI BAR0-3 */
static const struct {
	int cmd, ctl;
} pcibar[2] = {
	{ 0x10, 0x14 },
	{ 0x18, 0x1c },
};
/* legacy: ISA/PCI IO space */
static const struct {
	int cmd, ctl;
} compat[2] = {
	{ 0x1f0, 0x3f6 },
	{ 0x170, 0x376 },
};

int
pciide_match(unsigned tag, void *data)
{
	unsigned v;

	v = pcicfgread(tag, PCI_ID_REG);
	switch (v) {
	case PCI_DEVICE(0x1095, 0x0680): /* SiI 0680 IDE */
	case PCI_DEVICE(0x1283, 0x8211): /* ITE 8211 IDE */
	case PCI_DEVICE(0x1106, 0x1571): /* VIA 82C586 IDE */
	case PCI_DEVICE(0x10ad, 0x0105): /* Symphony Labs 82C105 IDE */
		return 1;
	}
	return 0;
}

void *
pciide_init(unsigned tag, void *data)
{
	int ch, i;
	unsigned val;
	struct atac_softc *l;
	struct atac_channel *cp;

	l = alloc(sizeof(struct atac_softc));
	memset(l, 0, sizeof(struct atac_softc));
	val = pcicfgread(tag, PCI_CLASS_REG);
	for (ch = 0; ch < 2; ch += 1) {
		cp = &l->channel[ch];
		if (PCIIDE_INTERFACE_PCI(ch) & val) {
			cp->c_cmdbase =
			  (void *)DEVTOV(~03 & pcicfgread(tag, pcibar[ch].cmd));
			cp->c_ctlbase =
			  (void *)DEVTOV(~03 & pcicfgread(tag, pcibar[ch].ctl));
			cp->c_data = (u_int16_t *)(cp->c_cmdbase + wd_data);
			for (i = 0; i < 8; i++)
				cp->c_cmdreg[i] = cp->c_cmdbase + i;
			cp->c_cmdreg[wd_status] = cp->c_cmdreg[wd_command];
			cp->c_cmdreg[wd_features] = cp->c_cmdreg[wd_precomp];
		}
		else {
			uint32_t pciiobase = 0xfe000000; /* !!! */
			cp->c_cmdbase =
			    (void *)DEVTOV(pciiobase + compat[ch].cmd);
			cp->c_ctlbase =
			    (void *)DEVTOV(pciiobase + compat[ch].ctl);
			cp->c_data = (u_int16_t *)(cp->c_cmdbase + wd_data);
			for (i = 0; i < 8; i++)
				cp->c_cmdreg[i] = cp->c_cmdbase + i;
			cp->c_cmdreg[wd_status] = cp->c_cmdreg[wd_command];
			cp->c_cmdreg[wd_features] = cp->c_cmdreg[wd_precomp];
		}
		cp->compatchan = ch;
	}
	l->chvalid = 03 & (unsigned)data;
	l->tag = tag;
	return l;
}