os161-1.99
 All Data Structures
lser.c
00001 /*
00002  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
00003  *      The President and Fellows of Harvard College.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 #include <types.h>
00031 #include <lib.h>
00032 #include <spinlock.h>
00033 #include <platform/bus.h>
00034 #include <lamebus/lser.h>
00035 #include "autoconf.h"
00036 
00037 /* Registers (offsets within slot) */
00038 #define LSER_REG_CHAR  0     /* Character in/out */
00039 #define LSER_REG_WIRQ  4     /* Write interrupt status */
00040 #define LSER_REG_RIRQ  8     /* Read interrupt status */
00041 
00042 /* Bits in the IRQ registers */
00043 #define LSER_IRQ_ENABLE  1
00044 #define LSER_IRQ_ACTIVE  2
00045 
00046 void
00047 lser_irq(void *vsc)
00048 {
00049         struct lser_softc *sc = vsc;
00050         uint32_t x;
00051         bool clear_to_write = false;
00052         bool got_a_read = false;
00053         uint32_t ch = 0;
00054 
00055         spinlock_acquire(&sc->ls_lock);
00056 
00057         x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
00058         if (x & LSER_IRQ_ACTIVE) {
00059                 x = LSER_IRQ_ENABLE;
00060                 sc->ls_wbusy = 0;
00061                 clear_to_write = true;
00062                 bus_write_register(sc->ls_busdata, sc->ls_buspos,
00063                                    LSER_REG_WIRQ, x);
00064         }
00065 
00066         x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ);
00067         if (x & LSER_IRQ_ACTIVE) {
00068                 x = LSER_IRQ_ENABLE;
00069                 ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
00070                                        LSER_REG_CHAR);
00071                 got_a_read = true;
00072                 bus_write_register(sc->ls_busdata, sc->ls_buspos, 
00073                                    LSER_REG_RIRQ, x);
00074         }
00075 
00076         spinlock_release(&sc->ls_lock);
00077 
00078         if (clear_to_write && sc->ls_start != NULL) {
00079                 sc->ls_start(sc->ls_devdata);
00080         }
00081         if (got_a_read && sc->ls_input != NULL) {
00082                 sc->ls_input(sc->ls_devdata, ch);
00083         }
00084 }
00085 
00086 void
00087 lser_write(void *vls, int ch)
00088 {
00089         struct lser_softc *ls = vls;
00090 
00091         spinlock_acquire(&ls->ls_lock);
00092 
00093         if (ls->ls_wbusy) {
00094                 /*
00095                  * We're not clear to write.
00096                  *
00097                  * This should not happen. It's the job of the driver
00098                  * attached to us to not write until we call
00099                  * ls->ls_start.
00100                  *
00101                  * (Note: if we're the console, the panic will go to
00102                  * lser_writepolled for printing, because we hold a
00103                  * spinlock and interrupts are off; it won't recurse.)
00104                  */
00105                 panic("lser: Not clear to write\n");
00106         }
00107         ls->ls_wbusy = true;
00108 
00109         bus_write_register(ls->ls_busdata, ls->ls_buspos, LSER_REG_CHAR, ch);
00110 
00111         spinlock_release(&ls->ls_lock);
00112 }
00113 
00114 static
00115 void
00116 lser_poll_until_write(struct lser_softc *sc)
00117 {
00118         uint32_t val;
00119 
00120         KASSERT(spinlock_do_i_hold(&sc->ls_lock));
00121 
00122         do {
00123                 val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
00124                                         LSER_REG_WIRQ);
00125         }
00126         while ((val & LSER_IRQ_ACTIVE) == 0);
00127 }
00128 
00129 void
00130 lser_writepolled(void *vsc, int ch)
00131 {
00132         struct lser_softc *sc = vsc;
00133         bool irqpending = false;
00134 
00135         spinlock_acquire(&sc->ls_lock);
00136 
00137         if (sc->ls_wbusy) {
00138                 irqpending = true;
00139                 lser_poll_until_write(sc);
00140                 /* Clear the ready condition */
00141                 bus_write_register(sc->ls_busdata, sc->ls_buspos,
00142                                    LSER_REG_WIRQ, LSER_IRQ_ENABLE);
00143         }
00144 
00145         /* Send the character. */
00146         bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR, ch);
00147 
00148         /* Wait until it's done. */
00149         lser_poll_until_write(sc);
00150 
00151         /*
00152          * If there wasn't already an IRQ pending, clear the ready condition.
00153          * But if there was, leave the ready condition, so we get to the 
00154          * interrupt handler in due course.
00155          */
00156         if (!irqpending) {
00157                 bus_write_register(sc->ls_busdata, sc->ls_buspos,
00158                                    LSER_REG_WIRQ, LSER_IRQ_ENABLE);
00159         }
00160 
00161         spinlock_release(&sc->ls_lock);
00162 }
00163 
00164 /*
00165  * Mask the interrupt while we're writing in polling mode. Doing so
00166  * causes the interrupt line to flap on every character, which makes
00167  * the CPU receiving those interrupts upset.
00168  */
00169 void
00170 lser_startpolling(void *vsc)
00171 {
00172         struct lser_softc *sc = vsc;
00173         sc->ls_maskinterrupt(sc->ls_busdata, sc->ls_buspos);
00174 }
00175 
00176 void
00177 lser_endpolling(void *vsc)
00178 {
00179         struct lser_softc *sc = vsc;
00180         sc->ls_unmaskinterrupt(sc->ls_busdata, sc->ls_buspos);
00181 }
00182 
00183 int
00184 config_lser(struct lser_softc *sc, int lserno)
00185 {
00186         (void)lserno;
00187 
00188         /*
00189          * Enable interrupting.
00190          */
00191 
00192         spinlock_init(&sc->ls_lock);
00193         sc->ls_wbusy = false;
00194 
00195         bus_write_register(sc->ls_busdata, sc->ls_buspos,
00196                            LSER_REG_RIRQ, LSER_IRQ_ENABLE);
00197         bus_write_register(sc->ls_busdata, sc->ls_buspos,
00198                            LSER_REG_WIRQ, LSER_IRQ_ENABLE);
00199 
00200         return 0;
00201 }
 All Data Structures