ia64/linux-2.6.18-xen.hg

annotate drivers/char/rio/riointr.c @ 893:f994bfe9b93b

linux/blktap2: reduce TLB flush scope

c/s 885 added very coarse TLB flushing. Since these flushes always
follow single page updates, single page flushes (when available) are
sufficient.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jun 04 10:32:57 2009 +0100 (2009-06-04)
parents 831230e53067
children
rev   line source
ian@0 1 /*
ian@0 2 ** -----------------------------------------------------------------------------
ian@0 3 **
ian@0 4 ** Perle Specialix driver for Linux
ian@0 5 ** Ported from existing RIO Driver for SCO sources.
ian@0 6 *
ian@0 7 * (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
ian@0 8 *
ian@0 9 * This program is free software; you can redistribute it and/or modify
ian@0 10 * it under the terms of the GNU General Public License as published by
ian@0 11 * the Free Software Foundation; either version 2 of the License, or
ian@0 12 * (at your option) any later version.
ian@0 13 *
ian@0 14 * This program is distributed in the hope that it will be useful,
ian@0 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ian@0 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ian@0 17 * GNU General Public License for more details.
ian@0 18 *
ian@0 19 * You should have received a copy of the GNU General Public License
ian@0 20 * along with this program; if not, write to the Free Software
ian@0 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
ian@0 22 **
ian@0 23 ** Module : riointr.c
ian@0 24 ** SID : 1.2
ian@0 25 ** Last Modified : 11/6/98 10:33:44
ian@0 26 ** Retrieved : 11/6/98 10:33:49
ian@0 27 **
ian@0 28 ** ident @(#)riointr.c 1.2
ian@0 29 **
ian@0 30 ** -----------------------------------------------------------------------------
ian@0 31 */
ian@0 32 #ifdef SCCS_LABELS
ian@0 33 static char *_riointr_c_sccs_ = "@(#)riointr.c 1.2";
ian@0 34 #endif
ian@0 35
ian@0 36
ian@0 37 #include <linux/module.h>
ian@0 38 #include <linux/slab.h>
ian@0 39 #include <linux/errno.h>
ian@0 40 #include <linux/tty.h>
ian@0 41 #include <linux/tty_flip.h>
ian@0 42 #include <asm/io.h>
ian@0 43 #include <asm/system.h>
ian@0 44 #include <asm/string.h>
ian@0 45 #include <asm/semaphore.h>
ian@0 46 #include <asm/uaccess.h>
ian@0 47
ian@0 48 #include <linux/termios.h>
ian@0 49 #include <linux/serial.h>
ian@0 50
ian@0 51 #include <linux/generic_serial.h>
ian@0 52
ian@0 53 #include <linux/delay.h>
ian@0 54
ian@0 55 #include "linux_compat.h"
ian@0 56 #include "rio_linux.h"
ian@0 57 #include "pkt.h"
ian@0 58 #include "daemon.h"
ian@0 59 #include "rio.h"
ian@0 60 #include "riospace.h"
ian@0 61 #include "cmdpkt.h"
ian@0 62 #include "map.h"
ian@0 63 #include "rup.h"
ian@0 64 #include "port.h"
ian@0 65 #include "riodrvr.h"
ian@0 66 #include "rioinfo.h"
ian@0 67 #include "func.h"
ian@0 68 #include "errors.h"
ian@0 69 #include "pci.h"
ian@0 70
ian@0 71 #include "parmmap.h"
ian@0 72 #include "unixrup.h"
ian@0 73 #include "board.h"
ian@0 74 #include "host.h"
ian@0 75 #include "phb.h"
ian@0 76 #include "link.h"
ian@0 77 #include "cmdblk.h"
ian@0 78 #include "route.h"
ian@0 79 #include "cirrus.h"
ian@0 80 #include "rioioctl.h"
ian@0 81
ian@0 82
ian@0 83 static void RIOReceive(struct rio_info *, struct Port *);
ian@0 84
ian@0 85
ian@0 86 static char *firstchars(char *p, int nch)
ian@0 87 {
ian@0 88 static char buf[2][128];
ian@0 89 static int t = 0;
ian@0 90 t = !t;
ian@0 91 memcpy(buf[t], p, nch);
ian@0 92 buf[t][nch] = 0;
ian@0 93 return buf[t];
ian@0 94 }
ian@0 95
ian@0 96
ian@0 97 #define INCR( P, I ) ((P) = (((P)+(I)) & p->RIOBufferMask))
ian@0 98 /* Enable and start the transmission of packets */
ian@0 99 void RIOTxEnable(char *en)
ian@0 100 {
ian@0 101 struct Port *PortP;
ian@0 102 struct rio_info *p;
ian@0 103 struct tty_struct *tty;
ian@0 104 int c;
ian@0 105 struct PKT __iomem *PacketP;
ian@0 106 unsigned long flags;
ian@0 107
ian@0 108 PortP = (struct Port *) en;
ian@0 109 p = (struct rio_info *) PortP->p;
ian@0 110 tty = PortP->gs.tty;
ian@0 111
ian@0 112
ian@0 113 rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt);
ian@0 114
ian@0 115 if (!PortP->gs.xmit_cnt)
ian@0 116 return;
ian@0 117
ian@0 118
ian@0 119 /* This routine is an order of magnitude simpler than the specialix
ian@0 120 version. One of the disadvantages is that this version will send
ian@0 121 an incomplete packet (usually 64 bytes instead of 72) once for
ian@0 122 every 4k worth of data. Let's just say that this won't influence
ian@0 123 performance significantly..... */
ian@0 124
ian@0 125 rio_spin_lock_irqsave(&PortP->portSem, flags);
ian@0 126
ian@0 127 while (can_add_transmit(&PacketP, PortP)) {
ian@0 128 c = PortP->gs.xmit_cnt;
ian@0 129 if (c > PKT_MAX_DATA_LEN)
ian@0 130 c = PKT_MAX_DATA_LEN;
ian@0 131
ian@0 132 /* Don't copy past the end of the source buffer */
ian@0 133 if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
ian@0 134 c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
ian@0 135
ian@0 136 {
ian@0 137 int t;
ian@0 138 t = (c > 10) ? 10 : c;
ian@0 139
ian@0 140 rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t));
ian@0 141 }
ian@0 142 /* If for one reason or another, we can't copy more data,
ian@0 143 we're done! */
ian@0 144 if (c == 0)
ian@0 145 break;
ian@0 146
ian@0 147 rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
ian@0 148 /* udelay (1); */
ian@0 149
ian@0 150 writeb(c, &(PacketP->len));
ian@0 151 if (!(PortP->State & RIO_DELETED)) {
ian@0 152 add_transmit(PortP);
ian@0 153 /*
ian@0 154 ** Count chars tx'd for port statistics reporting
ian@0 155 */
ian@0 156 if (PortP->statsGather)
ian@0 157 PortP->txchars += c;
ian@0 158 }
ian@0 159 PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1);
ian@0 160 PortP->gs.xmit_cnt -= c;
ian@0 161 }
ian@0 162
ian@0 163 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
ian@0 164
ian@0 165 if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN)) {
ian@0 166 rio_dprintk(RIO_DEBUG_INTR, "Waking up.... ldisc:%d (%d/%d)....", (int) (PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)), PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
ian@0 167 if ((PortP->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && PortP->gs.tty->ldisc.write_wakeup)
ian@0 168 (PortP->gs.tty->ldisc.write_wakeup) (PortP->gs.tty);
ian@0 169 rio_dprintk(RIO_DEBUG_INTR, "(%d/%d)\n", PortP->gs.wakeup_chars, PortP->gs.xmit_cnt);
ian@0 170 wake_up_interruptible(&PortP->gs.tty->write_wait);
ian@0 171 }
ian@0 172
ian@0 173 }
ian@0 174
ian@0 175
ian@0 176 /*
ian@0 177 ** RIO Host Service routine. Does all the work traditionally associated with an
ian@0 178 ** interrupt.
ian@0 179 */
ian@0 180 static int RupIntr;
ian@0 181 static int RxIntr;
ian@0 182 static int TxIntr;
ian@0 183
ian@0 184 void RIOServiceHost(struct rio_info *p, struct Host *HostP, int From)
ian@0 185 {
ian@0 186 rio_spin_lock(&HostP->HostLock);
ian@0 187 if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
ian@0 188 static int t = 0;
ian@0 189 rio_spin_unlock(&HostP->HostLock);
ian@0 190 if ((t++ % 200) == 0)
ian@0 191 rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags);
ian@0 192 return;
ian@0 193 }
ian@0 194 rio_spin_unlock(&HostP->HostLock);
ian@0 195
ian@0 196 if (readw(&HostP->ParmMapP->rup_intr)) {
ian@0 197 writew(0, &HostP->ParmMapP->rup_intr);
ian@0 198 p->RIORupCount++;
ian@0 199 RupIntr++;
ian@0 200 rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts);
ian@0 201 RIOPollHostCommands(p, HostP);
ian@0 202 }
ian@0 203
ian@0 204 if (readw(&HostP->ParmMapP->rx_intr)) {
ian@0 205 int port;
ian@0 206
ian@0 207 writew(0, &HostP->ParmMapP->rx_intr);
ian@0 208 p->RIORxCount++;
ian@0 209 RxIntr++;
ian@0 210
ian@0 211 rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts);
ian@0 212 /*
ian@0 213 ** Loop through every port. If the port is mapped into
ian@0 214 ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
ian@0 215 ** worth checking. If the port isn't open, grab any packets
ian@0 216 ** hanging on its receive queue and stuff them on the free
ian@0 217 ** list; check for commands on the way.
ian@0 218 */
ian@0 219 for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
ian@0 220 struct Port *PortP = p->RIOPortp[port];
ian@0 221 struct tty_struct *ttyP;
ian@0 222 struct PKT __iomem *PacketP;
ian@0 223
ian@0 224 /*
ian@0 225 ** not mapped in - most of the RIOPortp[] information
ian@0 226 ** has not been set up!
ian@0 227 ** Optimise: ports come in bundles of eight.
ian@0 228 */
ian@0 229 if (!PortP->Mapped) {
ian@0 230 port += 7;
ian@0 231 continue; /* with the next port */
ian@0 232 }
ian@0 233
ian@0 234 /*
ian@0 235 ** If the host board isn't THIS host board, check the next one.
ian@0 236 ** optimise: ports come in bundles of eight.
ian@0 237 */
ian@0 238 if (PortP->HostP != HostP) {
ian@0 239 port += 7;
ian@0 240 continue;
ian@0 241 }
ian@0 242
ian@0 243 /*
ian@0 244 ** Let us see - is the port open? If not, then don't service it.
ian@0 245 */
ian@0 246 if (!(PortP->PortState & PORT_ISOPEN)) {
ian@0 247 continue;
ian@0 248 }
ian@0 249
ian@0 250 /*
ian@0 251 ** find corresponding tty structure. The process of mapping
ian@0 252 ** the ports puts these here.
ian@0 253 */
ian@0 254 ttyP = PortP->gs.tty;
ian@0 255
ian@0 256 /*
ian@0 257 ** Lock the port before we begin working on it.
ian@0 258 */
ian@0 259 rio_spin_lock(&PortP->portSem);
ian@0 260
ian@0 261 /*
ian@0 262 ** Process received data if there is any.
ian@0 263 */
ian@0 264 if (can_remove_receive(&PacketP, PortP))
ian@0 265 RIOReceive(p, PortP);
ian@0 266
ian@0 267 /*
ian@0 268 ** If there is no data left to be read from the port, and
ian@0 269 ** it's handshake bit is set, then we must clear the handshake,
ian@0 270 ** so that that downstream RTA is re-enabled.
ian@0 271 */
ian@0 272 if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) {
ian@0 273 /*
ian@0 274 ** MAGIC! ( Basically, handshake the RX buffer, so that
ian@0 275 ** the RTAs upstream can be re-enabled. )
ian@0 276 */
ian@0 277 rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n");
ian@0 278 writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
ian@0 279 }
ian@0 280 rio_spin_unlock(&PortP->portSem);
ian@0 281 }
ian@0 282 }
ian@0 283
ian@0 284 if (readw(&HostP->ParmMapP->tx_intr)) {
ian@0 285 int port;
ian@0 286
ian@0 287 writew(0, &HostP->ParmMapP->tx_intr);
ian@0 288
ian@0 289 p->RIOTxCount++;
ian@0 290 TxIntr++;
ian@0 291 rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts);
ian@0 292
ian@0 293 /*
ian@0 294 ** Loop through every port.
ian@0 295 ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
ian@0 296 ** associated ) then it is worth checking.
ian@0 297 */
ian@0 298 for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
ian@0 299 struct Port *PortP = p->RIOPortp[port];
ian@0 300 struct tty_struct *ttyP;
ian@0 301 struct PKT __iomem *PacketP;
ian@0 302
ian@0 303 /*
ian@0 304 ** not mapped in - most of the RIOPortp[] information
ian@0 305 ** has not been set up!
ian@0 306 */
ian@0 307 if (!PortP->Mapped) {
ian@0 308 port += 7;
ian@0 309 continue; /* with the next port */
ian@0 310 }
ian@0 311
ian@0 312 /*
ian@0 313 ** If the host board isn't running, then its data structures
ian@0 314 ** are no use to us - continue quietly.
ian@0 315 */
ian@0 316 if (PortP->HostP != HostP) {
ian@0 317 port += 7;
ian@0 318 continue; /* with the next port */
ian@0 319 }
ian@0 320
ian@0 321 /*
ian@0 322 ** Let us see - is the port open? If not, then don't service it.
ian@0 323 */
ian@0 324 if (!(PortP->PortState & PORT_ISOPEN)) {
ian@0 325 continue;
ian@0 326 }
ian@0 327
ian@0 328 rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
ian@0 329 /*
ian@0 330 ** Lock the port before we begin working on it.
ian@0 331 */
ian@0 332 rio_spin_lock(&PortP->portSem);
ian@0 333
ian@0 334 /*
ian@0 335 ** If we can't add anything to the transmit queue, then
ian@0 336 ** we need do none of this processing.
ian@0 337 */
ian@0 338 if (!can_add_transmit(&PacketP, PortP)) {
ian@0 339 rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
ian@0 340 rio_spin_unlock(&PortP->portSem);
ian@0 341 continue;
ian@0 342 }
ian@0 343
ian@0 344 /*
ian@0 345 ** find corresponding tty structure. The process of mapping
ian@0 346 ** the ports puts these here.
ian@0 347 */
ian@0 348 ttyP = PortP->gs.tty;
ian@0 349 /* If ttyP is NULL, the port is getting closed. Forget about it. */
ian@0 350 if (!ttyP) {
ian@0 351 rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n");
ian@0 352 rio_spin_unlock(&PortP->portSem);
ian@0 353 continue;
ian@0 354 }
ian@0 355 /*
ian@0 356 ** If there is more room available we start up the transmit
ian@0 357 ** data process again. This can be direct I/O, if the cookmode
ian@0 358 ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
ian@0 359 ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
ian@0 360 ** characters via the line discipline. We must always call
ian@0 361 ** the line discipline,
ian@0 362 ** so that user input characters can be echoed correctly.
ian@0 363 **
ian@0 364 ** ++++ Update +++++
ian@0 365 ** With the advent of double buffering, we now see if
ian@0 366 ** TxBufferOut-In is non-zero. If so, then we copy a packet
ian@0 367 ** to the output place, and set it going. If this empties
ian@0 368 ** the buffer, then we must issue a wakeup( ) on OUT.
ian@0 369 ** If it frees space in the buffer then we must issue
ian@0 370 ** a wakeup( ) on IN.
ian@0 371 **
ian@0 372 ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
ian@0 373 ** have to send a WFLUSH command down the PHB, to mark the
ian@0 374 ** end point of a WFLUSH. We also need to clear out any
ian@0 375 ** data from the double buffer! ( note that WflushFlag is a
ian@0 376 ** *count* of the number of WFLUSH commands outstanding! )
ian@0 377 **
ian@0 378 ** ++++ And there's more!
ian@0 379 ** If an RTA is powered off, then on again, and rebooted,
ian@0 380 ** whilst it has ports open, then we need to re-open the ports.
ian@0 381 ** ( reasonable enough ). We can't do this when we spot the
ian@0 382 ** re-boot, in interrupt time, because the queue is probably
ian@0 383 ** full. So, when we come in here, we need to test if any
ian@0 384 ** ports are in this condition, and re-open the port before
ian@0 385 ** we try to send any more data to it. Now, the re-booted
ian@0 386 ** RTA will be discarding packets from the PHB until it
ian@0 387 ** receives this open packet, but don't worry tooo much
ian@0 388 ** about that. The one thing that is interesting is the
ian@0 389 ** combination of this effect and the WFLUSH effect!
ian@0 390 */
ian@0 391 /* For now don't handle RTA reboots. -- REW.
ian@0 392 Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
ian@0 393 if (PortP->MagicFlags) {
ian@0 394 if (PortP->MagicFlags & MAGIC_REBOOT) {
ian@0 395 /*
ian@0 396 ** well, the RTA has been rebooted, and there is room
ian@0 397 ** on its queue to add the open packet that is required.
ian@0 398 **
ian@0 399 ** The messy part of this line is trying to decide if
ian@0 400 ** we need to call the Param function as a tty or as
ian@0 401 ** a modem.
ian@0 402 ** DONT USE CLOCAL AS A TEST FOR THIS!
ian@0 403 **
ian@0 404 ** If we can't param the port, then move on to the
ian@0 405 ** next port.
ian@0 406 */
ian@0 407 PortP->InUse = NOT_INUSE;
ian@0 408
ian@0 409 rio_spin_unlock(&PortP->portSem);
ian@0 410 if (RIOParam(PortP, OPEN, ((PortP->Cor2Copy & (COR2_RTSFLOW | COR2_CTSFLOW)) == (COR2_RTSFLOW | COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL) {
ian@0 411 continue; /* with next port */
ian@0 412 }
ian@0 413 rio_spin_lock(&PortP->portSem);
ian@0 414 PortP->MagicFlags &= ~MAGIC_REBOOT;
ian@0 415 }
ian@0 416
ian@0 417 /*
ian@0 418 ** As mentioned above, this is a tacky hack to cope
ian@0 419 ** with WFLUSH
ian@0 420 */
ian@0 421 if (PortP->WflushFlag) {
ian@0 422 rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
ian@0 423
ian@0 424 if (PortP->InUse)
ian@0 425 rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
ian@0 426 }
ian@0 427
ian@0 428 while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) {
ian@0 429 int p;
ian@0 430 struct PktCmd __iomem *PktCmdP;
ian@0 431
ian@0 432 rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
ian@0 433 /*
ian@0 434 ** make it look just like a WFLUSH command
ian@0 435 */
ian@0 436 PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0];
ian@0 437
ian@0 438 writeb(WFLUSH, &PktCmdP->Command);
ian@0 439
ian@0 440 p = PortP->HostPort % (u16) PORTS_PER_RTA;
ian@0 441
ian@0 442 /*
ian@0 443 ** If second block of ports for 16 port RTA, add 8
ian@0 444 ** to index 8-15.
ian@0 445 */
ian@0 446 if (PortP->SecondBlock)
ian@0 447 p += PORTS_PER_RTA;
ian@0 448
ian@0 449 writeb(p, &PktCmdP->PhbNum);
ian@0 450
ian@0 451 /*
ian@0 452 ** to make debuggery easier
ian@0 453 */
ian@0 454 writeb('W', &PacketP->data[2]);
ian@0 455 writeb('F', &PacketP->data[3]);
ian@0 456 writeb('L', &PacketP->data[4]);
ian@0 457 writeb('U', &PacketP->data[5]);
ian@0 458 writeb('S', &PacketP->data[6]);
ian@0 459 writeb('H', &PacketP->data[7]);
ian@0 460 writeb(' ', &PacketP->data[8]);
ian@0 461 writeb('0' + PortP->WflushFlag, &PacketP->data[9]);
ian@0 462 writeb(' ', &PacketP->data[10]);
ian@0 463 writeb(' ', &PacketP->data[11]);
ian@0 464 writeb('\0', &PacketP->data[12]);
ian@0 465
ian@0 466 /*
ian@0 467 ** its two bytes long!
ian@0 468 */
ian@0 469 writeb(PKT_CMD_BIT | 2, &PacketP->len);
ian@0 470
ian@0 471 /*
ian@0 472 ** queue it!
ian@0 473 */
ian@0 474 if (!(PortP->State & RIO_DELETED)) {
ian@0 475 add_transmit(PortP);
ian@0 476 /*
ian@0 477 ** Count chars tx'd for port statistics reporting
ian@0 478 */
ian@0 479 if (PortP->statsGather)
ian@0 480 PortP->txchars += 2;
ian@0 481 }
ian@0 482
ian@0 483 if (--(PortP->WflushFlag) == 0) {
ian@0 484 PortP->MagicFlags &= ~MAGIC_FLUSH;
ian@0 485 }
ian@0 486
ian@0 487 rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag);
ian@0 488 }
ian@0 489 if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) {
ian@0 490 if (PortP->MagicFlags & MAGIC_FLUSH) {
ian@0 491 PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
ian@0 492 } else {
ian@0 493 if (!can_add_transmit(&PacketP, PortP)) {
ian@0 494 rio_spin_unlock(&PortP->portSem);
ian@0 495 continue;
ian@0 496 }
ian@0 497 rio_spin_unlock(&PortP->portSem);
ian@0 498 RIOTxEnable((char *) PortP);
ian@0 499 rio_spin_lock(&PortP->portSem);
ian@0 500 PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
ian@0 501 }
ian@0 502 }
ian@0 503 }
ian@0 504
ian@0 505
ian@0 506 /*
ian@0 507 ** If we can't add anything to the transmit queue, then
ian@0 508 ** we need do none of the remaining processing.
ian@0 509 */
ian@0 510 if (!can_add_transmit(&PacketP, PortP)) {
ian@0 511 rio_spin_unlock(&PortP->portSem);
ian@0 512 continue;
ian@0 513 }
ian@0 514
ian@0 515 rio_spin_unlock(&PortP->portSem);
ian@0 516 RIOTxEnable((char *) PortP);
ian@0 517 }
ian@0 518 }
ian@0 519 }
ian@0 520
ian@0 521 /*
ian@0 522 ** Routine for handling received data for tty drivers
ian@0 523 */
ian@0 524 static void RIOReceive(struct rio_info *p, struct Port *PortP)
ian@0 525 {
ian@0 526 struct tty_struct *TtyP;
ian@0 527 unsigned short transCount;
ian@0 528 struct PKT __iomem *PacketP;
ian@0 529 register unsigned int DataCnt;
ian@0 530 unsigned char __iomem *ptr;
ian@0 531 unsigned char *buf;
ian@0 532 int copied = 0;
ian@0 533
ian@0 534 static int intCount, RxIntCnt;
ian@0 535
ian@0 536 /*
ian@0 537 ** The receive data process is to remove packets from the
ian@0 538 ** PHB until there aren't any more or the current cblock
ian@0 539 ** is full. When this occurs, there will be some left over
ian@0 540 ** data in the packet, that we must do something with.
ian@0 541 ** As we haven't unhooked the packet from the read list
ian@0 542 ** yet, we can just leave the packet there, having first
ian@0 543 ** made a note of how far we got. This means that we need
ian@0 544 ** a pointer per port saying where we start taking the
ian@0 545 ** data from - this will normally be zero, but when we
ian@0 546 ** run out of space it will be set to the offset of the
ian@0 547 ** next byte to copy from the packet data area. The packet
ian@0 548 ** length field is decremented by the number of bytes that
ian@0 549 ** we successfully removed from the packet. When this reaches
ian@0 550 ** zero, we reset the offset pointer to be zero, and free
ian@0 551 ** the packet from the front of the queue.
ian@0 552 */
ian@0 553
ian@0 554 intCount++;
ian@0 555
ian@0 556 TtyP = PortP->gs.tty;
ian@0 557 if (!TtyP) {
ian@0 558 rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
ian@0 559 return;
ian@0 560 }
ian@0 561
ian@0 562 if (PortP->State & RIO_THROTTLE_RX) {
ian@0 563 rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
ian@0 564 return;
ian@0 565 }
ian@0 566
ian@0 567 if (PortP->State & RIO_DELETED) {
ian@0 568 while (can_remove_receive(&PacketP, PortP)) {
ian@0 569 remove_receive(PortP);
ian@0 570 put_free_end(PortP->HostP, PacketP);
ian@0 571 }
ian@0 572 } else {
ian@0 573 /*
ian@0 574 ** loop, just so long as:
ian@0 575 ** i ) there's some data ( i.e. can_remove_receive )
ian@0 576 ** ii ) we haven't been blocked
ian@0 577 ** iii ) there's somewhere to put the data
ian@0 578 ** iv ) we haven't outstayed our welcome
ian@0 579 */
ian@0 580 transCount = 1;
ian@0 581 while (can_remove_receive(&PacketP, PortP)
ian@0 582 && transCount) {
ian@0 583 RxIntCnt++;
ian@0 584
ian@0 585 /*
ian@0 586 ** check that it is not a command!
ian@0 587 */
ian@0 588 if (readb(&PacketP->len) & PKT_CMD_BIT) {
ian@0 589 rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
ian@0 590 /* rio_dprint(RIO_DEBUG_INTR, (" sysport = %d\n", p->RIOPortp->PortNum)); */
ian@0 591 rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit));
ian@0 592 rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port));
ian@0 593 rio_dprintk(RIO_DEBUG_INTR, " src_unit = %d\n", readb(&PacketP->src_unit));
ian@0 594 rio_dprintk(RIO_DEBUG_INTR, " src_port = %d\n", readb(&PacketP->src_port));
ian@0 595 rio_dprintk(RIO_DEBUG_INTR, " len = %d\n", readb(&PacketP->len));
ian@0 596 rio_dprintk(RIO_DEBUG_INTR, " control = %d\n", readb(&PacketP->control));
ian@0 597 rio_dprintk(RIO_DEBUG_INTR, " csum = %d\n", readw(&PacketP->csum));
ian@0 598 rio_dprintk(RIO_DEBUG_INTR, " data bytes: ");
ian@0 599 for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++)
ian@0 600 rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt]));
ian@0 601 remove_receive(PortP);
ian@0 602 put_free_end(PortP->HostP, PacketP);
ian@0 603 continue; /* with next packet */
ian@0 604 }
ian@0 605
ian@0 606 /*
ian@0 607 ** How many characters can we move 'upstream' ?
ian@0 608 **
ian@0 609 ** Determine the minimum of the amount of data
ian@0 610 ** available and the amount of space in which to
ian@0 611 ** put it.
ian@0 612 **
ian@0 613 ** 1. Get the packet length by masking 'len'
ian@0 614 ** for only the length bits.
ian@0 615 ** 2. Available space is [buffer size] - [space used]
ian@0 616 **
ian@0 617 ** Transfer count is the minimum of packet length
ian@0 618 ** and available space.
ian@0 619 */
ian@0 620
ian@0 621 transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK);
ian@0 622 rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount);
ian@0 623 /*
ian@0 624 ** To use the following 'kkprintfs' for debugging - change the '#undef'
ian@0 625 ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
ian@0 626 ** driver).
ian@0 627 */
ian@0 628 ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart;
ian@0 629
ian@0 630 tty_prepare_flip_string(TtyP, &buf, transCount);
ian@0 631 rio_memcpy_fromio(buf, ptr, transCount);
ian@0 632 PortP->RxDataStart += transCount;
ian@0 633 writeb(readb(&PacketP->len)-transCount, &PacketP->len);
ian@0 634 copied += transCount;
ian@0 635
ian@0 636
ian@0 637
ian@0 638 if (readb(&PacketP->len) == 0) {
ian@0 639 /*
ian@0 640 ** If we have emptied the packet, then we can
ian@0 641 ** free it, and reset the start pointer for
ian@0 642 ** the next packet.
ian@0 643 */
ian@0 644 remove_receive(PortP);
ian@0 645 put_free_end(PortP->HostP, PacketP);
ian@0 646 PortP->RxDataStart = 0;
ian@0 647 }
ian@0 648 }
ian@0 649 }
ian@0 650 if (copied) {
ian@0 651 rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
ian@0 652 tty_flip_buffer_push(TtyP);
ian@0 653 }
ian@0 654
ian@0 655 return;
ian@0 656 }
ian@0 657