ppb_base.c revision 63458
128257Smsmith/*-
255939Snsouch * Copyright (c) 1997, 1998, 1999 Nicolas Souchu
328257Smsmith * All rights reserved.
428257Smsmith *
528257Smsmith * Redistribution and use in source and binary forms, with or without
628257Smsmith * modification, are permitted provided that the following conditions
728257Smsmith * are met:
828257Smsmith * 1. Redistributions of source code must retain the above copyright
928257Smsmith *    notice, this list of conditions and the following disclaimer.
1028257Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1128257Smsmith *    notice, this list of conditions and the following disclaimer in the
1228257Smsmith *    documentation and/or other materials provided with the distribution.
1328257Smsmith *
1428257Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1528257Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1628257Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1728257Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1828257Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1928257Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2028257Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2128257Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2228257Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2328257Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2428257Smsmith * SUCH DAMAGE.
2528257Smsmith *
2650477Speter * $FreeBSD: head/sys/dev/ppbus/ppb_base.c 63458 2000-07-18 20:16:16Z n_hibma $
2728257Smsmith *
2828257Smsmith */
2928257Smsmith#include <sys/param.h>
3028257Smsmith#include <sys/systm.h>
3128257Smsmith#include <sys/kernel.h>
3255939Snsouch#include <sys/module.h>
3355939Snsouch#include <sys/bus.h>
3455939Snsouch
3542475Snsouch#include <machine/clock.h>
3628257Smsmith
3728257Smsmith#include <dev/ppbus/ppbconf.h>
3855939Snsouch
3955939Snsouch#include "ppbus_if.h"
4028257Smsmith
4155939Snsouch#include <dev/ppbus/ppbio.h>
4255939Snsouch
4355939Snsouch#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev))
4455939Snsouch
4528257Smsmith/*
4655939Snsouch * ppb_poll_bus()
4728257Smsmith *
4855939Snsouch * Polls the bus
4928257Smsmith *
5028257Smsmith * max is a delay in 10-milliseconds
5128257Smsmith */
5228257Smsmithint
5355939Snsouchppb_poll_bus(device_t bus, int max,
5455939Snsouch	     char mask, char status, int how)
5528257Smsmith{
5642475Snsouch	int i, j, error;
5742475Snsouch	char r;
5828257Smsmith
5942475Snsouch	/* try at least up to 10ms */
6042475Snsouch	for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) {
6142475Snsouch		for (i = 0; i < 10000; i++) {
6255939Snsouch			r = ppb_rstr(bus);
6342475Snsouch			DELAY(1);
6442475Snsouch			if ((r & mask) == status)
6542475Snsouch				return (0);
6642475Snsouch		}
6742475Snsouch	}
6842475Snsouch
6942475Snsouch	if (!(how & PPB_POLL)) {
7042475Snsouch	   for (i = 0; max == PPB_FOREVER || i < max-1; i++) {
7155939Snsouch		if ((ppb_rstr(bus) & mask) == status)
7228257Smsmith			return (0);
7328257Smsmith
7428257Smsmith		switch (how) {
7528257Smsmith		case PPB_NOINTR:
7628257Smsmith			/* wait 10 ms */
7755939Snsouch			tsleep((caddr_t)bus, PPBPRI, "ppbpoll", hz/100);
7828257Smsmith			break;
7928257Smsmith
8028257Smsmith		case PPB_INTR:
8128257Smsmith		default:
8228257Smsmith			/* wait 10 ms */
8355939Snsouch			if (((error = tsleep((caddr_t)bus, PPBPRI | PCATCH,
8443295Sdillon			    "ppbpoll", hz/100)) != EWOULDBLOCK) != 0) {
8528257Smsmith				return (error);
8643295Sdillon			}
8728257Smsmith			break;
8828257Smsmith		}
8942475Snsouch	   }
9028257Smsmith	}
9128257Smsmith
9228257Smsmith	return (EWOULDBLOCK);
9328257Smsmith}
9428257Smsmith
9528257Smsmith/*
9655939Snsouch * ppb_get_epp_protocol()
9738061Smsmith *
9855939Snsouch * Return the chipset EPP protocol
9938061Smsmith */
10038061Smsmithint
10155939Snsouchppb_get_epp_protocol(device_t bus)
10238061Smsmith{
10355939Snsouch	uintptr_t protocol;
10438061Smsmith
10555939Snsouch	BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_EPP_PROTO, &protocol);
10638061Smsmith
10755939Snsouch	return (protocol);
10855939Snsouch}
10955939Snsouch
11055939Snsouch/*
11155939Snsouch * ppb_get_mode()
11255939Snsouch *
11355939Snsouch */
11455939Snsouchint
11555939Snsouchppb_get_mode(device_t bus)
11655939Snsouch{
11755939Snsouch	struct ppb_data *ppb = DEVTOSOFTC(bus);
11855939Snsouch
11938061Smsmith	/* XXX yet device mode = ppbus mode = chipset mode */
12055939Snsouch	return (ppb->mode);
12155939Snsouch}
12238061Smsmith
12355939Snsouch/*
12455939Snsouch * ppb_set_mode()
12555939Snsouch *
12655939Snsouch * Set the operating mode of the chipset, return the previous mode
12755939Snsouch */
12855939Snsouchint
12955939Snsouchppb_set_mode(device_t bus, int mode)
13055939Snsouch{
13155939Snsouch	struct ppb_data *ppb = DEVTOSOFTC(bus);
13255939Snsouch	int old_mode = ppb_get_mode(bus);
13355939Snsouch
13463458Sn_hibma	if (PPBUS_SETMODE(device_get_parent(bus), mode))
13563458Sn_hibma		return -1;
13655939Snsouch
13763458Sn_hibma	/* XXX yet device mode = ppbus mode = chipset mode */
13863458Sn_hibma	ppb->mode = (mode & PPB_MASK);
13963458Sn_hibma
14038061Smsmith	return (old_mode);
14138061Smsmith}
14238061Smsmith
14338061Smsmith/*
14442475Snsouch * ppb_write()
14542475Snsouch *
14642475Snsouch * Write charaters to the port
14742475Snsouch */
14842475Snsouchint
14955939Snsouchppb_write(device_t bus, char *buf, int len, int how)
15042475Snsouch{
15155939Snsouch	return (PPBUS_WRITE(device_get_parent(bus), buf, len, how));
15242475Snsouch}
15342475Snsouch
15442475Snsouch/*
15528257Smsmith * ppb_reset_epp_timeout()
15628257Smsmith *
15738061Smsmith * Reset the EPP timeout bit in the status register
15828257Smsmith */
15928257Smsmithint
16055939Snsouchppb_reset_epp_timeout(device_t bus)
16128257Smsmith{
16255939Snsouch	return(PPBUS_RESET_EPP(device_get_parent(bus)));
16328257Smsmith}
16428257Smsmith
16528257Smsmith/*
16628257Smsmith * ppb_ecp_sync()
16728257Smsmith *
16838061Smsmith * Wait for the ECP FIFO to be empty
16928257Smsmith */
17028257Smsmithint
17155939Snsouchppb_ecp_sync(device_t bus)
17228257Smsmith{
17355939Snsouch	return (PPBUS_ECP_SYNC(device_get_parent(bus)));
17428257Smsmith}
17528257Smsmith
17628257Smsmith/*
17728257Smsmith * ppb_get_status()
17828257Smsmith *
17938061Smsmith * Read the status register and update the status info
18028257Smsmith */
18128257Smsmithint
18255939Snsouchppb_get_status(device_t bus, struct ppb_status *status)
18328257Smsmith{
18428257Smsmith	register char r;
18528257Smsmith
18655939Snsouch	r = status->status = ppb_rstr(bus);
18728257Smsmith
18828257Smsmith	status->timeout	= r & TIMEOUT;
18928257Smsmith	status->error	= !(r & nFAULT);
19028257Smsmith	status->select	= r & SELECT;
19139134Snsouch	status->paper_end = r & PERROR;
19228257Smsmith	status->ack	= !(r & nACK);
19328257Smsmith	status->busy	= !(r & nBUSY);
19428257Smsmith
19528257Smsmith	return (0);
19628257Smsmith}
197