Example #1
0
vt_efb_initialize(struct fb_info *info)
#endif
{
#ifdef	FDT
	char name[64];
	cell_t retval;
	ihandle_t ih;
	int i;

	/* Open display device, thereby initializing it */
	memset(name, 0, sizeof(name));
	OF_package_to_path(node, name, sizeof(name));
	ih = OF_open(name);
#endif

	/*
	 * Set up the color map
	 */
	switch (info->fb_depth) {
	case 8:
		vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
		    0x7, 5, 0x7, 2, 0x3, 0);
		break;
	case 15:
		vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
		    0x1f, 10, 0x1f, 5, 0x1f, 0);
		break;
	case 16:
		vt_generate_cons_palette(info->fb_cmap, COLOR_FORMAT_RGB,
		    0x1f, 11, 0x3f, 5, 0x1f, 0);
		break;
	case 24:
	case 32:
#if BYTE_ORDER == BIG_ENDIAN
		vt_generate_cons_palette(info->fb_cmap,
		    COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
#else
		vt_generate_cons_palette(info->fb_cmap,
		    COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
#endif
#ifdef	FDT
		for (i = 0; i < 16; i++) {
			OF_call_method("color!", ih, 4, 1,
			    (cell_t)((info->fb_cmap[i] >> 16) & 0xff),
			    (cell_t)((info->fb_cmap[i] >> 8) & 0xff),
			    (cell_t)((info->fb_cmap[i] >> 0) & 0xff),
			    (cell_t)i, &retval);
		}
#endif
		break;

	default:
		panic("Unknown color space fb_depth %d", info->fb_depth);
		break;
	}
}
Example #2
0
/* Return the fully qualified pathname corresponding to an instance. */
static ssize_t
ofw_fdt_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
{
	phandle_t phandle;

	phandle = OF_instance_to_package(instance);
	if (phandle == -1)
		return (-1);

	return (OF_package_to_path(phandle, buf, len));
}
Example #3
0
static void
ofnet_attach(struct device *parent, struct device *self, void *aux)
{
	struct ofnet_softc *of = device_private(self);
	struct ifnet *ifp = &of->sc_ethercom.ec_if;
	struct ofbus_attach_args *oba = aux;
	char path[256];
	int l;
	u_int8_t myaddr[ETHER_ADDR_LEN];

	of->sc_phandle = oba->oba_phandle;
#if NIPKDB_OFN > 0
	if (kifp &&
	    kifp->unit - 1 == device_unit(&of->sc_dev) &&
	    OF_instance_to_package(kifp->port) == oba->oba_phandle)  {
		ipkdb_of = of;
		of->sc_ihandle = kifp->port;
	} else
#endif
	if ((l = OF_package_to_path(oba->oba_phandle, path,
	    sizeof path - 1)) < 0 ||
	    l >= sizeof path ||
	    (path[l] = 0, !(of->sc_ihandle = OF_open(path))))
		panic("ofnet_attach: unable to open");
	if (OF_getprop(oba->oba_phandle, "mac-address", myaddr,
	    sizeof myaddr) < 0)
		panic("ofnet_attach: no mac-address");
	printf(": address %s\n", ether_sprintf(myaddr));

	callout_init(&of->sc_callout, 0);

	strlcpy(ifp->if_xname, device_xname(&of->sc_dev), IFNAMSIZ);
	ifp->if_softc = of;
	ifp->if_start = ofnet_start;
	ifp->if_ioctl = ofnet_ioctl;
	ifp->if_watchdog = ofnet_watchdog;
	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
	IFQ_SET_READY(&ifp->if_snd);

	if_attach(ifp);
	ether_ifattach(ifp, myaddr);
}
Example #4
0
static void
fix_cardbus_bridge(int node, pci_chipset_tag_t pc, pcitag_t tag)
{
	uint32_t bus_number = 0xffffffff;
	pcireg_t bi;
	int bus, dev, fn, ih, len;
	char path[256];

#if PB3400_CARDBUS_HACK
	int root_node;

	root_node = OF_finddevice("/");
	if (of_compatible(root_node, pb3400_compat) != -1) {

		bus_number = cardbus_number;
		cardbus_number++;
	} else {
#endif		
		ih = OF_open(path);
		OF_call_method("load-ata", ih, 0, 0);
		OF_close(ih);

		OF_getprop(node, "AAPL,bus-id", &bus_number,
		    sizeof(bus_number));
#if PB3400_CARDBUS_HACK
	}
#endif
	if (bus_number != 0xffffffff) {

		len = OF_package_to_path(node, path, sizeof(path));
		path[len] = 0;
		aprint_verbose("\n%s: fixing bus number to %d", path, bus_number);
		pci_decompose_tag(pc, tag, &bus, &dev, &fn);
		bi = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
		bi &= 0xff000000;
		/* XXX subordinate is always 32 here */
		bi |= (bus & 0xff) | (bus_number << 8) | 0x200000;
		pci_conf_write(pc, tag, PPB_REG_BUSINFO, bi);
	}
}
Example #5
0
static int
ofwfb_set_mode(video_adapter_t *adp, int mode)
{
	struct ofwfb_softc *sc;
	char name[64];
	ihandle_t ih;
	int i, retval;

	sc = (struct ofwfb_softc *)adp;

	if (ofwfb_reset_on_switch) {
		/*
		 * Open the display device, which will initialize it.
		 */

		memset(name, 0, sizeof(name));
		OF_package_to_path(sc->sc_node, name, sizeof(name));
		ih = OF_open(name);

		if (sc->sc_depth == 8) {
			/*
			 * Install the ISO6429 colormap - older OFW systems
			 * don't do this by default
			 */
			for (i = 0; i < 16; i++) {
				OF_call_method("color!", ih, 4, 1,
						   ofwfb_cmap[i].red,
						   ofwfb_cmap[i].green,
						   ofwfb_cmap[i].blue,
						   i,
						   &retval);
			}
		}
	}

	ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);

	return (0);
}
Example #6
0
static void
rtas_setup(void *junk)
{
	ihandle_t rtasi;
	cell_t rtas_size = 0, rtas_ptr;
	char path[31];
	int result;

	rtas = OF_finddevice("/rtas");
	if (rtas == -1) {
		rtas = 0;
		return;
	}
	OF_package_to_path(rtas, path, sizeof(path));
	rtasi = OF_open(path);
	if (rtasi == 0) {
		rtas = 0;
		printf("Error initializing RTAS: could not open node\n");
		return;
	}

	mtx_init(&rtas_mtx, "RTAS", MTX_DEF, 0);

	/* RTAS must be called with everything turned off in MSR */
	rtasmsr = mfmsr();
	rtasmsr &= ~(PSL_IR | PSL_DR | PSL_EE | PSL_SE);
	#ifdef __powerpc64__
	rtasmsr &= ~PSL_SF;
	#endif

	/*
	 * Allocate rtas_size + one page of contiguous, wired physical memory
	 * that can fit into a 32-bit address space and accessed from real mode.
	 * This is used both to bounce arguments and for RTAS private data.
	 *
	 * It must be 4KB-aligned and not cross a 256 MB boundary.
	 */

	OF_getprop(rtas, "rtas-size", &rtas_size, sizeof(rtas_size));
	rtas_size = round_page(rtas_size);
	rtas_bounce_virt = contigmalloc(rtas_size + PAGE_SIZE, M_RTAS, 0, 0,
	    ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT),
	    4096, 256*1024*1024);

	rtas_private_data = vtophys(rtas_bounce_virt);
	rtas_bounce_virt += rtas_size;	/* Actual bounce area */
	rtas_bounce_phys = vtophys(rtas_bounce_virt);
	rtas_bounce_size = PAGE_SIZE;

	/*
	 * Instantiate RTAS. We always use the 32-bit version.
	 */

	result = OF_call_method("instantiate-rtas", rtasi, 1, 1,
	    (cell_t)rtas_private_data, &rtas_ptr);
	OF_close(rtasi);

	if (result != 0) {
		rtas = 0;
		rtas_ptr = 0;
		printf("Error initializing RTAS (%d)\n", result);
		return;
	}

	rtas_entry = (uintptr_t)(rtas_ptr);
}
Example #7
0
static void
ofwpci_attach(device_t parent, device_t self, void *aux)
{
	struct ofwpci_softc *sc = device_private(self);
	pci_chipset_tag_t pc = &sc->sc_pc;
	struct confargs *ca = aux;
	struct pcibus_attach_args pba;
	struct genppc_pci_chipset_businfo *pbi;
	int node = ca->ca_node;
	int i, isprim = 0;
	uint32_t busrange[2];
	char buf[64];
#ifdef PCI_NETBSD_CONFIGURE
	struct extent *ioext, *memext;
#endif

	aprint_normal("\n");

	sc->sc_dev = self;

	/* PCI bus number */
	if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
		return;

	/* bus space map the io ranges */
	sc->sc_iot.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE;
	sc->sc_iot.pbs_base = 0x00000000;
	if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_IO, node, &sc->sc_iot,
	    "ofwpci io-space") != 0)
		panic("Can't init ofwpci io tag");

	sc->sc_memt.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE;
	sc->sc_memt.pbs_base = 0x00000000;
	if (ofwoea_map_space(RANGE_TYPE_PCI, RANGE_MEM, node, &sc->sc_memt,
	    "ofwpci mem-space") != 0)
		panic("Can't init ofwpci mem tag");

	aprint_debug("io base=0x%"PRIxPTR" offset=0x%"PRIxPTR" limit=0x%"PRIxPTR"\n",
	    sc->sc_iot.pbs_base, sc->sc_iot.pbs_offset, sc->sc_iot.pbs_limit);
	
	aprint_debug("mem base=0x%"PRIxPTR" offset=0x%"PRIxPTR" limit=0x%"PRIxPTR"\n",
	    sc->sc_memt.pbs_base, sc->sc_memt.pbs_offset,
	    sc->sc_memt.pbs_limit);
	
	/* are we the primary pci bus? */
	if (of_find_firstchild_byname(OF_finddevice("/"), "pci") == node) {
		int isa_node;

		isprim++;
		/* yes we are, now do we have an ISA child? */
		isa_node = of_find_firstchild_byname(node, "isa");
		if (isa_node != -1) {
			/* isa == pci */
			genppc_isa_io_space_tag = sc->sc_iot;
			genppc_isa_mem_space_tag = sc->sc_memt;
			map_isa_ioregs();
			init_ofppc_interrupt();
			ofppc_init_comcons(isa_node);
		}
	}

	ofwpci_get_chipset_tag(pc);

	pc->pc_node = node;
	i = OF_package_to_path(node, buf, sizeof(buf)-5);
	if (i <= 0)
		panic("Can't determine path for pci node %d", node);
	buf[i] = '\0';
	pc->pc_ihandle = OF_open(buf);
	if (pc->pc_ihandle < 0)
		panic("Can't open device %s", buf);
	pc->pc_bus = busrange[0];
	pc->pc_iot = &sc->sc_iot;
	pc->pc_memt = &sc->sc_memt;

	pbi = malloc(sizeof(struct genppc_pci_chipset_businfo),
	    M_DEVBUF, M_NOWAIT);
	KASSERT(pbi != NULL);
	pbi->pbi_properties = prop_dictionary_create();
	KASSERT(pbi->pbi_properties != NULL);
	SIMPLEQ_INIT(&pc->pc_pbi);
	SIMPLEQ_INSERT_TAIL(&pc->pc_pbi, pbi, next);

	genofw_setup_pciintr_map((void *)pc, pbi, pc->pc_node);
