1/*-
2 * Copyright (c) 2009 Neelkanth Natu
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/param.h>
28#include <sys/kernel.h>
29#include <sys/systm.h>
30#include <sys/module.h>
31#include <sys/bus.h>
32#include <sys/rman.h>
33#include <sys/lock.h>
34#include <sys/mutex.h>
35#include <sys/sema.h>
36#include <sys/taskqueue.h>
37
38#include <machine/bus.h>
39
40#include <vm/uma.h>
41
42#include <sys/ata.h>
43#include <dev/ata/ata-all.h>
44
45#include <machine/resource.h>
46
47__FBSDID("$FreeBSD$");
48
49static int
50ata_zbbus_probe(device_t dev)
51{
52
53	return (ata_probe(dev));
54}
55
56static int
57ata_zbbus_attach(device_t dev)
58{
59	int i, rid, regshift, regoffset;
60	struct ata_channel *ch;
61	struct resource *io;
62
63	ch = device_get_softc(dev);
64
65	if (ch->attached)
66		return (0);
67	ch->attached = 1;
68
69	rid = 0;
70	io = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE);
71	if (io == NULL)
72		return (ENXIO);
73
74	/*
75	 * SWARM needs an address shift of 5 when accessing ATA registers.
76	 *
77	 * For e.g. an access to register 4 actually needs an address
78	 * of (4 << 5) to be output on the generic bus.
79	 */
80	regshift = 5;
81	resource_int_value(device_get_name(dev), device_get_unit(dev),
82			   "regshift", &regshift);
83	if (regshift && bootverbose)
84		device_printf(dev, "using a register shift of %d\n", regshift);
85
86	regoffset = 0x1F0;
87	resource_int_value(device_get_name(dev), device_get_unit(dev),
88			   "regoffset", &regoffset);
89	if (regoffset && bootverbose) {
90		device_printf(dev, "using a register offset of 0x%0x\n",
91			      regoffset);
92	}
93
94	/* setup the ata register addresses */
95	for (i = ATA_DATA; i <= ATA_COMMAND; ++i) {
96		ch->r_io[i].res = io;
97		ch->r_io[i].offset = (regoffset + i) << regshift;
98	}
99
100	ch->r_io[ATA_CONTROL].res = io;
101	ch->r_io[ATA_CONTROL].offset = (regoffset + ATA_CTLOFFSET) << regshift;
102	ch->r_io[ATA_IDX_ADDR].res = io;	/* XXX what is this used for */
103	ata_default_registers(dev);
104
105	/* initialize softc for this channel */
106	ch->unit = 0;
107	ch->flags |= ATA_USE_16BIT;
108	ata_generic_hw(dev);
109
110	return (ata_attach(dev));
111}
112
113static int
114ata_zbbus_detach(device_t dev)
115{
116	int error;
117	struct ata_channel *ch = device_get_softc(dev);
118
119	if (!ch->attached)
120		return (0);
121	ch->attached = 0;
122
123	error = ata_detach(dev);
124
125	bus_release_resource(dev, SYS_RES_MEMORY, 0,
126			     ch->r_io[ATA_IDX_ADDR].res);
127
128	return (error);
129}
130
131static int
132ata_zbbus_suspend(device_t dev)
133{
134	struct ata_channel *ch = device_get_softc(dev);
135
136	if (!ch->attached)
137		return (0);
138
139	return (ata_suspend(dev));
140}
141
142static int
143ata_zbbus_resume(device_t dev)
144{
145	struct ata_channel *ch = device_get_softc(dev);
146
147	if (!ch->attached)
148		return (0);
149
150	return (ata_resume(dev));
151}
152
153static device_method_t ata_zbbus_methods[] = {
154	/* device interface */
155	DEVMETHOD(device_probe,		ata_zbbus_probe),
156	DEVMETHOD(device_attach,	ata_zbbus_attach),
157	DEVMETHOD(device_detach,	ata_zbbus_detach),
158	DEVMETHOD(device_suspend,	ata_zbbus_suspend),
159	DEVMETHOD(device_resume,	ata_zbbus_resume),
160
161	{ 0, 0 }
162};
163
164static driver_t ata_zbbus_driver = {
165	"ata",
166	ata_zbbus_methods,
167	sizeof(struct ata_channel)
168};
169
170DRIVER_MODULE(ata, zbbus, ata_zbbus_driver, ata_devclass, 0, 0);
171