/* * Mouse activity select routine */ qvselect(dev_t dev, rw) { register int s = spl5(); register struct qv_info *qp = qv_scn; if( QVCHAN(minor(dev)) == QVMOUSECHAN ) switch(rw) { case FREAD: /* if events okay */ if(qp->ihead != qp->itail) { splx(s); return(1); } qvrsel = u.u_procp; splx(s); return(0); default: /* can never write */ splx(s); return(0); } else { splx(s); return( ttselect(dev, rw) ); } /*NOTREACHED*/ }
/* * Start transmission */ qvstart(register struct tty *tp) { register int unit, c; register struct tty *tp0; int s; unit = minor(tp->t_dev); #ifdef CONS_HACK tp0 = &qv_tty[(unit&0xfc)+QVPCONS]; #endif unit = QVCHAN(unit); s = spl5(); /* * If it's currently active, or delaying, no need to do anything. */ if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) goto out; /* * Display chars until the queue is empty, if the second subchannel * is open direct them there. Drop characters from subchannels other * than 0 on the floor. */ while( tp->t_outq.c_cc ) { c = getc(&tp->t_outq); if (unit == QVKEYBOARD) #ifdef CONS_HACK if( tp0->t_state & TS_ISOPEN ){ (*tp0->t_linesw->l_rint)(c, tp0); } else #endif qvputchar( c & 0xff ); } /* * Position the cursor to the next character location. */ qv_pos_cur( qv_scn->col*8, qv_scn->row*15 ); /* * If there are sleepers, and output has drained below low * water mark, wake up the sleepers. */ ttypull(tp); tp->t_state &= ~TS_BUSY; out: splx(s); }
/*ARGSUSED*/ void qvstop(register struct tty *tp, int flag) { register int s; /* * Block input/output interrupts while messing with state. */ s = spl5(); if (tp->t_state & TS_BUSY) { if ((tp->t_state&TS_TTSTOP)==0) { tp->t_state |= TS_FLUSH; } else tp->t_state &= ~TS_BUSY; } splx(s); }
/* * This routine is called once for every block on which * an I/O operation needs to be done. */ void ideStrategy(struct buf *bp) { int minorDev; unsigned int blkStart; if (debugIdeDisk) { printf("----- ideStrategy dev = 0x%08X, blk = 0x%08X, %s -----\n", bp->b_dev, bp->b_blkno, bp->b_flags & B_READ ? "read" : "write"); } if (!ideInitialized) { ideInitialize(); } minorDev = minor(bp->b_dev); blkStart = bp->b_blkno * SPB; /* check parameters */ if (minorDev != 16) { if (minorDev < 0 || minorDev > 15 || ((partTbl[minorDev].type & 0x7FFFFFFF) != EOS32_FSYS && (partTbl[minorDev].type & 0x7FFFFFFF) != EOS32_SWAP) || blkStart + SPB > partTbl[minorDev].size) { /* illegal disk I/O request */ bp->b_flags |= B_ERROR; iodone(bp); return; } } spl5(); /* link buffer to disk queue */ bp->av_forw = NULL; if (ideTab.b_actf == NULL) { ideTab.b_actf = bp; } else { ideTab.b_actl->av_forw = bp; } ideTab.b_actl = bp; /* start operation if none in progress */ if (ideTab.b_active == 0) { ideStart(); } spl0(); }
hcommand(dev, com) { register struct buf *bp; bp = &chtbuf; VOID spl5(); while(bp->b_flags&B_BUSY) { bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO); } VOID spl0(); bp->b_dev = dev; bp->b_resid = com; bp->b_blkno = 0; bp->b_flags = B_BUSY|B_READ; htstrategy(bp); iowait(bp); if(bp->b_flags&B_WANTED) wakeup((caddr_t)bp); bp->b_flags = 0; return(bp->b_resid); }
vtwrite() { register int c; int register count; while ((c=cpass()) >= 0) { retry: for (count=0; count<10; count++) if ((VTADDR->csr&RQINT)==0) { VTADDR->buf = c&0377; VTADDR->csr =| RQINT; goto contin; } spl5(); if (VTADDR->csr&RQINT) { vtflag++; sleep(VTADDR, VTPRI); } spl0(); goto retry; contin:; } }
/* * This is the disk interrupt service routine. */ static void ideISR(int irq, InterruptContext *icp) { unsigned int diskCtrl; struct buf *bp; /* set process priority, re-enable interrupts */ spl5(); enableInt(); /* clear done bit und thus the yet pending irq */ diskCtrl = *DISK_CTRL; *DISK_CTRL = diskCtrl & (unsigned)~(DISK_CTRL_DONE | DISK_CTRL_STRT); if (ideTab.b_active == 0) { return; } bp = ideTab.b_actf; ideTab.b_active = 0; if (diskCtrl & DISK_CTRL_ERR) { /* an error occurred */ deverror(bp->b_dev, bp->b_blkno, diskCtrl); if (++ideTab.b_errcnt <= 10) { ideStart(); return; } bp->b_flags |= B_ERROR; } else { if (bp->b_flags & B_READ) { /* this was a read operation - transfer block from disk buffer */ copyWords((unsigned int *) bp->b_un.b_addr, DISK_BUFFER, WPB); } } ideTab.b_errcnt = 0; ideTab.b_actf = bp->av_forw; bp->b_resid = 0; /* hand buffer back to buffer cache */ iodone(bp); /* start next operation */ ideStart(); }
/* * Attach a found zs. * * Match slave number to zs unit number, so that misconfiguration will * not set up the keyboard as ttya, etc. */ static void zs_attach(device_t parent, device_t self, void *aux) { struct zsc_softc *zsc = device_private(self); struct confargs *ca = aux; struct zsc_attach_args zsc_args; volatile struct zschan *zc; struct zs_chanstate *cs; int s, zs_unit, channel; static int didintr; zsc->zsc_dev = self; zs_unit = device_unit(self); aprint_normal(": (softpri %d)\n", ZSSOFT_PRI); /* Use the mapping setup by the Sun PROM. */ if (zsaddr[zs_unit] == NULL) panic("zs_attach: zs%d not mapped", zs_unit); /* * Initialize software state for each channel. */ for (channel = 0; channel < 2; channel++) { zsc_args.channel = channel; zsc_args.hwflags = zs_hwflags[zs_unit][channel]; cs = &zsc->zsc_cs_store[channel]; zsc->zsc_cs[channel] = cs; zs_lock_init(cs); cs->cs_channel = channel; cs->cs_private = NULL; cs->cs_ops = &zsops_null; cs->cs_brg_clk = PCLK / 16; zc = zs_get_chan_addr(zs_unit, channel); cs->cs_reg_csr = &zc->zc_csr; cs->cs_reg_data = &zc->zc_data; memcpy(cs->cs_creg, zs_init_reg, 16); memcpy(cs->cs_preg, zs_init_reg, 16); /* XXX: Get these from the EEPROM instead? */ /* XXX: See the mvme167 code. Better. */ if (zsc_args.hwflags & ZS_HWFLAG_CONSOLE) cs->cs_defspeed = zs_get_speed(cs); else cs->cs_defspeed = zs_defspeed[zs_unit][channel]; cs->cs_defcflag = zs_def_cflag; /* Make these correspond to cs_defcflag (-crtscts) */ cs->cs_rr0_dcd = ZSRR0_DCD; cs->cs_rr0_cts = 0; cs->cs_wr5_dtr = ZSWR5_DTR | ZSWR5_RTS; cs->cs_wr5_rts = 0; /* * Clear the master interrupt enable. * The INTENA is common to both channels, * so just do it on the A channel. */ if (channel == 0) { zs_write_reg(cs, 9, 0); } /* * Look for a child driver for this channel. * The child attach will setup the hardware. */ if (!config_found(self, (void *)&zsc_args, zs_print)) { /* No sub-driver. Just reset it. */ uint8_t reset = (channel == 0) ? ZSWR9_A_RESET : ZSWR9_B_RESET; s = splhigh(); zs_write_reg(cs, 9, reset); splx(s); } } /* * Now safe to install interrupt handlers. Note the arguments * to the interrupt handlers aren't used. Note, we only do this * once since both SCCs interrupt at the same level and vector. */ if (!didintr) { didintr = 1; isr_add_autovect(zshard, NULL, ca->ca_intpri); } zsc->zs_si = softint_establish(SOFTINT_SERIAL, (void (*)(void *))zsc_intr_soft, zsc); /* XXX; evcnt_attach() ? */ /* * Set the master interrupt enable and interrupt vector. * (common to both channels, do it on A) */ cs = zsc->zsc_cs[0]; s = splhigh(); /* interrupt vector */ zs_write_reg(cs, 2, zs_init_reg[2]); /* master interrupt control (enable) */ zs_write_reg(cs, 9, zs_init_reg[9]); splx(s); /* * XXX: L1A hack - We would like to be able to break into * the debugger during the rest of autoconfiguration, so * lower interrupts just enough to let zs interrupts in. * This is done after both zs devices are attached. */ if (zs_unit == 1) { (void)spl5(); /* splzs - 1 */ } }