ppb_base.c revision 330897
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1997, 1998, 1999 Nicolas Souchu 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: stable/11/sys/dev/ppbus/ppb_base.c 330897 2018-03-14 03:19:51Z eadler $"); 31 32#include <sys/param.h> 33#include <sys/lock.h> 34#include <sys/kernel.h> 35#include <sys/module.h> 36#include <sys/mutex.h> 37#include <sys/systm.h> 38#include <sys/bus.h> 39 40#include <dev/ppbus/ppbconf.h> 41 42#include "ppbus_if.h" 43 44#include <dev/ppbus/ppbio.h> 45 46MODULE_VERSION(ppbus, 1); 47 48#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev)) 49 50/* 51 * ppb_poll_bus() 52 * 53 * Polls the bus 54 * 55 * max is a delay in 10-milliseconds 56 */ 57int 58ppb_poll_bus(device_t bus, int max, 59 uint8_t mask, uint8_t status, int how) 60{ 61 struct ppb_data *ppb = DEVTOSOFTC(bus); 62 int i, j, error; 63 uint8_t r; 64 65 ppb_assert_locked(bus); 66 67 /* try at least up to 10ms */ 68 for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) { 69 for (i = 0; i < 10000; i++) { 70 r = ppb_rstr(bus); 71 DELAY(1); 72 if ((r & mask) == status) 73 return (0); 74 } 75 } 76 77 if (!(how & PPB_POLL)) { 78 for (i = 0; max == PPB_FOREVER || i < max-1; i++) { 79 if ((ppb_rstr(bus) & mask) == status) 80 return (0); 81 82 /* wait 10 ms */ 83 error = mtx_sleep((caddr_t)bus, ppb->ppc_lock, PPBPRI | 84 (how == PPB_NOINTR ? 0 : PCATCH), "ppbpoll", hz/100); 85 if (error != EWOULDBLOCK) 86 return (error); 87 } 88 } 89 90 return (EWOULDBLOCK); 91} 92 93/* 94 * ppb_get_epp_protocol() 95 * 96 * Return the chipset EPP protocol 97 */ 98int 99ppb_get_epp_protocol(device_t bus) 100{ 101 uintptr_t protocol; 102 103 ppb_assert_locked(bus); 104 BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_EPP_PROTO, &protocol); 105 106 return (protocol); 107} 108 109/* 110 * ppb_get_mode() 111 * 112 */ 113int 114ppb_get_mode(device_t bus) 115{ 116 struct ppb_data *ppb = DEVTOSOFTC(bus); 117 118 /* XXX yet device mode = ppbus mode = chipset mode */ 119 ppb_assert_locked(bus); 120 return (ppb->mode); 121} 122 123/* 124 * ppb_set_mode() 125 * 126 * Set the operating mode of the chipset, return the previous mode 127 */ 128int 129ppb_set_mode(device_t bus, int mode) 130{ 131 struct ppb_data *ppb = DEVTOSOFTC(bus); 132 int old_mode = ppb_get_mode(bus); 133 134 ppb_assert_locked(bus); 135 if (PPBUS_SETMODE(device_get_parent(bus), mode)) 136 return (-1); 137 138 /* XXX yet device mode = ppbus mode = chipset mode */ 139 ppb->mode = (mode & PPB_MASK); 140 141 return (old_mode); 142} 143 144/* 145 * ppb_write() 146 * 147 * Write charaters to the port 148 */ 149int 150ppb_write(device_t bus, char *buf, int len, int how) 151{ 152 153 ppb_assert_locked(bus); 154 return (PPBUS_WRITE(device_get_parent(bus), buf, len, how)); 155} 156 157/* 158 * ppb_reset_epp_timeout() 159 * 160 * Reset the EPP timeout bit in the status register 161 */ 162int 163ppb_reset_epp_timeout(device_t bus) 164{ 165 166 ppb_assert_locked(bus); 167 return(PPBUS_RESET_EPP(device_get_parent(bus))); 168} 169 170/* 171 * ppb_ecp_sync() 172 * 173 * Wait for the ECP FIFO to be empty 174 */ 175int 176ppb_ecp_sync(device_t bus) 177{ 178 179 ppb_assert_locked(bus); 180 return (PPBUS_ECP_SYNC(device_get_parent(bus))); 181} 182 183/* 184 * ppb_get_status() 185 * 186 * Read the status register and update the status info 187 */ 188int 189ppb_get_status(device_t bus, struct ppb_status *status) 190{ 191 uint8_t r; 192 193 ppb_assert_locked(bus); 194 195 r = status->status = ppb_rstr(bus); 196 197 status->timeout = r & TIMEOUT; 198 status->error = !(r & nFAULT); 199 status->select = r & SELECT; 200 status->paper_end = r & PERROR; 201 status->ack = !(r & nACK); 202 status->busy = !(r & nBUSY); 203 204 return (0); 205} 206 207void 208ppb_lock(device_t bus) 209{ 210 struct ppb_data *ppb = DEVTOSOFTC(bus); 211 212 mtx_lock(ppb->ppc_lock); 213} 214 215void 216ppb_unlock(device_t bus) 217{ 218 struct ppb_data *ppb = DEVTOSOFTC(bus); 219 220 mtx_unlock(ppb->ppc_lock); 221} 222 223void 224_ppb_assert_locked(device_t bus, const char *file, int line) 225{ 226 227 mtx_assert_(DEVTOSOFTC(bus)->ppc_lock, MA_OWNED, file, line); 228} 229 230void 231ppb_init_callout(device_t bus, struct callout *c, int flags) 232{ 233 struct ppb_data *ppb = DEVTOSOFTC(bus); 234 235 callout_init_mtx(c, ppb->ppc_lock, flags); 236} 237 238int 239ppb_sleep(device_t bus, void *wchan, int priority, const char *wmesg, int timo) 240{ 241 struct ppb_data *ppb = DEVTOSOFTC(bus); 242 243 return (mtx_sleep(wchan, ppb->ppc_lock, priority, wmesg, timo)); 244} 245