#ifdef PCI_NETBSD_CONFIGURE
	ioext  = extent_create("pciio",
	    modeldata.pciiodata[device_unit(self)].start,
	    modeldata.pciiodata[device_unit(self)].limit,
	    NULL, 0, EX_NOWAIT);
	memext = extent_create("pcimem", sc->sc_memt.pbs_base,
	    sc->sc_memt.pbs_limit-1, NULL, 0, EX_NOWAIT);

	if (pci_configure_bus(pc, ioext, memext, NULL, 0, CACHELINESIZE))
		aprint_error("pci_configure_bus() failed\n");

	extent_destroy(ioext);
	extent_destroy(memext);
#endif /* PCI_NETBSD_CONFIGURE */
	memset(&pba, 0, sizeof(pba));
	pba.pba_memt = pc->pc_memt;
	pba.pba_iot = pc->pc_iot;
	pba.pba_dmat = &pci_bus_dma_tag;
	pba.pba_dmat64 = NULL;
	pba.pba_bus = pc->pc_bus;
	pba.pba_bridgetag = NULL;
	pba.pba_pc = pc;
	pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
	config_found_ia(self, "pcibus", &pba, pcibusprint);
}
Example #8
0
int
ofdisk_open(dev_t dev, int flags, int fmt, struct lwp *lwp)
{
	struct ofdisk_softc *of;
	char path[256];
	int error, l, part;

	of = device_lookup_private(&ofdisk_cd, DISKUNIT(dev));
	if (of == NULL)
		return ENXIO;

	part = DISKPART(dev);

	mutex_enter(&of->sc_dk.dk_openlock);

	/*
	 * If there are wedges, and this is not RAW_PART, then we
	 * need to fail.
	 */
	if (of->sc_dk.dk_nwedges != 0 && part != RAW_PART) {
		error = EBUSY;
		goto bad1;
	}

	if (!of->sc_ihandle) {
		if ((l = OF_package_to_path(of->sc_phandle, path,
		    sizeof path - 3)) < 0 ||
		    l >= sizeof path - 3) {
			error = ENXIO;
			goto bad1;
		}
		path[l] = 0;

		/*
		 * XXX This is for the benefit of SCSI/IDE disks that don't
		 * XXX have all their childs in the device tree.
		 * XXX YES, I DO THINK THIS IS A BUG IN OPENFIRMWARE!!!
		 * XXX And yes, this is a very gross hack!
		 * XXX See also ofscsi.c
		 */
		if (!strcmp(path + l - 4, "disk")) {
			path[l++] = '@';
			path[l++] = '0' + of->sc_unit;
			path[l] = 0;
		}

		strlcat(path, ":0", sizeof(path));

		if ((of->sc_ihandle = OF_open(path)) == -1) {
			error = ENXIO;
			goto bad1;
		}

		/*
		 * Try to get characteristics of the disk.
		 */
		of->max_transfer = OF_call_method_1("max-transfer",
		    of->sc_ihandle, 0);
		if (of->max_transfer > MAXPHYS)
			of->max_transfer = MAXPHYS;

		ofdisk_getdisklabel(dev);
	}

	switch (fmt) {
	case S_IFCHR:
		of->sc_dk.dk_copenmask |= 1 << part;
		break;
	case S_IFBLK:
		of->sc_dk.dk_bopenmask |= 1 << part;
		break;
	}
	of->sc_dk.dk_openmask =
	    of->sc_dk.dk_copenmask | of->sc_dk.dk_bopenmask;


	error = 0;
 bad1:
	mutex_exit(&of->sc_dk.dk_openlock);
	return (error);
}
Example #9
0
void
bmac_attach(struct device *parent, struct device *self, void *aux)
{
	struct confargs *ca = aux;
	struct bmac_softc *sc = (void *)self;
	struct ifnet *ifp = &sc->sc_if;
	struct mii_data *mii = &sc->sc_mii;
	u_char laddr[6];

	callout_init(&sc->sc_tick_ch, 0);

	sc->sc_flags =0;
	if (strcmp(ca->ca_name, "ethernet") == 0) {
		char name[64];

		memset(name, 0, 64);
		OF_package_to_path(ca->ca_node, name, sizeof(name));
		OF_open(name);
		sc->sc_flags |= BMAC_BMACPLUS;
	}

	ca->ca_reg[0] += ca->ca_baseaddr;
	ca->ca_reg[2] += ca->ca_baseaddr;
	ca->ca_reg[4] += ca->ca_baseaddr;

	sc->sc_iot = ca->ca_tag;
	if (bus_space_map(sc->sc_iot, ca->ca_reg[0], ca->ca_reg[1], 0,
	    &sc->sc_ioh) != 0) {
		aprint_error(": couldn't map %#x", ca->ca_reg[0]);
		return;
	}

	bmac_write_reg(sc, INTDISABLE, NoEventsMask);

	if (OF_getprop(ca->ca_node, "local-mac-address", laddr, 6) == -1 &&
	    OF_getprop(ca->ca_node, "mac-address", laddr, 6) == -1) {
		printf(": cannot get mac-address\n");
		return;
	}
	memcpy(sc->sc_enaddr, laddr, 6);

	sc->sc_txdma = mapiodev(ca->ca_reg[2], PAGE_SIZE);
	sc->sc_rxdma = mapiodev(ca->ca_reg[4], PAGE_SIZE);
	sc->sc_txcmd = dbdma_alloc(BMAC_TXBUFS * sizeof(dbdma_command_t));
	sc->sc_rxcmd = dbdma_alloc((BMAC_RXBUFS + 1) * sizeof(dbdma_command_t));
	sc->sc_txbuf = malloc(BMAC_BUFLEN * BMAC_TXBUFS, M_DEVBUF, M_NOWAIT);
	sc->sc_rxbuf = malloc(BMAC_BUFLEN * BMAC_RXBUFS, M_DEVBUF, M_NOWAIT);
	if (sc->sc_txbuf == NULL || sc->sc_rxbuf == NULL ||
	    sc->sc_txcmd == NULL || sc->sc_rxcmd == NULL) {
		printf("cannot allocate memory\n");
		return;
	}

	printf(" irq %d,%d: address %s\n", ca->ca_intr[0], ca->ca_intr[2],
		ether_sprintf(laddr));

	intr_establish(ca->ca_intr[0], IST_EDGE, IPL_NET, bmac_intr, sc);
	intr_establish(ca->ca_intr[2], IST_EDGE, IPL_NET, bmac_rint, sc);

	memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
	ifp->if_softc = sc;
	ifp->if_ioctl = bmac_ioctl;
	ifp->if_start = bmac_start;
	ifp->if_flags =
		IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
	ifp->if_watchdog = bmac_watchdog;
	IFQ_SET_READY(&ifp->if_snd);

	mii->mii_ifp = ifp;
	mii->mii_readreg = bmac_mii_readreg;
	mii->mii_writereg = bmac_mii_writereg;
	mii->mii_statchg = bmac_mii_statchg;

	sc->sc_ethercom.ec_mii = mii;
	ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
	mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY,
		      MII_OFFSET_ANY, 0);

	/* Choose a default media. */
	if (LIST_FIRST(&mii->mii_phys) == NULL) {
		ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_10_T, 0, NULL);
		ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_10_T);
	} else
		ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);

	bmac_reset_chip(sc);

	if_attach(ifp);
	ether_ifattach(ifp, sc->sc_enaddr);
}
void
wdc_obio_attach(device_t parent, device_t self, void *aux)
{
	struct wdc_obio_softc *sc = device_private(self);
	struct wdc_regs *wdr;
	struct confargs *ca = aux;
	struct ata_channel *chp = &sc->sc_channel;
	int intr, i, type = IST_EDGE;
	int use_dma = 0;
	char path[80];

	sc->sc_wdcdev.sc_atac.atac_dev = self;
	if (device_cfdata(sc->sc_wdcdev.sc_atac.atac_dev)->cf_flags &
	    WDC_OPTIONS_DMA) {
		if (ca->ca_nreg >= 16 || ca->ca_nintr == -1)
			use_dma = 1;	/* XXX Don't work yet. */
	}

	if (ca->ca_nintr >= 4 && ca->ca_nreg >= 8) {
		intr = ca->ca_intr[0];
		aprint_normal(" irq %d", intr);
		if (ca->ca_nintr > 8) {
			type = ca->ca_intr[1] ? IST_LEVEL : IST_EDGE;
		}
		aprint_normal(", %s triggered", (type == IST_EDGE) ? "edge" : "level");
	} else if (ca->ca_nintr == -1) {
		intr = WDC_DEFAULT_PIO_IRQ;
		aprint_normal(" irq property not found; using %d", intr);
	} else {
		aprint_error(": couldn't get irq property\n");
		return;
	}

	if (use_dma)
		aprint_normal(": DMA transfer");

	aprint_normal("\n");

	sc->sc_wdcdev.regs = wdr = &sc->sc_wdc_regs;

	wdr->cmd_iot = wdr->ctl_iot = ca->ca_tag;

	if (bus_space_map(wdr->cmd_iot, ca->ca_baseaddr + ca->ca_reg[0],
	    WDC_REG_NPORTS << 4, 0, &wdr->cmd_baseioh) ||
	    bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh,
			WDC_AUXREG_OFFSET << 4, 1, &wdr->ctl_ioh)) {
		aprint_error_dev(self, "couldn't map registers\n");
		return;
	}

	for (i = 0; i < WDC_NREG; i++) {
		if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, i << 4,
		    i == 0 ? 4 : 1, &wdr->cmd_iohs[i]) != 0) {
			bus_space_unmap(wdr->cmd_iot, wdr->cmd_baseioh,
			    WDC_REG_NPORTS << 4);
			aprint_error_dev(self,
			    "couldn't subregion registers\n");
			return;
		}
	}
