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 */ 26119418Sobrien 27119418Sobrien#include <sys/cdefs.h> 28119418Sobrien__FBSDID("$FreeBSD$"); 29119418Sobrien 3028257Smsmith#include <sys/param.h> 31187576Sjhb#include <sys/lock.h> 3228257Smsmith#include <sys/kernel.h> 3355939Snsouch#include <sys/module.h> 34187576Sjhb#include <sys/mutex.h> 35187576Sjhb#include <sys/systm.h> 3655939Snsouch#include <sys/bus.h> 3755939Snsouch 3828257Smsmith#include <dev/ppbus/ppbconf.h> 39185003Sjhb 4055939Snsouch#include "ppbus_if.h" 4128257Smsmith 4255939Snsouch#include <dev/ppbus/ppbio.h> 43185003Sjhb 44119284SimpMODULE_VERSION(ppbus, 1); 45119284Simp 4655939Snsouch#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev)) 47185003Sjhb 4828257Smsmith/* 4955939Snsouch * ppb_poll_bus() 5028257Smsmith * 5155939Snsouch * Polls the bus 5228257Smsmith * 5328257Smsmith * max is a delay in 10-milliseconds 5428257Smsmith */ 5528257Smsmithint 5655939Snsouchppb_poll_bus(device_t bus, int max, 57305555Sdim uint8_t mask, uint8_t status, int how) 5828257Smsmith{ 59187576Sjhb struct ppb_data *ppb = DEVTOSOFTC(bus); 6042475Snsouch int i, j, error; 61305555Sdim uint8_t r; 6228257Smsmith 63227814Sattilio ppb_assert_locked(bus); 64187576Sjhb 6542475Snsouch /* try at least up to 10ms */ 6642475Snsouch for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) { 6742475Snsouch for (i = 0; i < 10000; i++) { 6855939Snsouch r = ppb_rstr(bus); 6942475Snsouch DELAY(1); 7042475Snsouch if ((r & mask) == status) 7142475Snsouch return (0); 7242475Snsouch } 7342475Snsouch } 7442475Snsouch 7542475Snsouch if (!(how & PPB_POLL)) { 7642475Snsouch for (i = 0; max == PPB_FOREVER || i < max-1; i++) { 7755939Snsouch if ((ppb_rstr(bus) & mask) == status) 7828257Smsmith return (0); 7928257Smsmith 80187576Sjhb /* wait 10 ms */ 81187576Sjhb error = mtx_sleep((caddr_t)bus, ppb->ppc_lock, PPBPRI | 82187576Sjhb (how == PPB_NOINTR ? 0 : PCATCH), "ppbpoll", hz/100); 83187576Sjhb if (error != EWOULDBLOCK) 84187576Sjhb return (error); 8542475Snsouch } 8628257Smsmith } 8728257Smsmith 8828257Smsmith return (EWOULDBLOCK); 8928257Smsmith} 9028257Smsmith 9128257Smsmith/* 9255939Snsouch * ppb_get_epp_protocol() 9338061Smsmith * 9455939Snsouch * Return the chipset EPP protocol 9538061Smsmith */ 9638061Smsmithint 9755939Snsouchppb_get_epp_protocol(device_t bus) 9838061Smsmith{ 9955939Snsouch uintptr_t protocol; 10038061Smsmith 101227814Sattilio ppb_assert_locked(bus); 10255939Snsouch BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_EPP_PROTO, &protocol); 10338061Smsmith 10455939Snsouch return (protocol); 10555939Snsouch} 10655939Snsouch 10755939Snsouch/* 10855939Snsouch * ppb_get_mode() 10955939Snsouch * 11055939Snsouch */ 11155939Snsouchint 11255939Snsouchppb_get_mode(device_t bus) 11355939Snsouch{ 11455939Snsouch struct ppb_data *ppb = DEVTOSOFTC(bus); 11555939Snsouch 11638061Smsmith /* XXX yet device mode = ppbus mode = chipset mode */ 117227814Sattilio ppb_assert_locked(bus); 11855939Snsouch return (ppb->mode); 11955939Snsouch} 12038061Smsmith 12155939Snsouch/* 12255939Snsouch * ppb_set_mode() 12355939Snsouch * 12455939Snsouch * Set the operating mode of the chipset, return the previous mode 12555939Snsouch */ 12655939Snsouchint 12755939Snsouchppb_set_mode(device_t bus, int mode) 12855939Snsouch{ 12955939Snsouch struct ppb_data *ppb = DEVTOSOFTC(bus); 13055939Snsouch int old_mode = ppb_get_mode(bus); 13155939Snsouch 132227814Sattilio ppb_assert_locked(bus); 13363458Sn_hibma if (PPBUS_SETMODE(device_get_parent(bus), mode)) 134185003Sjhb return (-1); 13555939Snsouch 13663458Sn_hibma /* XXX yet device mode = ppbus mode = chipset mode */ 13763458Sn_hibma ppb->mode = (mode & PPB_MASK); 13863458Sn_hibma 13938061Smsmith return (old_mode); 14038061Smsmith} 14138061Smsmith 14238061Smsmith/* 14342475Snsouch * ppb_write() 14442475Snsouch * 14542475Snsouch * Write charaters to the port 14642475Snsouch */ 14742475Snsouchint 14855939Snsouchppb_write(device_t bus, char *buf, int len, int how) 14942475Snsouch{ 150187576Sjhb 151227814Sattilio ppb_assert_locked(bus); 15255939Snsouch return (PPBUS_WRITE(device_get_parent(bus), buf, len, how)); 15342475Snsouch} 15442475Snsouch 15542475Snsouch/* 15628257Smsmith * ppb_reset_epp_timeout() 15728257Smsmith * 15838061Smsmith * Reset the EPP timeout bit in the status register 15928257Smsmith */ 16028257Smsmithint 16155939Snsouchppb_reset_epp_timeout(device_t bus) 16228257Smsmith{ 163187576Sjhb 164227814Sattilio ppb_assert_locked(bus); 16555939Snsouch return(PPBUS_RESET_EPP(device_get_parent(bus))); 16628257Smsmith} 16728257Smsmith 16828257Smsmith/* 16928257Smsmith * ppb_ecp_sync() 17028257Smsmith * 17138061Smsmith * Wait for the ECP FIFO to be empty 17228257Smsmith */ 17328257Smsmithint 17455939Snsouchppb_ecp_sync(device_t bus) 17528257Smsmith{ 176187576Sjhb 177227814Sattilio ppb_assert_locked(bus); 17855939Snsouch return (PPBUS_ECP_SYNC(device_get_parent(bus))); 17928257Smsmith} 18028257Smsmith 18128257Smsmith/* 18228257Smsmith * ppb_get_status() 18328257Smsmith * 18438061Smsmith * Read the status register and update the status info 18528257Smsmith */ 18628257Smsmithint 18755939Snsouchppb_get_status(device_t bus, struct ppb_status *status) 18828257Smsmith{ 189305555Sdim uint8_t r; 19028257Smsmith 191227814Sattilio ppb_assert_locked(bus); 192187576Sjhb 19355939Snsouch r = status->status = ppb_rstr(bus); 19428257Smsmith 19528257Smsmith status->timeout = r & TIMEOUT; 19628257Smsmith status->error = !(r & nFAULT); 19728257Smsmith status->select = r & SELECT; 19839134Snsouch status->paper_end = r & PERROR; 19928257Smsmith status->ack = !(r & nACK); 20028257Smsmith status->busy = !(r & nBUSY); 20128257Smsmith 20228257Smsmith return (0); 20328257Smsmith} 204187576Sjhb 205187576Sjhbvoid 206187576Sjhbppb_lock(device_t bus) 207187576Sjhb{ 208187576Sjhb struct ppb_data *ppb = DEVTOSOFTC(bus); 209187576Sjhb 210187576Sjhb mtx_lock(ppb->ppc_lock); 211187576Sjhb} 212187576Sjhb 213187576Sjhbvoid 214187576Sjhbppb_unlock(device_t bus) 215187576Sjhb{ 216187576Sjhb struct ppb_data *ppb = DEVTOSOFTC(bus); 217187576Sjhb 218187576Sjhb mtx_unlock(ppb->ppc_lock); 219187576Sjhb} 220187576Sjhb 221187576Sjhbvoid 222187576Sjhb_ppb_assert_locked(device_t bus, const char *file, int line) 223187576Sjhb{ 224187576Sjhb 225227758Sattilio mtx_assert_(DEVTOSOFTC(bus)->ppc_lock, MA_OWNED, file, line); 226187576Sjhb} 227187576Sjhb 228187576Sjhbvoid 229187576Sjhbppb_init_callout(device_t bus, struct callout *c, int flags) 230187576Sjhb{ 231187576Sjhb struct ppb_data *ppb = DEVTOSOFTC(bus); 232187576Sjhb 233187576Sjhb callout_init_mtx(c, ppb->ppc_lock, flags); 234187576Sjhb} 235187576Sjhb 236187576Sjhbint 237187576Sjhbppb_sleep(device_t bus, void *wchan, int priority, const char *wmesg, int timo) 238187576Sjhb{ 239187576Sjhb struct ppb_data *ppb = DEVTOSOFTC(bus); 240187576Sjhb 241187576Sjhb return (mtx_sleep(wchan, ppb->ppc_lock, priority, wmesg, timo)); 242187576Sjhb} 243