xref: /NextBSD/sys/dev/aha/aha_mca.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
1 /*-
2  * Copyright (c) 1999 Matthew N. Dodd <winter@jurai.net>
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  * Based on aha_isa.c
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/mutex.h>
38 
39 #include <sys/module.h>
40 #include <sys/bus.h>
41 #include <machine/bus.h>
42 #include <machine/resource.h>
43 #include <sys/rman.h>
44 
45 #include <isa/isavar.h>
46 
47 #include <dev/mca/mca_busreg.h>
48 #include <dev/mca/mca_busvar.h>
49 
50 #include <dev/aha/ahareg.h>
51 
52 static struct mca_ident aha_mca_devs[] = {
53 	{ 0x0f1f, "Adaptec AHA-1640 SCSI Adapter" },
54 	{ 0, NULL },
55 };
56 
57 #define AHA_MCA_IOPORT_POS		MCA_ADP_POS(MCA_POS1)
58 # define AHA_MCA_IOPORT_MASK1		0x07
59 # define AHA_MCA_IOPORT_MASK2		0xc0
60 # define AHA_MCA_IOPORT_SIZE		0x03
61 # define AHA_MCA_IOPORT(pos)		(0x30 + \
62 					(((uint32_t)pos & \
63 						AHA_MCA_IOPORT_MASK1) << 8) + \
64 					(((uint32_t)pos & \
65 						AHA_MCA_IOPORT_MASK2) >> 4))
66 
67 #define AHA_MCA_DRQ_POS			MCA_ADP_POS(MCA_POS3)
68 # define AHA_MCA_DRQ_MASK		0x0f
69 # define AHA_MCA_DRQ(pos)		(pos & AHA_MCA_DRQ_MASK)
70 
71 #define AHA_MCA_IRQ_POS			MCA_ADP_POS(MCA_POS2)
72 # define AHA_MCA_IRQ_MASK		0x07
73 # define AHA_MCA_IRQ(pos)		((pos & AHA_MCA_IRQ_MASK) + 8)
74 
75 /*
76  * Not needed as the board knows its config
77  * internally and the ID will be fetched
78  * via AOP_INQUIRE_SETUP_INFO command.
79  */
80 #define AHA_MCA_SCSIID_POS		MCA_ADP_POS(MCA_POS2)
81 #define AHA_MCA_SCSIID_MASK		0xe0
82 #define AHA_MCA_SCSIID(pos)		((pos & AHA_MCA_SCSIID_MASK) >> 5)
83 
84 static int
aha_mca_probe(device_t dev)85 aha_mca_probe (device_t dev)
86 {
87 	const char *	desc;
88 	mca_id_t	id = mca_get_id(dev);
89 	uint32_t	iobase = 0;
90 	uint32_t	iosize = 0;
91 	uint8_t		drq = 0;
92 	uint8_t		irq = 0;
93 	uint8_t		pos;
94 
95 	desc = mca_match_id(id, aha_mca_devs);
96 	if (!desc)
97 		return (ENXIO);
98 	device_set_desc(dev, desc);
99 
100 	pos = mca_pos_read(dev, AHA_MCA_IOPORT_POS);
101 	iobase = AHA_MCA_IOPORT(pos);
102 	iosize = AHA_MCA_IOPORT_SIZE;
103 
104 	pos = mca_pos_read(dev, AHA_MCA_DRQ_POS);
105 	drq = AHA_MCA_DRQ(pos);
106 
107 	pos = mca_pos_read(dev, AHA_MCA_IRQ_POS);
108 	irq = AHA_MCA_IRQ(pos);
109 
110 	mca_add_iospace(dev, iobase, iosize);
111 	mca_add_drq(dev, drq);
112 	mca_add_irq(dev, irq);
113 
114 	return (0);
115 }
116 
117 static int
aha_mca_attach(device_t dev)118 aha_mca_attach (device_t dev)
119 {
120 	struct aha_softc *	sc = device_get_softc(dev);
121 	int			error = ENOMEM;
122 
123 	sc->portrid = 0;
124 	sc->port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->portrid,
125 	    RF_ACTIVE);
126 	if (sc->port == NULL) {
127 		device_printf(dev, "No I/O space?!\n");
128 		goto bad;
129 	}
130 
131 	sc->irqrid = 0;
132 	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid,
133 	    RF_ACTIVE);
134 	if (sc->irq == NULL) {
135 		device_printf(dev, "No IRQ?!\n");
136 		goto bad;
137 	}
138 
139 	sc->drqrid = 0;
140 	sc->drq = bus_alloc_resource_any(dev, SYS_RES_DRQ, &sc->drqrid,
141 	    RF_ACTIVE);
142 	if (sc->drq == NULL) {
143 		device_printf(dev, "No DRQ?!\n");
144 		goto bad;
145 	}
146 
147 	aha_alloc(sc);
148 	error = aha_probe(sc);
149 	if (error) {
150 		device_printf(dev, "aha_probe() failed!\n");
151 		goto bad;
152 	}
153 
154 	error = aha_fetch_adapter_info(sc);
155 	if (error) {
156 		device_printf(dev, "aha_fetch_adapter_info() failed!\n");
157 		goto bad;
158 	}
159 
160 	isa_dmacascade(rman_get_start(sc->drq));
161 
162 	error = bus_dma_tag_create(
163 				/* parent	*/ bus_get_dma_tag(dev),
164 				/* alignemnt	*/ 1,
165 				/* boundary	*/ 0,
166 				/* lowaddr	*/ BUS_SPACE_MAXADDR_24BIT,
167 				/* highaddr	*/ BUS_SPACE_MAXADDR,
168 				/* filter	*/ NULL,
169 				/* filterarg	*/ NULL,
170 				/* maxsize	*/ BUS_SPACE_MAXSIZE_24BIT,
171 				/* nsegments	*/ ~0,
172 				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_24BIT,
173 				/* flags	*/ 0,
174 				/* lockfunc	*/ NULL,
175 				/* lockarg	*/ NULL,
176 				&sc->parent_dmat);
177 	if (error) {
178 		device_printf(dev, "bus_dma_tag_create() failed!\n");
179 		goto bad;
180 	}
181 
182 	error = aha_init(sc);
183 	if (error) {
184 		device_printf(dev, "aha_init() failed\n");
185 		goto bad;
186 	}
187 
188 	error = aha_attach(sc);
189 	if (error) {
190 		device_printf(dev, "aha_attach() failed\n");
191 		goto bad;
192 	}
193 
194 	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_CAM | INTR_ENTROPY |
195 	    INTR_MPSAFE, NULL, aha_intr, sc, &sc->ih);
196 	if (error) {
197 		device_printf(dev, "Unable to register interrupt handler\n");
198 		aha_detach(sc);
199 		goto bad;
200 	}
201 
202 	return (0);
203 
204 bad:
205 	aha_free(sc);
206 	bus_free_resource(dev, SYS_RES_IOPORT, sc->port);
207 	bus_free_resource(dev, SYS_RES_IRQ, sc->irq);
208 	bus_free_resource(dev, SYS_RES_DRQ, sc->drq);
209 	return (error);
210 }
211 
212 static device_method_t aha_mca_methods[] = {
213 	DEVMETHOD(device_probe,         aha_mca_probe),
214 	DEVMETHOD(device_attach,        aha_mca_attach),
215 
216 	{ 0, 0 }
217 };
218 
219 static driver_t aha_mca_driver = {
220 	"aha",
221 	aha_mca_methods,
222 	1,
223 /*
224 	sizeof(struct aha_softc *),
225  */
226 };
227 
228 static devclass_t aha_devclass;
229 
230 DRIVER_MODULE(aha, mca, aha_mca_driver, aha_devclass, 0, 0);
231 MODULE_DEPEND(aha, mca, 1, 1, 1);
232