19406Sbde/*-
26261Sjkh * cyclades cyclom-y serial driver
36261Sjkh *	Andrew Herbert <andrew@werple.apana.org.au>, 17 August 1993
46261Sjkh *
56261Sjkh * Copyright (c) 1993 Andrew Herbert.
66261Sjkh * All rights reserved.
76261Sjkh *
86261Sjkh * Redistribution and use in source and binary forms, with or without
96261Sjkh * modification, are permitted provided that the following conditions
106261Sjkh * are met:
116261Sjkh * 1. Redistributions of source code must retain the above copyright
126261Sjkh *    notice, this list of conditions and the following disclaimer.
136261Sjkh * 2. Redistributions in binary form must reproduce the above copyright
146261Sjkh *    notice, this list of conditions and the following disclaimer in the
156261Sjkh *    documentation and/or other materials provided with the distribution.
166261Sjkh * 3. The name Andrew Herbert may not be used to endorse or promote products
176261Sjkh *    derived from this software without specific prior written permission.
186261Sjkh *
196261Sjkh * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
206261Sjkh * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
216261Sjkh * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
226261Sjkh * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
236261Sjkh * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
246261Sjkh * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
256261Sjkh * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
266261Sjkh * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
276261Sjkh * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
286261Sjkh * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
296261Sjkh */
306261Sjkh
31128804Sbde/*
32128804Sbde * Cyclades Y ISA serial interface driver
33128804Sbde */
34128804Sbde
35115703Sobrien#include <sys/cdefs.h>
36115703Sobrien__FBSDID("$FreeBSD$");
37115703Sobrien
386261Sjkh#include <sys/param.h>
396261Sjkh#include <sys/systm.h>
4076166Smarkm#include <sys/bus.h>
416261Sjkh#include <sys/kernel.h>
42129879Sphk#include <sys/module.h>
4376166Smarkm
44127885Sbde#include <machine/bus.h>
45127885Sbde#include <sys/rman.h>
46127885Sbde#include <machine/resource.h>
476261Sjkh
48128800Sbde#include <isa/isavar.h>
496261Sjkh
50128800Sbde#include <dev/cy/cyreg.h>
51128800Sbde#include <dev/cy/cyvar.h>
52128800Sbde
53128804Sbdestatic int	cy_isa_attach(device_t dev);
54128804Sbdestatic int	cy_isa_probe(device_t dev);
559406Sbde
56127885Sbdestatic device_method_t cy_isa_methods[] = {
57127885Sbde	/* Device interface. */
58127885Sbde	DEVMETHOD(device_probe,		cy_isa_probe),
59127885Sbde	DEVMETHOD(device_attach,	cy_isa_attach),
60127885Sbde
61127885Sbde	{ 0, 0 }
6212962Sbde};
6312675Sjulian
64127885Sbdestatic driver_t cy_isa_driver = {
65128800Sbde	cy_driver_name,
66127885Sbde	cy_isa_methods,
67127885Sbde	0,
68127885Sbde};
69127885Sbde
70127885SbdeDRIVER_MODULE(cy, isa, cy_isa_driver, cy_devclass, 0, 0);
71127885Sbde
729406Sbdestatic int
73127885Sbdecy_isa_probe(device_t dev)
749406Sbde{
75127885Sbde	struct resource *mem_res;
76127885Sbde	cy_addr iobase;
77165996Sbde	int error, mem_rid;
786261Sjkh
79127885Sbde	if (isa_get_logicalid(dev) != 0)	/* skip PnP probes */
80127885Sbde		return (ENXIO);
816261Sjkh
82127885Sbde	mem_rid = 0;
83127885Sbde	mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &mem_rid,
84127885Sbde	    0ul, ~0ul, 0ul, RF_ACTIVE);
85127885Sbde	if (mem_res == NULL) {
86127885Sbde		device_printf(dev, "ioport resource allocation failed\n");
87127885Sbde		return (ENXIO);
88127885Sbde	}
89127885Sbde	iobase = rman_get_virtual(mem_res);
90127885Sbde
919406Sbde	/* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */
9241309Sbde	cy_inb(iobase, CY16_RESET, 0);	/* XXX? */
93128804Sbde	DELAY(500);		/* wait for the board to get its act together */
946261Sjkh
9511424Sdg	/* this is needed to get the board out of reset */
9641309Sbde	cy_outb(iobase, CY_CLEAR_INTR, 0, 0);
9711424Sdg	DELAY(500);
9811424Sdg
99165996Sbde	error = (cy_units(iobase, 0) == 0 ? ENXIO : 0);
100127885Sbde	bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res);
101165996Sbde	return (error);
10218901Sdg}
10318901Sdg
10418901Sdgstatic int
105127885Sbdecy_isa_attach(device_t dev)
1066261Sjkh{
107127885Sbde	struct resource *irq_res, *mem_res;
108127885Sbde	void *irq_cookie, *vaddr, *vsc;
109127885Sbde	int irq_rid, mem_rid;
1106261Sjkh
111127885Sbde	irq_res = NULL;
112127885Sbde	mem_res = NULL;
11329047Sbde
114127885Sbde	mem_rid = 0;
115127885Sbde	mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &mem_rid,
116127885Sbde	    0ul, ~0ul, 0ul, RF_ACTIVE);
117127885Sbde	if (mem_res == NULL) {
118127885Sbde		device_printf(dev, "memory resource allocation failed\n");
119127885Sbde		goto fail;
12018901Sdg	}
121127885Sbde	vaddr = rman_get_virtual(mem_res);
122123104Sbde
123127885Sbde	vsc = cyattach_common(vaddr, 0);
124127885Sbde	if (vsc == NULL) {
125127885Sbde		device_printf(dev, "no ports found!\n");
126127885Sbde		goto fail;
127127885Sbde	}
128127885Sbde
129127885Sbde	irq_rid = 0;
130127885Sbde	irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, 0ul, ~0ul, 0ul,
131127885Sbde	    RF_SHAREABLE | RF_ACTIVE);
132127885Sbde	if (irq_res == NULL) {
133127885Sbde		device_printf(dev, "interrupt resource allocation failed\n");
134127885Sbde		goto fail;
135127885Sbde	}
136166901Spiso	if (bus_setup_intr(dev, irq_res, INTR_TYPE_TTY,
137166901Spiso	    cyintr, NULL, vsc, &irq_cookie) != 0) {
138127885Sbde		device_printf(dev, "interrupt setup failed\n");
139127885Sbde		goto fail;
140127885Sbde	}
141127885Sbde
142127885Sbde	return (0);
143127885Sbde
144127885Sbdefail:
145127885Sbde	if (irq_res != NULL)
146127885Sbde		bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res);
147127885Sbde	if (mem_res != NULL)
148127885Sbde		bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res);
149127885Sbde	return (ENXIO);
15018901Sdg}
151