#if 0
	wdr->data32iot = wdr->cmd_iot;
	wdr->data32ioh = wdr->cmd_ioh;
#endif

	sc->sc_ih = intr_establish(intr, type, IPL_BIO, wdcintr, chp);

	if (use_dma) {
		sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20);
		/*
		 * XXX
		 * we don't use ca->ca_reg[3] for size here because at least
		 * on the PB3400c it says 0x200 for both IDE channels ( the
		 * one on the mainboard and the other on the mediabay ) but
		 * their start addresses are only 0x100 apart. Since those
		 * DMA registers are always 0x100 or less we don't really 
		 * have to care though
		 */
		if (bus_space_map(wdr->cmd_iot, ca->ca_baseaddr + ca->ca_reg[2],
		    0x100, BUS_SPACE_MAP_LINEAR, &sc->sc_dmaregh)) {

			aprint_error_dev(self,
			    "unable to map DMA registers (%08x)\n",
			    ca->ca_reg[2]);
			/* should unmap stuff here */
			return;
		}
		sc->sc_dmareg = bus_space_vaddr(wdr->cmd_iot, sc->sc_dmaregh);

		sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA;
		sc->sc_wdcdev.sc_atac.atac_dma_cap = 2;
		if (strcmp(ca->ca_name, "ata-4") == 0) {
			sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA;
			sc->sc_wdcdev.sc_atac.atac_udma_cap = 4;
			sc->sc_wdcdev.sc_atac.atac_set_modes = 
			    ata4_adjust_timing;
		} else {
			sc->sc_wdcdev.sc_atac.atac_set_modes = adjust_timing;
		}
