118334Speter/*-
250397Sobrien * Copyright (c) 2004 TAKAHASHI Yoshihiro
318334Speter * All rights reserved.
418334Speter *
518334Speter * Redistribution and use in source and binary forms, with or without
618334Speter * modification, are permitted provided that the following conditions
718334Speter * are met:
818334Speter * 1. Redistributions of source code must retain the above copyright
918334Speter *    notice, this list of conditions, and the following disclaimer,
1018334Speter *    without modification, immediately at the beginning of the file.
1118334Speter * 2. Redistributions in binary form must reproduce the above copyright
1218334Speter *    notice, this list of conditions and the following disclaimer in
1318334Speter *    the documentation and/or other materials provided with the
1418334Speter *    distribution.
1518334Speter *
1618334Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1718334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1818334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1918334Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
2018334Speter * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2118334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2250397Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2318334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2418334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2550397Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2618334Speter * SUCH DAMAGE.
2718334Speter */
2818334Speter
2918334Speter#include <sys/cdefs.h>
3018334Speter__FBSDID("$FreeBSD: releng/10.3/sys/pc98/cbus/fdc_cbus.c 146216 2005-05-14 10:51:16Z nyan $");
3150397Sobrien
3250397Sobrien#include <sys/param.h>
3350397Sobrien#include <sys/bio.h>
3418334Speter#include <sys/bus.h>
3550397Sobrien#include <sys/kernel.h>
3618334Speter#include <sys/module.h>
3718334Speter#include <sys/rman.h>
3818334Speter#include <sys/systm.h>
3918334Speter
4018334Speter#include <machine/bus.h>
4118334Speter
4218334Speter#include <pc98/cbus/cbus.h>
4318334Speter#include <pc98/cbus/fdcreg.h>
4418334Speter#include <pc98/cbus/fdcvar.h>
4518334Speter
4618334Speter#include <isa/isavar.h>
4718334Speter
4850397Sobrienstatic bus_addr_t fdc_iat[] = {0, 2, 4};
4950397Sobrien
5050397Sobrienstatic int
5150397Sobrienfdc_cbus_alloc_resources(device_t dev, struct fdc_data *fdc)
5250397Sobrien{
5350397Sobrien	int rid;
5450397Sobrien
5550397Sobrien	fdc->fdc_dev = dev;
5650397Sobrien	fdc->rid_ioport = 0;
5750397Sobrien	fdc->rid_irq = 0;
5850397Sobrien	fdc->rid_drq = 0;
5950397Sobrien	fdc->res_irq = 0;
6050397Sobrien	fdc->res_drq = 0;
6118334Speter
6250397Sobrien	fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
6350397Sobrien					      &fdc->rid_ioport, fdc_iat,
6450397Sobrien					      3, RF_ACTIVE);
6518334Speter	if (fdc->res_ioport == 0) {
6618334Speter		device_printf(dev, "cannot reserve I/O port range\n");
6718334Speter		return ENXIO;
6818334Speter	}
6950397Sobrien	isa_load_resourcev(fdc->res_ioport, fdc_iat, 3);
7018334Speter	fdc->portt = rman_get_bustag(fdc->res_ioport);
7118334Speter	fdc->porth = rman_get_bushandle(fdc->res_ioport);
7218334Speter
7318334Speter	rid = 3;
7418334Speter	bus_set_resource(dev, SYS_RES_IOPORT, rid, IO_FDPORT, 1);
7518334Speter	fdc->res_fdsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
7618334Speter						RF_ACTIVE);
7750397Sobrien	if (fdc->res_fdsio == 0)
7818334Speter		return ENXIO;
7918334Speter	fdc->sc_fdsiot = rman_get_bustag(fdc->res_fdsio);
8018334Speter	fdc->sc_fdsioh = rman_get_bushandle(fdc->res_fdsio);
8118334Speter
8218334Speter	rid = 4;
8318334Speter	bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x4be, 1);
8418334Speter	fdc->res_fdemsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
8518334Speter						  RF_ACTIVE);
8618334Speter	if (fdc->res_fdemsio == 0)
8718334Speter		return ENXIO;
8818334Speter	fdc->sc_fdemsiot = rman_get_bustag(fdc->res_fdemsio);
8918334Speter	fdc->sc_fdemsioh = rman_get_bushandle(fdc->res_fdemsio);
9018334Speter
9118334Speter	fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
9218334Speter					      RF_ACTIVE);
9318334Speter	if (fdc->res_irq == 0) {
9418334Speter		device_printf(dev, "cannot reserve interrupt line\n");
9518334Speter		return ENXIO;
9618334Speter	}
9718334Speter
9818334Speter	if ((fdc->flags & FDC_NODMA) == 0) {
9918334Speter		fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
10018334Speter						      &fdc->rid_drq, RF_ACTIVE);
10118334Speter		if (fdc->res_drq == 0) {
10218334Speter			device_printf(dev, "cannot reserve DMA request line\n");
10318334Speter			return ENXIO;
10418334Speter		}
10518334Speter		fdc->dmachan = rman_get_start(fdc->res_drq);
10618334Speter	}
10718334Speter
10818334Speter	return 0;
10918334Speter}
11018334Speter
11118334Speterstatic int
11218334Speterfdc_cbus_probe(device_t dev)
11318334Speter{
11418334Speter	int	error;
11518334Speter	struct	fdc_data *fdc;
11618334Speter
11718334Speter	fdc = device_get_softc(dev);
11818334Speter
11918334Speter	/* Check pnp ids */
12018334Speter	if (isa_get_vendorid(dev))
12118334Speter		return (ENXIO);
12218334Speter
12318334Speter	/* Attempt to allocate our resources for the duration of the probe */
12418334Speter	error = fdc_cbus_alloc_resources(dev, fdc);
12550397Sobrien	if (!error)
12618334Speter		error = fdc_initial_reset(fdc);
12718334Speter
12818334Speter	fdc_release_resources(fdc);
12918334Speter	return (error);
13018334Speter}
13118334Speter
13218334Speterstatic int
13318334Speterfdc_cbus_attach(device_t dev)
13418334Speter{
13518334Speter	struct	fdc_data *fdc;
13618334Speter	int error;
13718334Speter
13818334Speter	fdc = device_get_softc(dev);
13950397Sobrien
14050397Sobrien	if ((error = fdc_cbus_alloc_resources(dev, fdc)) != 0 ||
14118334Speter	    (error = fdc_attach(dev)) != 0 ||
14218334Speter	    (error = fdc_hints_probe(dev)) != 0) {
14318334Speter		fdc_release_resources(fdc);
14418334Speter		return (error);
14518334Speter	}
14618334Speter
14718334Speter	return (0);
14818334Speter}
14918334Speter
15018334Speterstatic device_method_t fdc_methods[] = {
15118334Speter	/* Device interface */
15218334Speter	DEVMETHOD(device_probe,		fdc_cbus_probe),
15318334Speter	DEVMETHOD(device_attach,	fdc_cbus_attach),
15418334Speter	DEVMETHOD(device_detach,	fdc_detach),
15518334Speter	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
15618334Speter	DEVMETHOD(device_suspend,	bus_generic_suspend),
15718334Speter	DEVMETHOD(device_resume,	bus_generic_resume),
15818334Speter
15918334Speter	/* Bus interface */
16050397Sobrien	DEVMETHOD(bus_print_child,	fdc_print_child),
16118334Speter	DEVMETHOD(bus_read_ivar,	fdc_read_ivar),
16250397Sobrien	DEVMETHOD(bus_write_ivar,       fdc_write_ivar),
16350397Sobrien	/* Our children never use any other bus interface methods. */
16418334Speter
16518334Speter	{ 0, 0 }
16618334Speter};
16718334Speter
16818334Speterstatic driver_t fdc_driver = {
16950397Sobrien	"fdc",
17050397Sobrien	fdc_methods,
17118334Speter	sizeof(struct fdc_data)
17218334Speter};
17318334Speter
17418334SpeterDRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0);
17518334Speter