ppb_base.c revision 55939
1166768Sbmah/*-
2166768Sbmah * Copyright (c) 1997, 1998, 1999 Nicolas Souchu
3166768Sbmah * All rights reserved.
4166768Sbmah *
5166768Sbmah * Redistribution and use in source and binary forms, with or without
6166768Sbmah * modification, are permitted provided that the following conditions
7166768Sbmah * are met:
8166768Sbmah * 1. Redistributions of source code must retain the above copyright
9166768Sbmah *    notice, this list of conditions and the following disclaimer.
10166768Sbmah * 2. Redistributions in binary form must reproduce the above copyright
11166768Sbmah *    notice, this list of conditions and the following disclaimer in the
12166768Sbmah *    documentation and/or other materials provided with the distribution.
13166768Sbmah *
14166768Sbmah * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15183626Ssimon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16183626Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17166768Sbmah * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18183626Ssimon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19166768Sbmah * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20183626Ssimon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21166768Sbmah * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22183626Ssimon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23183626Ssimon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24183626Ssimon * SUCH DAMAGE.
25183626Ssimon *
26183626Ssimon * $FreeBSD: head/sys/dev/ppbus/ppb_base.c 55939 2000-01-14 00:18:06Z nsouch $
27183626Ssimon *
28183626Ssimon */
29183626Ssimon#include <sys/param.h>
30183626Ssimon#include <sys/systm.h>
31183626Ssimon#include <sys/kernel.h>
32191511Sblackend#include <sys/module.h>
33183626Ssimon#include <sys/bus.h>
34183626Ssimon
35166771Sbmah#include <machine/clock.h>
36183626Ssimon
37183626Ssimon#include <dev/ppbus/ppbconf.h>
38183626Ssimon
39183626Ssimon#include "ppbus_if.h"
40183626Ssimon
41183626Ssimon#include <dev/ppbus/ppbio.h>
42183626Ssimon
43183626Ssimon#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev))
44183626Ssimon
45172094Sbmah/*
46183626Ssimon * ppb_poll_bus()
47172094Sbmah *
48183626Ssimon * Polls the bus
49183626Ssimon *
50166768Sbmah * max is a delay in 10-milliseconds
51183626Ssimon */
52183626Ssimonint
53183626Ssimonppb_poll_bus(device_t bus, int max,
54183626Ssimon	     char mask, char status, int how)
55183626Ssimon{
56183626Ssimon	int i, j, error;
57166768Sbmah	char r;
58183626Ssimon
59183626Ssimon	/* try at least up to 10ms */
60166768Sbmah	for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) {
61183626Ssimon		for (i = 0; i < 10000; i++) {
62183626Ssimon			r = ppb_rstr(bus);
63183626Ssimon			DELAY(1);
64166768Sbmah			if ((r & mask) == status)
65183626Ssimon				return (0);
66183626Ssimon		}
67166770Sbmah	}
68183626Ssimon
69183626Ssimon	if (!(how & PPB_POLL)) {
70183626Ssimon	   for (i = 0; max == PPB_FOREVER || i < max-1; i++) {
71183626Ssimon		if ((ppb_rstr(bus) & mask) == status)
72183626Ssimon			return (0);
73183626Ssimon
74166770Sbmah		switch (how) {
75183626Ssimon		case PPB_NOINTR:
76183626Ssimon			/* wait 10 ms */
77183626Ssimon			tsleep((caddr_t)bus, PPBPRI, "ppbpoll", hz/100);
78183626Ssimon			break;
79183626Ssimon
80166770Sbmah		case PPB_INTR:
81183626Ssimon		default:
82183626Ssimon			/* wait 10 ms */
83166770Sbmah			if (((error = tsleep((caddr_t)bus, PPBPRI | PCATCH,
84183626Ssimon			    "ppbpoll", hz/100)) != EWOULDBLOCK) != 0) {
85183626Ssimon				return (error);
86183626Ssimon			}
87183626Ssimon			break;
88166770Sbmah		}
89183626Ssimon	   }
90183626Ssimon	}
91183626Ssimon
92166770Sbmah	return (EWOULDBLOCK);
93183626Ssimon}
94186204Smurray
95186208Smurray/*
96183626Ssimon * ppb_get_epp_protocol()
97166770Sbmah *
98183626Ssimon * Return the chipset EPP protocol
99186204Smurray */
100186204Smurrayint
101186204Smurrayppb_get_epp_protocol(device_t bus)
102186204Smurray{
103183626Ssimon	uintptr_t protocol;
104186204Smurray
105186204Smurray	BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_EPP_PROTO, &protocol);
106186204Smurray
107186204Smurray	return (protocol);
108186204Smurray}
109186204Smurray
110186204Smurray/*
111186204Smurray * ppb_get_mode()
112186204Smurray *
113186204Smurray */
114186204Smurrayint
115186204Smurrayppb_get_mode(device_t bus)
116186204Smurray{
117186204Smurray	struct ppb_data *ppb = DEVTOSOFTC(bus);
118186204Smurray
119186204Smurray	/* XXX yet device mode = ppbus mode = chipset mode */
120186204Smurray	return (ppb->mode);
121186204Smurray}
122186204Smurray
123186204Smurray/*
124186204Smurray * ppb_set_mode()
125186204Smurray *
126186204Smurray * Set the operating mode of the chipset, return the previous mode
127186204Smurray */
128183626Ssimonint
129166770Sbmahppb_set_mode(device_t bus, int mode)
130183626Ssimon{
131183626Ssimon	struct ppb_data *ppb = DEVTOSOFTC(bus);
132183626Ssimon	int old_mode = ppb_get_mode(bus);
133183626Ssimon
134183626Ssimon	if (!PPBUS_SETMODE(device_get_parent(bus), mode)) {
135166770Sbmah		/* XXX yet device mode = ppbus mode = chipset mode */
136186242Smurray		ppb->mode = (mode & PPB_MASK);
137183626Ssimon	}
138183626Ssimon
139166770Sbmah	return (old_mode);
140183626Ssimon}
141183626Ssimon
142183626Ssimon/*
143183626Ssimon * ppb_write()
144183626Ssimon *
145166770Sbmah * Write charaters to the port
146183626Ssimon */
147183626Ssimonint
148183626Ssimonppb_write(device_t bus, char *buf, int len, int how)
149183626Ssimon{
150166770Sbmah	return (PPBUS_WRITE(device_get_parent(bus), buf, len, how));
151183626Ssimon}
152166770Sbmah
153183626Ssimon/*
154183626Ssimon * ppb_reset_epp_timeout()
155166770Sbmah *
156183626Ssimon * Reset the EPP timeout bit in the status register
157183626Ssimon */
158183626Ssimonint
159183626Ssimonppb_reset_epp_timeout(device_t bus)
160183626Ssimon{
161183626Ssimon	return(PPBUS_RESET_EPP(device_get_parent(bus)));
162166770Sbmah}
163183626Ssimon
164183626Ssimon/*
165183626Ssimon * ppb_ecp_sync()
166183626Ssimon *
167183626Ssimon * Wait for the ECP FIFO to be empty
168183626Ssimon */
169183626Ssimonint
170183626Ssimonppb_ecp_sync(device_t bus)
171183626Ssimon{
172183626Ssimon	return (PPBUS_ECP_SYNC(device_get_parent(bus)));
173183626Ssimon}
174183626Ssimon
175166770Sbmah/*
176183626Ssimon * ppb_get_status()
177183626Ssimon *
178183626Ssimon * Read the status register and update the status info
179183626Ssimon */
180183626Ssimonint
181166770Sbmahppb_get_status(device_t bus, struct ppb_status *status)
182183626Ssimon{
183183626Ssimon	register char r;
184183626Ssimon
185183626Ssimon	r = status->status = ppb_rstr(bus);
186166770Sbmah
187183626Ssimon	status->timeout	= r & TIMEOUT;
188183626Ssimon	status->error	= !(r & nFAULT);
189183626Ssimon	status->select	= r & SELECT;
190183626Ssimon	status->paper_end = r & PERROR;
191183626Ssimon	status->ack	= !(r & nACK);
192183626Ssimon	status->busy	= !(r & nBUSY);
193183626Ssimon
194183626Ssimon	return (0);
195183626Ssimon}
196183626Ssimon