1/*-
2 * cyclades cyclom-y serial driver
3 *	Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993
4 *
5 * Copyright (c) 1993 Andrew Herbert.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. The name Andrew Herbert may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
22 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/*
32 * Cyclades Y ISA serial interface driver
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD$");
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/bus.h>
41#include <sys/kernel.h>
42#include <sys/module.h>
43
44#include <machine/bus.h>
45#include <sys/rman.h>
46#include <machine/resource.h>
47
48#include <isa/isavar.h>
49
50#include <dev/cy/cyreg.h>
51#include <dev/cy/cyvar.h>
52
53static int	cy_isa_attach(device_t dev);
54static int	cy_isa_probe(device_t dev);
55
56static device_method_t cy_isa_methods[] = {
57	/* Device interface. */
58	DEVMETHOD(device_probe,		cy_isa_probe),
59	DEVMETHOD(device_attach,	cy_isa_attach),
60
61	{ 0, 0 }
62};
63
64static driver_t cy_isa_driver = {
65	cy_driver_name,
66	cy_isa_methods,
67	0,
68};
69
70DRIVER_MODULE(cy, isa, cy_isa_driver, cy_devclass, 0, 0);
71
72static int
73cy_isa_probe(device_t dev)
74{
75	struct resource *mem_res;
76	cy_addr iobase;
77	int error, mem_rid;
78
79	if (isa_get_logicalid(dev) != 0)	/* skip PnP probes */
80		return (ENXIO);
81
82	mem_rid = 0;
83	mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid,
84	    RF_ACTIVE);
85	if (mem_res == NULL) {
86		device_printf(dev, "ioport resource allocation failed\n");
87		return (ENXIO);
88	}
89	iobase = rman_get_virtual(mem_res);
90
91	/* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
92	cy_inb(iobase, CY16_RESET, 0);	/* XXX? */
93	DELAY(500);		/* wait for the board to get its act together */
94
95	/* this is needed to get the board out of reset */
96	cy_outb(iobase, CY_CLEAR_INTR, 0, 0);
97	DELAY(500);
98
99	error = (cy_units(iobase, 0) == 0 ? ENXIO : 0);
100	bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res);
101	return (error);
102}
103
104static int
105cy_isa_attach(device_t dev)
106{
107	struct resource *irq_res, *mem_res;
108	void *irq_cookie, *vaddr, *vsc;
109	int irq_rid, mem_rid;
110
111	irq_res = NULL;
112	mem_res = NULL;
113
114	mem_rid = 0;
115	mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid,
116	    RF_ACTIVE);
117	if (mem_res == NULL) {
118		device_printf(dev, "memory resource allocation failed\n");
119		goto fail;
120	}
121	vaddr = rman_get_virtual(mem_res);
122
123	vsc = cyattach_common(vaddr, 0);
124	if (vsc == NULL) {
125		device_printf(dev, "no ports found!\n");
126		goto fail;
127	}
128
129	irq_rid = 0;
130	irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_rid,
131	    RF_SHAREABLE | RF_ACTIVE);
132	if (irq_res == NULL) {
133		device_printf(dev, "interrupt resource allocation failed\n");
134		goto fail;
135	}
136	if (bus_setup_intr(dev, irq_res, INTR_TYPE_TTY,
137	    cyintr, NULL, vsc, &irq_cookie) != 0) {
138		device_printf(dev, "interrupt setup failed\n");
139		goto fail;
140	}
141
142	return (0);
143
144fail:
145	if (irq_res != NULL)
146		bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res);
147	if (mem_res != NULL)
148		bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res);
149	return (ENXIO);
150}
151