1 /*- 2 * Copyright (c) 1997, 1998 Nicolas Souchu 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 * 28 */ 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/kernel.h> 32 #include <machine/clock.h> 33 34 #include <dev/ppbus/ppbconf.h> 35 36 /* 37 * ppb_intr() 38 * 39 * Function called by ppcintr() when an intr occurs. 40 */ 41 void 42 ppb_intr(struct ppb_link *pl) 43 { 44 struct ppb_data *ppb = pl->ppbus; 45 46 /* 47 * Call chipset dependent code. 48 * Should be filled at chipset initialisation if needed. 49 */ 50 if (pl->adapter->intr_handler) 51 (*pl->adapter->intr_handler)(pl->adapter_unit); 52 53 /* 54 * Call upper handler iff the bus is owned by a device and 55 * this device has specified an interrupt handler. 56 */ 57 if (ppb->ppb_owner && ppb->ppb_owner->intr) 58 (*ppb->ppb_owner->intr)(ppb->ppb_owner->id_unit); 59 if (ppb->ppb_owner && ppb->ppb_owner->bintr) 60 (*ppb->ppb_owner->bintr)(ppb->ppb_owner); 61 62 return; 63 } 64 65 /* 66 * ppb_poll_device() 67 * 68 * Polls the device 69 * 70 * max is a delay in 10-milliseconds 71 */ 72 int 73 ppb_poll_device(struct ppb_device *dev, int max, 74 char mask, char status, int how) 75 { 76 int i, j, error; 77 char r; 78 79 /* try at least up to 10ms */ 80 for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) { 81 for (i = 0; i < 10000; i++) { 82 r = ppb_rstr(dev); 83 DELAY(1); 84 if ((r & mask) == status) 85 return (0); 86 } 87 } 88 89 if (!(how & PPB_POLL)) { 90 for (i = 0; max == PPB_FOREVER || i < max-1; i++) { 91 if ((ppb_rstr(dev) & mask) == status) 92 return (0); 93 94 switch (how) { 95 case PPB_NOINTR: 96 /* wait 10 ms */ 97 tsleep((caddr_t)dev, PPBPRI, "ppbpoll", hz/100); 98 break; 99 100 case PPB_INTR: 101 default: 102 /* wait 10 ms */ 103 if (((error = tsleep((caddr_t)dev, PPBPRI | PCATCH, 104 "ppbpoll", hz/100)) != EWOULDBLOCK) != 0) { 105 return (error); 106 } 107 break; 108 } 109 } 110 } 111 112 return (EWOULDBLOCK); 113 } 114 115 /* 116 * ppb_set_mode() 117 * 118 * Set the operating mode of the chipset 119 */ 120 int 121 ppb_set_mode(struct ppb_device *dev, int mode) 122 { 123 struct ppb_data *ppb = dev->ppb; 124 int old_mode = ppb_get_mode(dev); 125 126 if ((*ppb->ppb_link->adapter->setmode)( 127 ppb->ppb_link->adapter_unit, mode)) 128 return (-1); 129 130 /* XXX yet device mode = ppbus mode = chipset mode */ 131 dev->mode = ppb->mode = (mode & PPB_MASK); 132 133 return (old_mode); 134 } 135 136 /* 137 * ppb_write() 138 * 139 * Write charaters to the port 140 */ 141 int 142 ppb_write(struct ppb_device *dev, char *buf, int len, int how) 143 { 144 struct ppb_data *ppb = dev->ppb; 145 146 return (ppb->ppb_link->adapter->write(ppb->ppb_link->adapter_unit, 147 buf, len, how)); 148 } 149 150 /* 151 * ppb_reset_epp_timeout() 152 * 153 * Reset the EPP timeout bit in the status register 154 */ 155 int 156 ppb_reset_epp_timeout(struct ppb_device *dev) 157 { 158 struct ppb_data *ppb = dev->ppb; 159 160 if (ppb->ppb_owner != dev) 161 return (EACCES); 162 163 (*ppb->ppb_link->adapter->reset_epp_timeout)(ppb->ppb_link->adapter_unit); 164 165 return (0); 166 } 167 168 /* 169 * ppb_ecp_sync() 170 * 171 * Wait for the ECP FIFO to be empty 172 */ 173 int 174 ppb_ecp_sync(struct ppb_device *dev) 175 { 176 struct ppb_data *ppb = dev->ppb; 177 178 if (ppb->ppb_owner != dev) 179 return (EACCES); 180 181 (*ppb->ppb_link->adapter->ecp_sync)(ppb->ppb_link->adapter_unit); 182 183 return (0); 184 } 185 186 /* 187 * ppb_get_status() 188 * 189 * Read the status register and update the status info 190 */ 191 int 192 ppb_get_status(struct ppb_device *dev, struct ppb_status *status) 193 { 194 struct ppb_data *ppb = dev->ppb; 195 register char r; 196 197 if (ppb->ppb_owner != dev) 198 return (EACCES); 199 200 r = status->status = ppb_rstr(dev); 201 202 status->timeout = r & TIMEOUT; 203 status->error = !(r & nFAULT); 204 status->select = r & SELECT; 205 status->paper_end = r & PERROR; 206 status->ack = !(r & nACK); 207 status->busy = !(r & nBUSY); 208 209 return (0); 210 } 211