1132286Snyan/*-
2146216Snyan * Copyright (c) 2004 TAKAHASHI Yoshihiro
3131819Snyan * All rights reserved.
4131819Snyan *
5131819Snyan * Redistribution and use in source and binary forms, with or without
6131819Snyan * modification, are permitted provided that the following conditions
7131819Snyan * are met:
8131819Snyan * 1. Redistributions of source code must retain the above copyright
9131819Snyan *    notice, this list of conditions, and the following disclaimer,
10131819Snyan *    without modification, immediately at the beginning of the file.
11131819Snyan * 2. Redistributions in binary form must reproduce the above copyright
12131819Snyan *    notice, this list of conditions and the following disclaimer in
13131819Snyan *    the documentation and/or other materials provided with the
14131819Snyan *    distribution.
15131819Snyan *
16131819Snyan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17131819Snyan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18131819Snyan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19131819Snyan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20131819Snyan * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21131819Snyan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22131819Snyan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23131819Snyan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24131819Snyan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25131819Snyan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26131819Snyan * SUCH DAMAGE.
27131819Snyan */
28131819Snyan
29131819Snyan#include <sys/cdefs.h>
30131819Snyan__FBSDID("$FreeBSD$");
31131819Snyan
32131819Snyan#include <sys/param.h>
33131819Snyan#include <sys/bio.h>
34131819Snyan#include <sys/bus.h>
35131819Snyan#include <sys/kernel.h>
36131819Snyan#include <sys/module.h>
37131819Snyan#include <sys/rman.h>
38131819Snyan#include <sys/systm.h>
39131819Snyan
40132103Snyan#include <machine/bus.h>
41132103Snyan
42146049Snyan#include <pc98/cbus/cbus.h>
43146049Snyan#include <pc98/cbus/fdcreg.h>
44146049Snyan#include <pc98/cbus/fdcvar.h>
45131819Snyan
46131819Snyan#include <isa/isavar.h>
47131819Snyan
48132210Snyanstatic bus_addr_t fdc_iat[] = {0, 2, 4};
49132210Snyan
50131819Snyanstatic int
51132210Snyanfdc_cbus_alloc_resources(device_t dev, struct fdc_data *fdc)
52132210Snyan{
53132210Snyan	int rid;
54132210Snyan
55132210Snyan	fdc->fdc_dev = dev;
56132210Snyan	fdc->rid_ioport = 0;
57132210Snyan	fdc->rid_irq = 0;
58132210Snyan	fdc->rid_drq = 0;
59132210Snyan	fdc->res_irq = 0;
60132210Snyan	fdc->res_drq = 0;
61132210Snyan
62132210Snyan	fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
63132210Snyan					      &fdc->rid_ioport, fdc_iat,
64132210Snyan					      3, RF_ACTIVE);
65132210Snyan	if (fdc->res_ioport == 0) {
66132210Snyan		device_printf(dev, "cannot reserve I/O port range\n");
67132210Snyan		return ENXIO;
68132210Snyan	}
69132210Snyan	isa_load_resourcev(fdc->res_ioport, fdc_iat, 3);
70132210Snyan	fdc->portt = rman_get_bustag(fdc->res_ioport);
71132210Snyan	fdc->porth = rman_get_bushandle(fdc->res_ioport);
72132210Snyan
73132210Snyan	rid = 3;
74132210Snyan	bus_set_resource(dev, SYS_RES_IOPORT, rid, IO_FDPORT, 1);
75132210Snyan	fdc->res_fdsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
76132210Snyan						RF_ACTIVE);
77132210Snyan	if (fdc->res_fdsio == 0)
78132210Snyan		return ENXIO;
79132210Snyan	fdc->sc_fdsiot = rman_get_bustag(fdc->res_fdsio);
80132210Snyan	fdc->sc_fdsioh = rman_get_bushandle(fdc->res_fdsio);
81132210Snyan
82132210Snyan	rid = 4;
83132210Snyan	bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x4be, 1);
84132210Snyan	fdc->res_fdemsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
85132210Snyan						  RF_ACTIVE);
86132210Snyan	if (fdc->res_fdemsio == 0)
87132210Snyan		return ENXIO;
88132210Snyan	fdc->sc_fdemsiot = rman_get_bustag(fdc->res_fdemsio);
89132210Snyan	fdc->sc_fdemsioh = rman_get_bushandle(fdc->res_fdemsio);
90132210Snyan
91132210Snyan	fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
92132210Snyan					      RF_ACTIVE);
93132210Snyan	if (fdc->res_irq == 0) {
94132210Snyan		device_printf(dev, "cannot reserve interrupt line\n");
95132210Snyan		return ENXIO;
96132210Snyan	}
97132210Snyan
98132210Snyan	if ((fdc->flags & FDC_NODMA) == 0) {
99132210Snyan		fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
100132210Snyan						      &fdc->rid_drq, RF_ACTIVE);
101132210Snyan		if (fdc->res_drq == 0) {
102132210Snyan			device_printf(dev, "cannot reserve DMA request line\n");
103132210Snyan			return ENXIO;
104132210Snyan		}
105132210Snyan		fdc->dmachan = rman_get_start(fdc->res_drq);
106132210Snyan	}
107132210Snyan
108132210Snyan	return 0;
109132210Snyan}
110132210Snyan
111132210Snyanstatic int
112131819Snyanfdc_cbus_probe(device_t dev)
113131819Snyan{
114131819Snyan	int	error;
115131819Snyan	struct	fdc_data *fdc;
116131819Snyan
117131819Snyan	fdc = device_get_softc(dev);
118131819Snyan
119131819Snyan	/* Check pnp ids */
120131819Snyan	if (isa_get_vendorid(dev))
121131819Snyan		return (ENXIO);
122131819Snyan
123131819Snyan	/* Attempt to allocate our resources for the duration of the probe */
124132210Snyan	error = fdc_cbus_alloc_resources(dev, fdc);
125132103Snyan	if (!error)
126132103Snyan		error = fdc_initial_reset(fdc);
127131819Snyan
128131819Snyan	fdc_release_resources(fdc);
129131819Snyan	return (error);
130131819Snyan}
131131819Snyan
132132210Snyanstatic int
133132210Snyanfdc_cbus_attach(device_t dev)
134132210Snyan{
135132210Snyan	struct	fdc_data *fdc;
136132286Snyan	int error;
137132210Snyan
138132210Snyan	fdc = device_get_softc(dev);
139132210Snyan
140132210Snyan	if ((error = fdc_cbus_alloc_resources(dev, fdc)) != 0 ||
141132286Snyan	    (error = fdc_attach(dev)) != 0 ||
142132286Snyan	    (error = fdc_hints_probe(dev)) != 0) {
143132210Snyan		fdc_release_resources(fdc);
144132210Snyan		return (error);
145132210Snyan	}
146132210Snyan
147132210Snyan	return (0);
148132210Snyan}
149132210Snyan
150131819Snyanstatic device_method_t fdc_methods[] = {
151131819Snyan	/* Device interface */
152131819Snyan	DEVMETHOD(device_probe,		fdc_cbus_probe),
153132210Snyan	DEVMETHOD(device_attach,	fdc_cbus_attach),
154131819Snyan	DEVMETHOD(device_detach,	fdc_detach),
155131819Snyan	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
156131819Snyan	DEVMETHOD(device_suspend,	bus_generic_suspend),
157131819Snyan	DEVMETHOD(device_resume,	bus_generic_resume),
158131819Snyan
159131819Snyan	/* Bus interface */
160131819Snyan	DEVMETHOD(bus_print_child,	fdc_print_child),
161131819Snyan	DEVMETHOD(bus_read_ivar,	fdc_read_ivar),
162132103Snyan	DEVMETHOD(bus_write_ivar,       fdc_write_ivar),
163131819Snyan	/* Our children never use any other bus interface methods. */
164131819Snyan
165131819Snyan	{ 0, 0 }
166131819Snyan};
167131819Snyan
168131819Snyanstatic driver_t fdc_driver = {
169131819Snyan	"fdc",
170131819Snyan	fdc_methods,
171131819Snyan	sizeof(struct fdc_data)
172131819Snyan};
173131819Snyan
174131819SnyanDRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0);
175