1195333Simp/*-
2195333Simp * Copyright (c) 2009 Neelkanth Natu
3195333Simp * All rights reserved.
4195333Simp *
5195333Simp * Redistribution and use in source and binary forms, with or without
6195333Simp * modification, are permitted provided that the following conditions
7195333Simp * are met:
8195333Simp * 1. Redistributions of source code must retain the above copyright
9195333Simp *    notice, this list of conditions and the following disclaimer.
10195333Simp * 2. Redistributions in binary form must reproduce the above copyright
11195333Simp *    notice, this list of conditions and the following disclaimer in the
12195333Simp *    documentation and/or other materials provided with the distribution.
13195333Simp *
14195333Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15195333Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16195333Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17195333Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18195333Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19195333Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20195333Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21195333Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22195333Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23195333Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24195333Simp * SUCH DAMAGE.
25195333Simp */
26195333Simp
27195333Simp#include <sys/param.h>
28195333Simp#include <sys/kernel.h>
29195333Simp#include <sys/systm.h>
30195333Simp#include <sys/module.h>
31195333Simp#include <sys/bus.h>
32195333Simp#include <sys/rman.h>
33195333Simp#include <sys/lock.h>
34195333Simp#include <sys/mutex.h>
35195333Simp#include <sys/sema.h>
36195333Simp#include <sys/taskqueue.h>
37195333Simp
38195333Simp#include <machine/bus.h>
39195333Simp
40195333Simp#include <vm/uma.h>
41195333Simp
42195333Simp#include <sys/ata.h>
43195333Simp#include <dev/ata/ata-all.h>
44195333Simp
45195333Simp#include <machine/resource.h>
46195333Simp
47195333Simp__FBSDID("$FreeBSD$");
48195333Simp
49195333Simpstatic int
50195333Simpata_zbbus_probe(device_t dev)
51195333Simp{
52195333Simp
53195333Simp	return (ata_probe(dev));
54195333Simp}
55195333Simp
56195333Simpstatic int
57195333Simpata_zbbus_attach(device_t dev)
58195333Simp{
59195333Simp	int i, rid, regshift, regoffset;
60195333Simp	struct ata_channel *ch;
61195333Simp	struct resource *io;
62195333Simp
63195333Simp	ch = device_get_softc(dev);
64195333Simp
65195333Simp	if (ch->attached)
66195333Simp		return (0);
67195333Simp	ch->attached = 1;
68195333Simp
69195333Simp	rid = 0;
70295790Sjhibbits	io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
71195333Simp	if (io == NULL)
72195333Simp		return (ENXIO);
73195333Simp
74195333Simp	/*
75195333Simp	 * SWARM needs an address shift of 5 when accessing ATA registers.
76195333Simp	 *
77195333Simp	 * For e.g. an access to register 4 actually needs an address
78195333Simp	 * of (4 << 5) to be output on the generic bus.
79195333Simp	 */
80195333Simp	regshift = 5;
81195333Simp	resource_int_value(device_get_name(dev), device_get_unit(dev),
82195333Simp			   "regshift", &regshift);
83195333Simp	if (regshift && bootverbose)
84195333Simp		device_printf(dev, "using a register shift of %d\n", regshift);
85195333Simp
86195333Simp	regoffset = 0x1F0;
87195333Simp	resource_int_value(device_get_name(dev), device_get_unit(dev),
88195333Simp			   "regoffset", &regoffset);
89195333Simp	if (regoffset && bootverbose) {
90195333Simp		device_printf(dev, "using a register offset of 0x%0x\n",
91195333Simp			      regoffset);
92195333Simp	}
93195333Simp
94195333Simp	/* setup the ata register addresses */
95195333Simp	for (i = ATA_DATA; i <= ATA_COMMAND; ++i) {
96195333Simp		ch->r_io[i].res = io;
97195333Simp		ch->r_io[i].offset = (regoffset + i) << regshift;
98195333Simp	}
99195333Simp
100195333Simp	ch->r_io[ATA_CONTROL].res = io;
101195333Simp	ch->r_io[ATA_CONTROL].offset = (regoffset + ATA_CTLOFFSET) << regshift;
102195333Simp	ch->r_io[ATA_IDX_ADDR].res = io;	/* XXX what is this used for */
103195333Simp	ata_default_registers(dev);
104195333Simp
105195333Simp	/* initialize softc for this channel */
106195333Simp	ch->unit = 0;
107195333Simp	ch->flags |= ATA_USE_16BIT;
108195333Simp	ata_generic_hw(dev);
109195333Simp
110195333Simp	return (ata_attach(dev));
111195333Simp}
112195333Simp
113195333Simpstatic int
114195333Simpata_zbbus_detach(device_t dev)
115195333Simp{
116195333Simp	int error;
117195333Simp	struct ata_channel *ch = device_get_softc(dev);
118195333Simp
119195333Simp	if (!ch->attached)
120195333Simp		return (0);
121195333Simp	ch->attached = 0;
122195333Simp
123195333Simp	error = ata_detach(dev);
124195333Simp
125195333Simp	bus_release_resource(dev, SYS_RES_MEMORY, 0,
126195333Simp			     ch->r_io[ATA_IDX_ADDR].res);
127195333Simp
128195333Simp	return (error);
129195333Simp}
130195333Simp
131195333Simpstatic int
132195333Simpata_zbbus_suspend(device_t dev)
133195333Simp{
134195333Simp	struct ata_channel *ch = device_get_softc(dev);
135195333Simp
136195333Simp	if (!ch->attached)
137195333Simp		return (0);
138195333Simp
139195333Simp	return (ata_suspend(dev));
140195333Simp}
141195333Simp
142195333Simpstatic int
143195333Simpata_zbbus_resume(device_t dev)
144195333Simp{
145195333Simp	struct ata_channel *ch = device_get_softc(dev);
146195333Simp
147195333Simp	if (!ch->attached)
148195333Simp		return (0);
149195333Simp
150195333Simp	return (ata_resume(dev));
151195333Simp}
152195333Simp
153195333Simpstatic device_method_t ata_zbbus_methods[] = {
154195333Simp	/* device interface */
155195333Simp	DEVMETHOD(device_probe,		ata_zbbus_probe),
156195333Simp	DEVMETHOD(device_attach,	ata_zbbus_attach),
157195333Simp	DEVMETHOD(device_detach,	ata_zbbus_detach),
158195333Simp	DEVMETHOD(device_suspend,	ata_zbbus_suspend),
159195333Simp	DEVMETHOD(device_resume,	ata_zbbus_resume),
160195333Simp
161195333Simp	{ 0, 0 }
162195333Simp};
163195333Simp
164195333Simpstatic driver_t ata_zbbus_driver = {
165195333Simp	"ata",
166195333Simp	ata_zbbus_methods,
167195333Simp	sizeof(struct ata_channel)
168195333Simp};
169195333Simp
170195333SimpDRIVER_MODULE(ata, zbbus, ata_zbbus_driver, ata_devclass, 0, 0);
171