#ifdef notyet
		/* Minimum cycle time is 150ns (DMA MODE 1) on ohare. */
		if (ohare) {
			sc->sc_wdcdev.sc_atac.atac_pio_cap = 3;
			sc->sc_wdcdev.sc_atac.atac_dma_cap = 1;
		}
#endif
	} else {
		/* all non-DMA controllers can use adjust_timing */
		sc->sc_wdcdev.sc_atac.atac_set_modes = adjust_timing;
	}

	sc->sc_wdcdev.sc_atac.atac_pio_cap = 4;
	sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16;
	sc->sc_chanptr = chp;
	sc->sc_wdcdev.sc_atac.atac_channels = &sc->sc_chanptr;
	sc->sc_wdcdev.sc_atac.atac_nchannels = 1;
	sc->sc_wdcdev.wdc_maxdrives = 2;
	sc->sc_wdcdev.dma_arg = sc;
	sc->sc_wdcdev.dma_init = wdc_obio_dma_init;
	sc->sc_wdcdev.dma_start = wdc_obio_dma_start;
	sc->sc_wdcdev.dma_finish = wdc_obio_dma_finish;
	chp->ch_channel = 0;
	chp->ch_atac = &sc->sc_wdcdev.sc_atac;
	chp->ch_queue = &sc->sc_chqueue;

	wdc_init_shadow_regs(chp);

#define OHARE_FEATURE_REG	0xf3000038

	/* XXX Enable wdc1 by feature reg. */
	memset(path, 0, sizeof(path));
	OF_package_to_path(ca->ca_node, path, sizeof(path));
	if (strcmp(path, "/bandit@F2000000/ohare@10/ata@21000") == 0) {
		u_int x;

		x = in32rb(OHARE_FEATURE_REG);
		x |= 8;
		out32rb(OHARE_FEATURE_REG, x);
	}

	wdcattach(chp);
}