clang-format

This commit is contained in:
2024-09-10 13:03:02 -04:00
parent 53c617d779
commit d66450e427
381 changed files with 28864 additions and 34170 deletions

View File

@@ -38,18 +38,16 @@
#include <lamebus/ltimer.h>
#include "autoconf.h"
struct beep_softc *
attach_beep_to_ltimer(int beepno, struct ltimer_softc *ls)
{
struct beep_softc *bs = kmalloc(sizeof(struct beep_softc));
if (bs==NULL) {
return NULL;
}
struct beep_softc *attach_beep_to_ltimer(int beepno, struct ltimer_softc *ls) {
struct beep_softc *bs = kmalloc(sizeof(struct beep_softc));
if (bs == NULL) {
return NULL;
}
(void)beepno; // unused
(void)beepno; // unused
bs->bs_devdata = ls;
bs->bs_beep = ltimer_beep;
bs->bs_devdata = ls;
bs->bs_beep = ltimer_beep;
return bs;
return bs;
}

View File

@@ -38,22 +38,19 @@
#include <lamebus/lscreen.h>
#include "autoconf.h"
struct con_softc *
attach_con_to_lscreen(int consno, struct lscreen_softc *ls)
{
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs==NULL) {
return NULL;
}
struct con_softc *attach_con_to_lscreen(int consno, struct lscreen_softc *ls) {
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs == NULL) {
return NULL;
}
cs->cs_devdata = ls;
cs->cs_send = lscreen_write;
cs->cs_sendpolled = lscreen_write;
cs->cs_devdata = ls;
cs->cs_send = lscreen_write;
cs->cs_sendpolled = lscreen_write;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
return cs;
return cs;
}

View File

@@ -38,24 +38,21 @@
#include <lamebus/lser.h>
#include "autoconf.h"
struct con_softc *
attach_con_to_lser(int consno, struct lser_softc *ls)
{
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs==NULL) {
return NULL;
}
struct con_softc *attach_con_to_lser(int consno, struct lser_softc *ls) {
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs == NULL) {
return NULL;
}
(void)consno; // unused
(void)consno; // unused
cs->cs_devdata = ls;
cs->cs_send = lser_write;
cs->cs_sendpolled = lser_writepolled;
cs->cs_devdata = ls;
cs->cs_send = lser_write;
cs->cs_sendpolled = lser_writepolled;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
return cs;
return cs;
}

File diff suppressed because it is too large Load Diff

View File

@@ -30,9 +30,8 @@
#ifndef _LAMEBUS_EMU_H_
#define _LAMEBUS_EMU_H_
#define EMU_MAXIO 16384
#define EMU_ROOTHANDLE 0
#define EMU_MAXIO 16384
#define EMU_ROOTHANDLE 0
/*
* The per-device data used by the emufs device driver.
@@ -41,22 +40,21 @@
*/
struct emu_softc {
/* Initialized by lower-level attach code */
void *e_busdata;
uint32_t e_buspos;
int e_unit;
/* Initialized by lower-level attach code */
void *e_busdata;
uint32_t e_buspos;
int e_unit;
/* Initialized by config_emu() */
struct lock *e_lock;
struct semaphore *e_sem;
void *e_iobuf;
/* Initialized by config_emu() */
struct lock *e_lock;
struct semaphore *e_sem;
void *e_iobuf;
/* Written by the interrupt handler */
uint32_t e_result;
/* Written by the interrupt handler */
uint32_t e_result;
};
/* Functions called by lower-level drivers */
void emu_irq(/*struct emu_softc*/ void *);
#endif /* _LAMEBUS_EMU_H_ */

View File

@@ -38,29 +38,27 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct emu_softc *
attach_emu_to_lamebus(int emuno, struct lamebus_softc *sc)
{
struct emu_softc *es;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_EMUFS,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct emu_softc *attach_emu_to_lamebus(int emuno, struct lamebus_softc *sc) {
struct emu_softc *es;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_EMUFS, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
es = kmalloc(sizeof(struct emu_softc));
if (es==NULL) {
return NULL;
}
es = kmalloc(sizeof(struct emu_softc));
if (es == NULL) {
return NULL;
}
es->e_busdata = sc;
es->e_buspos = slot;
es->e_unit = emuno;
es->e_busdata = sc;
es->e_buspos = slot;
es->e_unit = emuno;
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, es, emu_irq);
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, es, emu_irq);
return es;
return es;
}

View File

@@ -40,147 +40,124 @@
#include <lamebus/lamebus.h>
/* Register offsets within each config region */
#define CFGREG_VID 0 /* Vendor ID */
#define CFGREG_DID 4 /* Device ID */
#define CFGREG_DRL 8 /* Device Revision Level */
#define CFGREG_VID 0 /* Vendor ID */
#define CFGREG_DID 4 /* Device ID */
#define CFGREG_DRL 8 /* Device Revision Level */
/* LAMEbus controller private registers (offsets within its config region) */
#define CTLREG_RAMSZ 0x200
#define CTLREG_IRQS 0x204
#define CTLREG_PWR 0x208
#define CTLREG_IRQE 0x20c
#define CTLREG_CPUS 0x210
#define CTLREG_CPUE 0x214
#define CTLREG_SELF 0x218
#define CTLREG_RAMSZ 0x200
#define CTLREG_IRQS 0x204
#define CTLREG_PWR 0x208
#define CTLREG_IRQE 0x20c
#define CTLREG_CPUS 0x210
#define CTLREG_CPUE 0x214
#define CTLREG_SELF 0x218
/* LAMEbus CPU control registers (offsets within each per-cpu region) */
#define CTLCPU_CIRQE 0x000
#define CTLCPU_CIPI 0x004
#define CTLCPU_CRAM 0x300
#define CTLCPU_CIRQE 0x000
#define CTLCPU_CIPI 0x004
#define CTLCPU_CRAM 0x300
/*
* Read a config register for the given slot.
*/
static
inline
uint32_t
read_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset)
{
/* Note that lb might be NULL on some platforms in some contexts. */
offset += LB_CONFIG_SIZE*slot;
return lamebus_read_register(lb, LB_CONTROLLER_SLOT, offset);
static inline uint32_t read_cfg_register(struct lamebus_softc *lb, int slot,
uint32_t offset) {
/* Note that lb might be NULL on some platforms in some contexts. */
offset += LB_CONFIG_SIZE * slot;
return lamebus_read_register(lb, LB_CONTROLLER_SLOT, offset);
}
/*
* Write a config register for a given slot.
*/
static
inline
void
write_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset,
uint32_t val)
{
offset += LB_CONFIG_SIZE*slot;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_cfg_register(struct lamebus_softc *lb, int slot,
uint32_t offset, uint32_t val) {
offset += LB_CONFIG_SIZE * slot;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Read one of the bus controller's registers.
*/
static
inline
uint32_t
read_ctl_register(struct lamebus_softc *lb, uint32_t offset)
{
/* Note that lb might be NULL on some platforms in some contexts. */
return read_cfg_register(lb, LB_CONTROLLER_SLOT, offset);
static inline uint32_t read_ctl_register(struct lamebus_softc *lb,
uint32_t offset) {
/* Note that lb might be NULL on some platforms in some contexts. */
return read_cfg_register(lb, LB_CONTROLLER_SLOT, offset);
}
/*
* Write one of the bus controller's registers.
*/
static
inline
void
write_ctl_register(struct lamebus_softc *lb, uint32_t offset, uint32_t val)
{
write_cfg_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_ctl_register(struct lamebus_softc *lb, uint32_t offset,
uint32_t val) {
write_cfg_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Write one of the bus controller's CPU control registers.
*/
static
inline
void
write_ctlcpu_register(struct lamebus_softc *lb, unsigned hw_cpunum,
uint32_t offset, uint32_t val)
{
offset += LB_CTLCPU_OFFSET + hw_cpunum * LB_CTLCPU_SIZE;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_ctlcpu_register(struct lamebus_softc *lb,
unsigned hw_cpunum, uint32_t offset,
uint32_t val) {
offset += LB_CTLCPU_OFFSET + hw_cpunum * LB_CTLCPU_SIZE;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Find and create secondary CPUs.
*/
void
lamebus_find_cpus(struct lamebus_softc *lamebus)
{
uint32_t mainboard_vid, mainboard_did;
uint32_t cpumask, self, bit, val;
unsigned i, numcpus, bootcpu;
unsigned hwnum[32];
void lamebus_find_cpus(struct lamebus_softc *lamebus) {
uint32_t mainboard_vid, mainboard_did;
uint32_t cpumask, self, bit, val;
unsigned i, numcpus, bootcpu;
unsigned hwnum[32];
mainboard_vid = read_cfg_register(lamebus, LB_CONTROLLER_SLOT,
CFGREG_VID);
mainboard_did = read_cfg_register(lamebus, LB_CONTROLLER_SLOT,
CFGREG_DID);
if (mainboard_vid == LB_VENDOR_CS161 &&
mainboard_did == LBCS161_UPBUSCTL) {
/* Old uniprocessor mainboard; no cpu registers. */
lamebus->ls_uniprocessor = 1;
return;
}
mainboard_vid = read_cfg_register(lamebus, LB_CONTROLLER_SLOT, CFGREG_VID);
mainboard_did = read_cfg_register(lamebus, LB_CONTROLLER_SLOT, CFGREG_DID);
if (mainboard_vid == LB_VENDOR_CS161 && mainboard_did == LBCS161_UPBUSCTL) {
/* Old uniprocessor mainboard; no cpu registers. */
lamebus->ls_uniprocessor = 1;
return;
}
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
numcpus = 0;
bootcpu = 0;
for (i=0; i<32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
bootcpu = numcpus;
curcpu->c_hardware_number = i;
}
hwnum[numcpus] = i;
numcpus++;
}
}
numcpus = 0;
bootcpu = 0;
for (i = 0; i < 32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
bootcpu = numcpus;
curcpu->c_hardware_number = i;
}
hwnum[numcpus] = i;
numcpus++;
}
}
for (i=0; i<numcpus; i++) {
if (i != bootcpu) {
cpu_create(hwnum[i]);
}
}
for (i = 0; i < numcpus; i++) {
if (i != bootcpu) {
cpu_create(hwnum[i]);
}
}
/*
* By default, route all interrupts only to the boot cpu. We
* could be arbitrarily more elaborate, up to things like
* dynamic load balancing.
*/
/*
* By default, route all interrupts only to the boot cpu. We
* could be arbitrarily more elaborate, up to things like
* dynamic load balancing.
*/
for (i=0; i<numcpus; i++) {
if (i != bootcpu) {
val = 0;
}
else {
val = 0xffffffff;
}
write_ctlcpu_register(lamebus, hwnum[i], CTLCPU_CIRQE, val);
}
for (i = 0; i < numcpus; i++) {
if (i != bootcpu) {
val = 0;
} else {
val = 0xffffffff;
}
write_ctlcpu_register(lamebus, hwnum[i], CTLCPU_CIRQE, val);
}
}
/*
@@ -193,43 +170,40 @@ lamebus_find_cpus(struct lamebus_softc *lamebus)
* LAMEbus; if in some environment there are other CPUs about as well
* this logic will have to be made more complex.
*/
void
lamebus_start_cpus(struct lamebus_softc *lamebus)
{
uint32_t cpumask, self, bit;
uint32_t ctlcpuoffset;
uint32_t *cram;
unsigned i;
unsigned cpunum;
void lamebus_start_cpus(struct lamebus_softc *lamebus) {
uint32_t cpumask, self, bit;
uint32_t ctlcpuoffset;
uint32_t *cram;
unsigned i;
unsigned cpunum;
if (lamebus->ls_uniprocessor) {
return;
}
if (lamebus->ls_uniprocessor) {
return;
}
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
/* Poke in the startup address. */
cpunum = 1;
for (i=0; i<32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
continue;
}
ctlcpuoffset = LB_CTLCPU_OFFSET + i * LB_CTLCPU_SIZE;
cram = lamebus_map_area(lamebus,
LB_CONTROLLER_SLOT,
ctlcpuoffset + CTLCPU_CRAM);
cram[0] = (uint32_t)cpu_start_secondary;
cram[1] = cpunum++;
}
}
/* Ensure all the above writes get flushed. */
membar_store_store();
/* Poke in the startup address. */
cpunum = 1;
for (i = 0; i < 32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
continue;
}
ctlcpuoffset = LB_CTLCPU_OFFSET + i * LB_CTLCPU_SIZE;
cram = lamebus_map_area(lamebus, LB_CONTROLLER_SLOT,
ctlcpuoffset + CTLCPU_CRAM);
cram[0] = (uint32_t)cpu_start_secondary;
cram[1] = cpunum++;
}
}
/* Ensure all the above writes get flushed. */
membar_store_store();
/* Now, enable them all. */
write_ctl_register(lamebus, CTLREG_CPUE, cpumask);
/* Now, enable them all. */
write_ctl_register(lamebus, CTLREG_CPUE, cpumask);
}
/*
@@ -247,58 +221,55 @@ lamebus_start_cpus(struct lamebus_softc *lamebus)
* more specific checks.
*/
int
lamebus_probe(struct lamebus_softc *sc,
uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret)
{
int slot;
uint32_t val;
int lamebus_probe(struct lamebus_softc *sc, uint32_t vendorid,
uint32_t deviceid, uint32_t lowver, uint32_t *version_ret) {
int slot;
uint32_t val;
/*
* Because the slot information in sc is used when dispatching
* interrupts, disable interrupts while working with it.
*/
/*
* Because the slot information in sc is used when dispatching
* interrupts, disable interrupts while working with it.
*/
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
for (slot=0; slot<LB_NSLOTS; slot++) {
if (sc->ls_slotsinuse & (1<<slot)) {
/* Slot already in use; skip */
continue;
}
for (slot = 0; slot < LB_NSLOTS; slot++) {
if (sc->ls_slotsinuse & (1 << slot)) {
/* Slot already in use; skip */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_VID);
if (val!=vendorid) {
/* Wrong vendor id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_VID);
if (val != vendorid) {
/* Wrong vendor id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DID);
if (val != deviceid) {
/* Wrong device id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DID);
if (val != deviceid) {
/* Wrong device id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DRL);
if (val < lowver) {
/* Unsupported device revision */
continue;
}
if (version_ret != NULL) {
*version_ret = val;
}
val = read_cfg_register(sc, slot, CFGREG_DRL);
if (val < lowver) {
/* Unsupported device revision */
continue;
}
if (version_ret != NULL) {
*version_ret = val;
}
/* Found something */
/* Found something */
spinlock_release(&sc->ls_lock);
return slot;
}
spinlock_release(&sc->ls_lock);
return slot;
}
/* Found nothing */
/* Found nothing */
spinlock_release(&sc->ls_lock);
return -1;
spinlock_release(&sc->ls_lock);
return -1;
}
/*
@@ -306,360 +277,328 @@ lamebus_probe(struct lamebus_softc *sc,
* This prevents the probe routine from returning the same device over
* and over again.
*/
void
lamebus_mark(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_mark(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)!=0) {
panic("lamebus_mark: slot %d already in use\n", slot);
}
if ((sc->ls_slotsinuse & mask) != 0) {
panic("lamebus_mark: slot %d already in use\n", slot);
}
sc->ls_slotsinuse |= mask;
sc->ls_slotsinuse |= mask;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Mark that a slot is no longer in use.
*/
void
lamebus_unmark(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_unmark(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_mark: slot %d not marked in use\n", slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_mark: slot %d not marked in use\n", slot);
}
sc->ls_slotsinuse &= ~mask;
sc->ls_slotsinuse &= ~mask;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Register a function (and a device context pointer) to be called
* when a particular slot signals an interrupt.
*/
void
lamebus_attach_interrupt(struct lamebus_softc *sc, int slot,
void *devdata,
void (*irqfunc)(void *devdata))
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_attach_interrupt(struct lamebus_softc *sc, int slot, void *devdata,
void (*irqfunc)(void *devdata)) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_attach_interrupt: slot %d not marked in use\n",
slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_attach_interrupt: slot %d not marked in use\n", slot);
}
KASSERT(sc->ls_devdata[slot]==NULL);
KASSERT(sc->ls_irqfuncs[slot]==NULL);
KASSERT(sc->ls_devdata[slot] == NULL);
KASSERT(sc->ls_irqfuncs[slot] == NULL);
sc->ls_devdata[slot] = devdata;
sc->ls_irqfuncs[slot] = irqfunc;
sc->ls_devdata[slot] = devdata;
sc->ls_irqfuncs[slot] = irqfunc;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Unregister a function that was being called when a particular slot
* signaled an interrupt.
*/
void
lamebus_detach_interrupt(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_detach_interrupt(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_detach_interrupt: slot %d not marked in use\n",
slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_detach_interrupt: slot %d not marked in use\n", slot);
}
KASSERT(sc->ls_irqfuncs[slot]!=NULL);
KASSERT(sc->ls_irqfuncs[slot] != NULL);
sc->ls_devdata[slot] = NULL;
sc->ls_irqfuncs[slot] = NULL;
sc->ls_devdata[slot] = NULL;
sc->ls_irqfuncs[slot] = NULL;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Mask/unmask an interrupt using the global IRQE register.
*/
void
lamebus_mask_interrupt(struct lamebus_softc *lamebus, int slot)
{
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
void lamebus_mask_interrupt(struct lamebus_softc *lamebus, int slot) {
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits &= ~mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits &= ~mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
}
void
lamebus_unmask_interrupt(struct lamebus_softc *lamebus, int slot)
{
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
void lamebus_unmask_interrupt(struct lamebus_softc *lamebus, int slot) {
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits |= mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits |= mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
}
/*
* LAMEbus interrupt handling function. (Machine-independent!)
*/
void
lamebus_interrupt(struct lamebus_softc *lamebus)
{
/*
* Note that despite the fact that "spl" stands for "set
* priority level", we don't actually support interrupt
* priorities. When an interrupt happens, we look through the
* slots to find the first interrupting device and call its
* interrupt routine, no matter what that device is.
*
* Note that the entire LAMEbus uses only one on-cpu interrupt line.
* Thus, we do not use any on-cpu interrupt priority system either.
*/
void lamebus_interrupt(struct lamebus_softc *lamebus) {
/*
* Note that despite the fact that "spl" stands for "set
* priority level", we don't actually support interrupt
* priorities. When an interrupt happens, we look through the
* slots to find the first interrupting device and call its
* interrupt routine, no matter what that device is.
*
* Note that the entire LAMEbus uses only one on-cpu interrupt line.
* Thus, we do not use any on-cpu interrupt priority system either.
*/
int slot;
uint32_t mask;
uint32_t irqs;
void (*handler)(void *);
void *data;
int slot;
uint32_t mask;
uint32_t irqs;
void (*handler)(void *);
void *data;
/* For keeping track of how many bogus things happen in a row. */
static int duds = 0;
int duds_this_time = 0;
/* For keeping track of how many bogus things happen in a row. */
static int duds = 0;
int duds_this_time = 0;
/* and we better have a valid bus instance. */
KASSERT(lamebus != NULL);
/* and we better have a valid bus instance. */
KASSERT(lamebus != NULL);
/* Lock the softc */
spinlock_acquire(&lamebus->ls_lock);
/* Lock the softc */
spinlock_acquire(&lamebus->ls_lock);
/*
* Read the LAMEbus controller register that tells us which
* slots are asserting an interrupt condition.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
/*
* Read the LAMEbus controller register that tells us which
* slots are asserting an interrupt condition.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
if (irqs == 0) {
/*
* Huh? None of them? Must be a glitch.
*/
kprintf("lamebus: stray interrupt on cpu %u\n",
curcpu->c_number);
duds++;
duds_this_time++;
if (irqs == 0) {
/*
* Huh? None of them? Must be a glitch.
*/
kprintf("lamebus: stray interrupt on cpu %u\n", curcpu->c_number);
duds++;
duds_this_time++;
/*
* We could just return now, but instead we'll
* continue ahead. Because irqs == 0, nothing in the
* loop will execute, and passing through it gets us
* to the code that checks how many duds we've
* seen. This is important, because we just might get
* a stray interrupt that latches itself on. If that
* happens, we're pretty much toast, but it's better
* to panic and hopefully reset the system than to
* loop forever printing "stray interrupt".
*/
}
/*
* We could just return now, but instead we'll
* continue ahead. Because irqs == 0, nothing in the
* loop will execute, and passing through it gets us
* to the code that checks how many duds we've
* seen. This is important, because we just might get
* a stray interrupt that latches itself on. If that
* happens, we're pretty much toast, but it's better
* to panic and hopefully reset the system than to
* loop forever printing "stray interrupt".
*/
}
/*
* Go through the bits in the value we got back to see which
* ones are set.
*/
/*
* Go through the bits in the value we got back to see which
* ones are set.
*/
for (mask=1, slot=0; slot<LB_NSLOTS; mask<<=1, slot++) {
if ((irqs & mask) == 0) {
/* Nope. */
continue;
}
for (mask = 1, slot = 0; slot < LB_NSLOTS; mask <<= 1, slot++) {
if ((irqs & mask) == 0) {
/* Nope. */
continue;
}
/*
* This slot is signalling an interrupt.
*/
/*
* This slot is signalling an interrupt.
*/
if ((lamebus->ls_slotsinuse & mask)==0) {
/*
* No device driver is using this slot.
*/
duds++;
duds_this_time++;
continue;
}
if ((lamebus->ls_slotsinuse & mask) == 0) {
/*
* No device driver is using this slot.
*/
duds++;
duds_this_time++;
continue;
}
if (lamebus->ls_irqfuncs[slot]==NULL) {
/*
* The device driver hasn't installed an interrupt
* handler.
*/
duds++;
duds_this_time++;
continue;
}
if (lamebus->ls_irqfuncs[slot] == NULL) {
/*
* The device driver hasn't installed an interrupt
* handler.
*/
duds++;
duds_this_time++;
continue;
}
/*
* Call the interrupt handler. Release the spinlock
* while we do so, in case other CPUs are handling
* interrupts on other devices.
*/
handler = lamebus->ls_irqfuncs[slot];
data = lamebus->ls_devdata[slot];
spinlock_release(&lamebus->ls_lock);
/*
* Call the interrupt handler. Release the spinlock
* while we do so, in case other CPUs are handling
* interrupts on other devices.
*/
handler = lamebus->ls_irqfuncs[slot];
data = lamebus->ls_devdata[slot];
spinlock_release(&lamebus->ls_lock);
handler(data);
handler(data);
spinlock_acquire(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
/*
* Reload the mask of pending IRQs - if we just called
* hardclock, we might not have come back to this
* context for some time, and it might have changed.
*/
/*
* Reload the mask of pending IRQs - if we just called
* hardclock, we might not have come back to this
* context for some time, and it might have changed.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
}
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
}
/*
* If we get interrupts for a slot with no driver or no
* interrupt handler, it's fairly serious. Because LAMEbus
* uses level-triggered interrupts, if we don't shut off the
* condition, we'll keep getting interrupted continuously and
* the system will make no progress. But we don't know how to
* do that if there's no driver or no interrupt handler.
*
* So, if we get too many dud interrupts, panic, since it's
* better to panic and reset than to hang.
*
* If we get through here without seeing any duds this time,
* the condition, whatever it was, has gone away. It might be
* some stupid device we don't have a driver for, or it might
* have been an electrical transient. In any case, warn and
* clear the dud count.
*/
/*
* If we get interrupts for a slot with no driver or no
* interrupt handler, it's fairly serious. Because LAMEbus
* uses level-triggered interrupts, if we don't shut off the
* condition, we'll keep getting interrupted continuously and
* the system will make no progress. But we don't know how to
* do that if there's no driver or no interrupt handler.
*
* So, if we get too many dud interrupts, panic, since it's
* better to panic and reset than to hang.
*
* If we get through here without seeing any duds this time,
* the condition, whatever it was, has gone away. It might be
* some stupid device we don't have a driver for, or it might
* have been an electrical transient. In any case, warn and
* clear the dud count.
*/
if (duds_this_time == 0 && duds > 0) {
kprintf("lamebus: %d dud interrupts\n", duds);
duds = 0;
}
if (duds_this_time == 0 && duds > 0) {
kprintf("lamebus: %d dud interrupts\n", duds);
duds = 0;
}
if (duds > 10000) {
panic("lamebus: too many (%d) dud interrupts\n", duds);
}
if (duds > 10000) {
panic("lamebus: too many (%d) dud interrupts\n", duds);
}
/* Unlock the softc */
spinlock_release(&lamebus->ls_lock);
/* Unlock the softc */
spinlock_release(&lamebus->ls_lock);
}
/*
* Have the bus controller power the system off.
*/
void
lamebus_poweroff(struct lamebus_softc *lamebus)
{
/*
* Write 0 to the power register to shut the system off.
*/
void lamebus_poweroff(struct lamebus_softc *lamebus) {
/*
* Write 0 to the power register to shut the system off.
*/
cpu_irqoff();
write_ctl_register(lamebus, CTLREG_PWR, 0);
cpu_irqoff();
write_ctl_register(lamebus, CTLREG_PWR, 0);
/* The power doesn't go off instantly... so halt the cpu. */
cpu_halt();
/* The power doesn't go off instantly... so halt the cpu. */
cpu_halt();
}
/*
* Ask the bus controller how much memory we have.
*/
uint32_t
lamebus_ramsize(void)
{
/*
* Note that this has to work before bus initialization.
* On machines where lamebus_read_register doesn't work
* before bus initialization, this function can't be used
* for initial RAM size lookup.
*/
uint32_t lamebus_ramsize(void) {
/*
* Note that this has to work before bus initialization.
* On machines where lamebus_read_register doesn't work
* before bus initialization, this function can't be used
* for initial RAM size lookup.
*/
return read_ctl_register(NULL, CTLREG_RAMSZ);
return read_ctl_register(NULL, CTLREG_RAMSZ);
}
/*
* Turn on or off the interprocessor interrupt line for a given CPU.
*/
void
lamebus_assert_ipi(struct lamebus_softc *lamebus, struct cpu *target)
{
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number,
CTLCPU_CIPI, 1);
void lamebus_assert_ipi(struct lamebus_softc *lamebus, struct cpu *target) {
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number, CTLCPU_CIPI, 1);
}
void
lamebus_clear_ipi(struct lamebus_softc *lamebus, struct cpu *target)
{
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number,
CTLCPU_CIPI, 0);
void lamebus_clear_ipi(struct lamebus_softc *lamebus, struct cpu *target) {
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number, CTLCPU_CIPI, 0);
}
/*
* Initial setup.
* Should be called from mainbus_bootstrap().
*/
struct lamebus_softc *
lamebus_init(void)
{
struct lamebus_softc *lamebus;
int i;
struct lamebus_softc *lamebus_init(void) {
struct lamebus_softc *lamebus;
int i;
/* Allocate space for lamebus data */
lamebus = kmalloc(sizeof(struct lamebus_softc));
if (lamebus==NULL) {
panic("lamebus_init: Out of memory\n");
}
/* Allocate space for lamebus data */
lamebus = kmalloc(sizeof(struct lamebus_softc));
if (lamebus == NULL) {
panic("lamebus_init: Out of memory\n");
}
spinlock_init(&lamebus->ls_lock);
spinlock_init(&lamebus->ls_lock);
/*
* Initialize the LAMEbus data structure.
*/
lamebus->ls_slotsinuse = 1 << LB_CONTROLLER_SLOT;
/*
* Initialize the LAMEbus data structure.
*/
lamebus->ls_slotsinuse = 1 << LB_CONTROLLER_SLOT;
for (i=0; i<LB_NSLOTS; i++) {
lamebus->ls_devdata[i] = NULL;
lamebus->ls_irqfuncs[i] = NULL;
}
for (i = 0; i < LB_NSLOTS; i++) {
lamebus->ls_devdata[i] = NULL;
lamebus->ls_irqfuncs[i] = NULL;
}
lamebus->ls_uniprocessor = 0;
lamebus->ls_uniprocessor = 0;
return lamebus;
return lamebus;
}

View File

@@ -39,39 +39,38 @@
* Machine-independent definitions.
*/
/* Vendors */
#define LB_VENDOR_CS161 1
#define LB_VENDOR_CS161 1
/* CS161 devices */
#define LBCS161_UPBUSCTL 1
#define LBCS161_TIMER 2
#define LBCS161_DISK 3
#define LBCS161_SERIAL 4
#define LBCS161_SCREEN 5
#define LBCS161_NET 6
#define LBCS161_EMUFS 7
#define LBCS161_TRACE 8
#define LBCS161_RANDOM 9
#define LBCS161_MPBUSCTL 10
#define LBCS161_UPBUSCTL 1
#define LBCS161_TIMER 2
#define LBCS161_DISK 3
#define LBCS161_SERIAL 4
#define LBCS161_SCREEN 5
#define LBCS161_NET 6
#define LBCS161_EMUFS 7
#define LBCS161_TRACE 8
#define LBCS161_RANDOM 9
#define LBCS161_MPBUSCTL 10
/* LAMEbus controller always goes in slot 31 */
#define LB_CONTROLLER_SLOT 31
#define LB_CONTROLLER_SLOT 31
/* Number of slots */
#define LB_NSLOTS 32
#define LB_NSLOTS 32
/* LAMEbus controller per-slot config space */
#define LB_CONFIG_SIZE 1024
#define LB_CONFIG_SIZE 1024
/* LAMEbus controller per-cpu control space */
#define LB_CTLCPU_SIZE 1024
#define LB_CTLCPU_SIZE 1024
/* LAMEbus controller slot offset to per-cpu control space */
#define LB_CTLCPU_OFFSET 32768
#define LB_CTLCPU_OFFSET 32768
/* LAMEbus mapping size per slot */
#define LB_SLOT_SIZE 65536
#define LB_SLOT_SIZE 65536
/* Pointer to kind of function called on interrupt */
typedef void (*lb_irqfunc)(void *devdata);
@@ -80,15 +79,15 @@ typedef void (*lb_irqfunc)(void *devdata);
* Driver data
*/
struct lamebus_softc {
struct spinlock ls_lock;
struct spinlock ls_lock;
/* Accessed from interrupts; synchronized with ls_lock */
uint32_t ls_slotsinuse;
void *ls_devdata[LB_NSLOTS];
lb_irqfunc ls_irqfuncs[LB_NSLOTS];
/* Accessed from interrupts; synchronized with ls_lock */
uint32_t ls_slotsinuse;
void *ls_devdata[LB_NSLOTS];
lb_irqfunc ls_irqfuncs[LB_NSLOTS];
/* Read-only once set early in boot */
unsigned ls_uniprocessor;
/* Read-only once set early in boot */
unsigned ls_uniprocessor;
};
/*
@@ -113,9 +112,8 @@ void lamebus_start_cpus(struct lamebus_softc *lamebus);
*
* Returns a slot number (0-31) or -1 if no such device is found.
*/
int lamebus_probe(struct lamebus_softc *,
uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret);
int lamebus_probe(struct lamebus_softc *, uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret);
/*
* Mark a slot in-use (that is, has a device driver attached to it),
@@ -128,9 +126,8 @@ void lamebus_unmark(struct lamebus_softc *, int slot);
/*
* Attach to an interrupt.
*/
void lamebus_attach_interrupt(struct lamebus_softc *, int slot,
void *devdata,
void (*irqfunc)(void *devdata));
void lamebus_attach_interrupt(struct lamebus_softc *, int slot, void *devdata,
void (*irqfunc)(void *devdata));
/*
* Detach from interrupt.
*/
@@ -168,15 +165,13 @@ void lamebus_clear_ipi(struct lamebus_softc *, struct cpu *targetcpu);
* (Machine dependent.)
*/
uint32_t lamebus_read_register(struct lamebus_softc *, int slot,
uint32_t offset);
void lamebus_write_register(struct lamebus_softc *, int slot,
uint32_t offset, uint32_t val);
uint32_t offset);
void lamebus_write_register(struct lamebus_softc *, int slot, uint32_t offset,
uint32_t val);
/*
* Map a buffer that starts at offset OFFSET within slot SLOT.
*/
void *lamebus_map_area(struct lamebus_softc *, int slot,
uint32_t offset);
void *lamebus_map_area(struct lamebus_softc *, int slot, uint32_t offset);
#endif /* _LAMEBUS_H_ */

View File

@@ -43,68 +43,60 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LHD_REG_NSECT 0 /* Number of sectors */
#define LHD_REG_STAT 4 /* Status */
#define LHD_REG_SECT 8 /* Sector for I/O */
#define LHD_REG_RPM 12 /* Disk rotation speed (revs per minute) */
#define LHD_REG_NSECT 0 /* Number of sectors */
#define LHD_REG_STAT 4 /* Status */
#define LHD_REG_SECT 8 /* Sector for I/O */
#define LHD_REG_RPM 12 /* Disk rotation speed (revs per minute) */
/* Status codes */
#define LHD_IDLE 0 /* Device idle */
#define LHD_WORKING 1 /* Operation in progress */
#define LHD_OK 4 /* Operation succeeded */
#define LHD_INVSECT 12 /* Invalid sector requested */
#define LHD_MEDIA 20 /* Media error */
#define LHD_ISWRITE 2 /* OR with above: I/O is a write */
#define LHD_STATEMASK 0x1d /* mask for masking out LHD_ISWRITE */
#define LHD_IDLE 0 /* Device idle */
#define LHD_WORKING 1 /* Operation in progress */
#define LHD_OK 4 /* Operation succeeded */
#define LHD_INVSECT 12 /* Invalid sector requested */
#define LHD_MEDIA 20 /* Media error */
#define LHD_ISWRITE 2 /* OR with above: I/O is a write */
#define LHD_STATEMASK 0x1d /* mask for masking out LHD_ISWRITE */
/* Buffer (offset within slot) */
#define LHD_BUFFER 32768
#define LHD_BUFFER 32768
/*
* Shortcut for reading a register.
*/
static
inline
uint32_t lhd_rdreg(struct lhd_softc *lh, uint32_t reg)
{
return bus_read_register(lh->lh_busdata, lh->lh_buspos, reg);
static inline uint32_t lhd_rdreg(struct lhd_softc *lh, uint32_t reg) {
return bus_read_register(lh->lh_busdata, lh->lh_buspos, reg);
}
/*
* Shortcut for writing a register.
*/
static
inline
void lhd_wreg(struct lhd_softc *lh, uint32_t reg, uint32_t val)
{
bus_write_register(lh->lh_busdata, lh->lh_buspos, reg, val);
static inline void lhd_wreg(struct lhd_softc *lh, uint32_t reg, uint32_t val) {
bus_write_register(lh->lh_busdata, lh->lh_buspos, reg, val);
}
/*
* Convert a result code from the hardware to an errno value.
*/
static
int lhd_code_to_errno(struct lhd_softc *lh, int code)
{
switch (code & LHD_STATEMASK) {
case LHD_OK: return 0;
case LHD_INVSECT: return EINVAL;
case LHD_MEDIA: return EIO;
}
kprintf("lhd%d: Unknown result code %d\n", lh->lh_unit, code);
return EAGAIN;
static int lhd_code_to_errno(struct lhd_softc *lh, int code) {
switch (code & LHD_STATEMASK) {
case LHD_OK:
return 0;
case LHD_INVSECT:
return EINVAL;
case LHD_MEDIA:
return EIO;
}
kprintf("lhd%d: Unknown result code %d\n", lh->lh_unit, code);
return EAGAIN;
}
/*
* Record that an I/O has completed: save the result and poke the
* completion semaphore.
*/
static
void
lhd_iodone(struct lhd_softc *lh, int err)
{
lh->lh_result = err;
V(lh->lh_done);
static void lhd_iodone(struct lhd_softc *lh, int err) {
lh->lh_result = err;
V(lh->lh_done);
}
/*
@@ -112,57 +104,49 @@ lhd_iodone(struct lhd_softc *lh, int err)
* Read the status register; if an operation finished, clear the status
* register and report completion.
*/
void
lhd_irq(void *vlh)
{
struct lhd_softc *lh = vlh;
uint32_t val;
void lhd_irq(void *vlh) {
struct lhd_softc *lh = vlh;
uint32_t val;
val = lhd_rdreg(lh, LHD_REG_STAT);
val = lhd_rdreg(lh, LHD_REG_STAT);
switch (val & LHD_STATEMASK) {
case LHD_IDLE:
case LHD_WORKING:
break;
case LHD_OK:
case LHD_INVSECT:
case LHD_MEDIA:
lhd_wreg(lh, LHD_REG_STAT, 0);
lhd_iodone(lh, lhd_code_to_errno(lh, val));
break;
}
switch (val & LHD_STATEMASK) {
case LHD_IDLE:
case LHD_WORKING:
break;
case LHD_OK:
case LHD_INVSECT:
case LHD_MEDIA:
lhd_wreg(lh, LHD_REG_STAT, 0);
lhd_iodone(lh, lhd_code_to_errno(lh, val));
break;
}
}
/*
* Function called when we are open()'d.
*/
static
int
lhd_eachopen(struct device *d, int openflags)
{
/*
* Don't need to do anything.
*/
(void)d;
(void)openflags;
static int lhd_eachopen(struct device *d, int openflags) {
/*
* Don't need to do anything.
*/
(void)d;
(void)openflags;
return 0;
return 0;
}
/*
* Function for handling ioctls.
*/
static
int
lhd_ioctl(struct device *d, int op, userptr_t data)
{
/*
* We don't support any ioctls.
*/
(void)d;
(void)op;
(void)data;
return EIOCTL;
static int lhd_ioctl(struct device *d, int op, userptr_t data) {
/*
* We don't support any ioctls.
*/
(void)d;
(void)op;
(void)data;
return EIOCTL;
}
#if 0
@@ -182,127 +166,122 @@ lhd_reset(struct lhd_softc *lh)
/*
* I/O function (for both reads and writes)
*/
static
int
lhd_io(struct device *d, struct uio *uio)
{
struct lhd_softc *lh = d->d_data;
static int lhd_io(struct device *d, struct uio *uio) {
struct lhd_softc *lh = d->d_data;
uint32_t sector = uio->uio_offset / LHD_SECTSIZE;
uint32_t sectoff = uio->uio_offset % LHD_SECTSIZE;
uint32_t len = uio->uio_resid / LHD_SECTSIZE;
uint32_t lenoff = uio->uio_resid % LHD_SECTSIZE;
uint32_t i;
uint32_t statval = LHD_WORKING;
int result;
uint32_t sector = uio->uio_offset / LHD_SECTSIZE;
uint32_t sectoff = uio->uio_offset % LHD_SECTSIZE;
uint32_t len = uio->uio_resid / LHD_SECTSIZE;
uint32_t lenoff = uio->uio_resid % LHD_SECTSIZE;
uint32_t i;
uint32_t statval = LHD_WORKING;
int result;
/* Don't allow I/O that isn't sector-aligned. */
if (sectoff != 0 || lenoff != 0) {
return EINVAL;
}
/* Don't allow I/O that isn't sector-aligned. */
if (sectoff != 0 || lenoff != 0) {
return EINVAL;
}
/* Don't allow I/O past the end of the disk. */
/* XXX this check can overflow */
if (sector+len > lh->lh_dev.d_blocks) {
return EINVAL;
}
/* Don't allow I/O past the end of the disk. */
/* XXX this check can overflow */
if (sector + len > lh->lh_dev.d_blocks) {
return EINVAL;
}
/* Set up the value to write into the status register. */
if (uio->uio_rw==UIO_WRITE) {
statval |= LHD_ISWRITE;
}
/* Set up the value to write into the status register. */
if (uio->uio_rw == UIO_WRITE) {
statval |= LHD_ISWRITE;
}
/* Loop over all the sectors we were asked to do. */
for (i=0; i<len; i++) {
/* Loop over all the sectors we were asked to do. */
for (i = 0; i < len; i++) {
/* Wait until nobody else is using the device. */
P(lh->lh_clear);
/* Wait until nobody else is using the device. */
P(lh->lh_clear);
/*
* Are we writing? If so, transfer the data to the
* on-card buffer.
*/
if (uio->uio_rw == UIO_WRITE) {
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
membar_store_store();
if (result) {
V(lh->lh_clear);
return result;
}
}
/*
* Are we writing? If so, transfer the data to the
* on-card buffer.
*/
if (uio->uio_rw == UIO_WRITE) {
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
membar_store_store();
if (result) {
V(lh->lh_clear);
return result;
}
}
/* Tell it what sector we want... */
lhd_wreg(lh, LHD_REG_SECT, sector+i);
/* Tell it what sector we want... */
lhd_wreg(lh, LHD_REG_SECT, sector + i);
/* and start the operation. */
lhd_wreg(lh, LHD_REG_STAT, statval);
/* and start the operation. */
lhd_wreg(lh, LHD_REG_STAT, statval);
/* Now wait until the interrupt handler tells us we're done. */
P(lh->lh_done);
/* Now wait until the interrupt handler tells us we're done. */
P(lh->lh_done);
/* Get the result value saved by the interrupt handler. */
result = lh->lh_result;
/* Get the result value saved by the interrupt handler. */
result = lh->lh_result;
/*
* Are we reading? If so, and if we succeeded,
* transfer the data out of the on-card buffer.
*/
if (result==0 && uio->uio_rw==UIO_READ) {
membar_load_load();
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
}
/*
* Are we reading? If so, and if we succeeded,
* transfer the data out of the on-card buffer.
*/
if (result == 0 && uio->uio_rw == UIO_READ) {
membar_load_load();
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
}
/* Tell another thread it's cleared to go ahead. */
V(lh->lh_clear);
/* Tell another thread it's cleared to go ahead. */
V(lh->lh_clear);
/* If we failed, return the error. */
if (result) {
return result;
}
}
/* If we failed, return the error. */
if (result) {
return result;
}
}
return 0;
return 0;
}
static const struct device_ops lhd_devops = {
.devop_eachopen = lhd_eachopen,
.devop_io = lhd_io,
.devop_ioctl = lhd_ioctl,
.devop_eachopen = lhd_eachopen,
.devop_io = lhd_io,
.devop_ioctl = lhd_ioctl,
};
/*
* Setup routine called by autoconf.c when an lhd is found.
*/
int
config_lhd(struct lhd_softc *lh, int lhdno)
{
char name[32];
int config_lhd(struct lhd_softc *lh, int lhdno) {
char name[32];
/* Figure out what our name is. */
snprintf(name, sizeof(name), "lhd%d", lhdno);
/* Figure out what our name is. */
snprintf(name, sizeof(name), "lhd%d", lhdno);
/* Get a pointer to the on-chip buffer. */
lh->lh_buf = bus_map_area(lh->lh_busdata, lh->lh_buspos, LHD_BUFFER);
/* Get a pointer to the on-chip buffer. */
lh->lh_buf = bus_map_area(lh->lh_busdata, lh->lh_buspos, LHD_BUFFER);
/* Create the semaphores. */
lh->lh_clear = sem_create("lhd-clear", 1);
if (lh->lh_clear == NULL) {
return ENOMEM;
}
lh->lh_done = sem_create("lhd-done", 0);
if (lh->lh_done == NULL) {
sem_destroy(lh->lh_clear);
lh->lh_clear = NULL;
return ENOMEM;
}
/* Create the semaphores. */
lh->lh_clear = sem_create("lhd-clear", 1);
if (lh->lh_clear == NULL) {
return ENOMEM;
}
lh->lh_done = sem_create("lhd-done", 0);
if (lh->lh_done == NULL) {
sem_destroy(lh->lh_clear);
lh->lh_clear = NULL;
return ENOMEM;
}
/* Set up the VFS device structure. */
lh->lh_dev.d_ops = &lhd_devops;
lh->lh_dev.d_blocks = bus_read_register(lh->lh_busdata, lh->lh_buspos,
LHD_REG_NSECT);
lh->lh_dev.d_blocksize = LHD_SECTSIZE;
lh->lh_dev.d_data = lh;
/* Set up the VFS device structure. */
lh->lh_dev.d_ops = &lhd_devops;
lh->lh_dev.d_blocks =
bus_read_register(lh->lh_busdata, lh->lh_buspos, LHD_REG_NSECT);
lh->lh_dev.d_blocksize = LHD_SECTSIZE;
lh->lh_dev.d_data = lh;
/* Add the VFS device structure to the VFS device list. */
return vfs_adddev(name, &lh->lh_dev, 1);
/* Add the VFS device structure to the VFS device list. */
return vfs_adddev(name, &lh->lh_dev, 1);
}

View File

@@ -35,30 +35,30 @@
/*
* Our sector size
*/
#define LHD_SECTSIZE 512
#define LHD_SECTSIZE 512
/*
* Hardware device data associated with lhd (LAMEbus hard disk)
*/
struct lhd_softc {
/* Initialized by lower-level attach code */
void *lh_busdata; /* The bus we're on */
uint32_t lh_buspos; /* Our slot on that bus */
int lh_unit; /* What number lhd we are */
/* Initialized by lower-level attach code */
void *lh_busdata; /* The bus we're on */
uint32_t lh_buspos; /* Our slot on that bus */
int lh_unit; /* What number lhd we are */
/*
* Initialized by config_lhd
*/
/*
* Initialized by config_lhd
*/
void *lh_buf; /* Pointer to on-card I/O buffer */
int lh_result; /* Result from I/O operation */
struct semaphore *lh_clear; /* Synchronization */
struct semaphore *lh_done;
void *lh_buf; /* Pointer to on-card I/O buffer */
int lh_result; /* Result from I/O operation */
struct semaphore *lh_clear; /* Synchronization */
struct semaphore *lh_done;
struct device lh_dev; /* VFS device structure */
struct device lh_dev; /* VFS device structure */
};
/* Functions called by lower-level drivers */
void lhd_irq(/*struct lhd_softc*/ void *); /* Interrupt handler */
void lhd_irq(/*struct lhd_softc*/ void *); /* Interrupt handler */
#endif /* _LAMEBUS_LHD_H_ */

View File

@@ -37,33 +37,31 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 2
#define LOW_VERSION 2
struct lhd_softc *
attach_lhd_to_lamebus(int lhdno, struct lamebus_softc *sc)
{
struct lhd_softc *lh;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_DISK,
LOW_VERSION, NULL);
if (slot < 0) {
/* None found */
return NULL;
}
struct lhd_softc *attach_lhd_to_lamebus(int lhdno, struct lamebus_softc *sc) {
struct lhd_softc *lh;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_DISK, LOW_VERSION, NULL);
if (slot < 0) {
/* None found */
return NULL;
}
lh = kmalloc(sizeof(struct lhd_softc));
if (lh==NULL) {
/* Out of memory */
return NULL;
}
lh = kmalloc(sizeof(struct lhd_softc));
if (lh == NULL) {
/* Out of memory */
return NULL;
}
/* Record what the lhd is attached to */
lh->lh_busdata = sc;
lh->lh_buspos = slot;
lh->lh_unit = lhdno;
/* Record what the lhd is attached to */
lh->lh_busdata = sc;
lh->lh_buspos = slot;
lh->lh_unit = lhdno;
/* Mark the slot in use and collect interrupts */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lh, lhd_irq);
/* Mark the slot in use and collect interrupts */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lh, lhd_irq);
return lh;
return lh;
}

View File

@@ -33,14 +33,10 @@
/*#include <lamebus/lnet.h>*/ /* not yet */
#include "autoconf.h"
int
config_lnet(struct lnet_softc *sc, int lnetno)
{
(void)sc;
int config_lnet(struct lnet_softc *sc, int lnetno) {
(void)sc;
kprintf("lnet%d: No network support in system\n", lnetno);
kprintf("lnet%d: No network support in system\n", lnetno);
return ENODEV;
return ENODEV;
}

View File

@@ -33,20 +33,19 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Highest revision we support */
#define HIGH_VERSION 1
#define HIGH_VERSION 1
struct lnet_softc *
attach_lnet_to_lamebus(int lnetno, struct lamebus_softc *sc)
{
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_NET,
LOW_VERSION, HIGH_VERSION);
if (slot < 0) {
return NULL;
}
struct lnet_softc *attach_lnet_to_lamebus(int lnetno,
struct lamebus_softc *sc) {
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_NET, LOW_VERSION,
HIGH_VERSION);
if (slot < 0) {
return NULL;
}
kprintf("lnet%d: No network support in system\n", lnetno);
kprintf("lnet%d: No network support in system\n", lnetno);
return NULL;
return NULL;
}

View File

@@ -38,48 +38,39 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LR_REG_RAND 0 /* random register */
#define LR_REG_RAND 0 /* random register */
/* Constants */
#define LR_RANDMAX 0xffffffff
#define LR_RANDMAX 0xffffffff
int
config_lrandom(struct lrandom_softc *lr, int lrandomno)
{
(void)lrandomno;
(void)lr;
return 0;
int config_lrandom(struct lrandom_softc *lr, int lrandomno) {
(void)lrandomno;
(void)lr;
return 0;
}
uint32_t
lrandom_random(void *devdata)
{
struct lrandom_softc *lr = devdata;
return bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
uint32_t lrandom_random(void *devdata) {
struct lrandom_softc *lr = devdata;
return bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
}
uint32_t
lrandom_randmax(void *devdata)
{
(void)devdata;
return LR_RANDMAX;
uint32_t lrandom_randmax(void *devdata) {
(void)devdata;
return LR_RANDMAX;
}
int
lrandom_read(void *devdata, struct uio *uio)
{
struct lrandom_softc *lr = devdata;
uint32_t val;
int result;
int lrandom_read(void *devdata, struct uio *uio) {
struct lrandom_softc *lr = devdata;
uint32_t val;
int result;
while (uio->uio_resid > 0) {
val = bus_read_register(lr->lr_bus, lr->lr_buspos,
LR_REG_RAND);
result = uiomove(&val, sizeof(val), uio);
if (result) {
return result;
}
}
while (uio->uio_resid > 0) {
val = bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
result = uiomove(&val, sizeof(val), uio);
if (result) {
return result;
}
}
return 0;
return 0;
}

View File

@@ -33,9 +33,9 @@
struct uio;
struct lrandom_softc {
/* Initialized by lower-level attach routine */
void *lr_bus;
uint32_t lr_buspos;
/* Initialized by lower-level attach routine */
void *lr_bus;
uint32_t lr_buspos;
};
/* Functions called by higher-level drivers */

View File

@@ -34,29 +34,28 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct lrandom_softc *
attach_lrandom_to_lamebus(int lrandomno, struct lamebus_softc *sc)
{
struct lrandom_softc *lr;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_RANDOM,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct lrandom_softc *attach_lrandom_to_lamebus(int lrandomno,
struct lamebus_softc *sc) {
struct lrandom_softc *lr;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_RANDOM, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
lr = kmalloc(sizeof(struct lrandom_softc));
if (lr==NULL) {
return NULL;
}
lr = kmalloc(sizeof(struct lrandom_softc));
if (lr == NULL) {
return NULL;
}
(void)lrandomno; // unused
(void)lrandomno; // unused
lr->lr_bus = sc;
lr->lr_buspos = slot;
lr->lr_bus = sc;
lr->lr_buspos = slot;
lamebus_mark(sc, slot);
lamebus_mark(sc, slot);
return lr;
return lr;
}

View File

@@ -41,37 +41,29 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LSCR_REG_POSN 0 /* Cursor position */
#define LSCR_REG_SIZE 4 /* Display size */
#define LSCR_REG_CHAR 8 /* Character in */
#define LSCR_REG_RIRQ 12 /* Read interrupt status */
#define LSCR_REG_POSN 0 /* Cursor position */
#define LSCR_REG_SIZE 4 /* Display size */
#define LSCR_REG_CHAR 8 /* Character in */
#define LSCR_REG_RIRQ 12 /* Read interrupt status */
/* Bits in the IRQ registers */
#define LSCR_IRQ_ENABLE 1
#define LSCR_IRQ_ACTIVE 2
#define LSCR_IRQ_ENABLE 1
#define LSCR_IRQ_ACTIVE 2
/* Offset within slot of screen buffer */
#define LSCR_SCREEN 32768
#define LSCR_SCREEN 32768
/* Convert a 32-bit X/Y pair to X and Y coordinates. */
static
inline
void
splitxy(uint32_t xy, unsigned *x, unsigned *y)
{
*x = xy >> 16;
*y = xy & 0xffff;
static inline void splitxy(uint32_t xy, unsigned *x, unsigned *y) {
*x = xy >> 16;
*y = xy & 0xffff;
}
/* Convert X and Y coordinates to a single 32-bit value. */
static
inline
uint32_t
mergexy(unsigned x, unsigned y)
{
uint32_t val = x;
static inline uint32_t mergexy(unsigned x, unsigned y) {
uint32_t val = x;
return (val << 16) | y;
return (val << 16) | y;
}
////////////////////////////////////////////////////////////
@@ -79,29 +71,25 @@ mergexy(unsigned x, unsigned y)
/*
* Interrupt handler.
*/
void
lscreen_irq(void *vsc)
{
struct lscreen_softc *sc = vsc;
uint32_t ch, x;
void lscreen_irq(void *vsc) {
struct lscreen_softc *sc = vsc;
uint32_t ch, x;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);
if (x & LSCR_IRQ_ACTIVE) {
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_CHAR);
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);
if (x & LSCR_IRQ_ACTIVE) {
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_CHAR);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ,
LSCR_IRQ_ENABLE);
spinlock_release(&sc->ls_lock);
if (sc->ls_input) {
sc->ls_input(sc->ls_devdata, ch);
}
}
else {
spinlock_release(&sc->ls_lock);
}
spinlock_release(&sc->ls_lock);
if (sc->ls_input) {
sc->ls_input(sc->ls_devdata, ch);
}
} else {
spinlock_release(&sc->ls_lock);
}
}
////////////////////////////////////////////////////////////
@@ -109,74 +97,68 @@ lscreen_irq(void *vsc)
/*
* Handle a newline on the screen.
*/
static
void
lscreen_newline(struct lscreen_softc *sc)
{
if (sc->ls_cy >= sc->ls_height-1) {
/*
* Scroll
*/
static void lscreen_newline(struct lscreen_softc *sc) {
if (sc->ls_cy >= sc->ls_height - 1) {
/*
* Scroll
*/
memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,
sc->ls_width * (sc->ls_height-1));
bzero(sc->ls_screen + sc->ls_width * (sc->ls_height-1),
sc->ls_width);
}
else {
sc->ls_cy++;
}
sc->ls_cx=0;
memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,
sc->ls_width * (sc->ls_height - 1));
bzero(sc->ls_screen + sc->ls_width * (sc->ls_height - 1), sc->ls_width);
} else {
sc->ls_cy++;
}
sc->ls_cx = 0;
}
/*
* Handle a printable character being written to the screen.
*/
static
void
lscreen_char(struct lscreen_softc *sc, int ch)
{
if (sc->ls_cx >= sc->ls_width) {
lscreen_newline(sc);
}
static void lscreen_char(struct lscreen_softc *sc, int ch) {
if (sc->ls_cx >= sc->ls_width) {
lscreen_newline(sc);
}
sc->ls_screen[sc->ls_cy*sc->ls_width + sc->ls_cx] = ch;
sc->ls_cx++;
sc->ls_screen[sc->ls_cy * sc->ls_width + sc->ls_cx] = ch;
sc->ls_cx++;
}
/*
* Send a character to the screen.
* This should probably know about backspace and tab.
*/
void
lscreen_write(void *vsc, int ch)
{
struct lscreen_softc *sc = vsc;
int ccx, ccy;
void lscreen_write(void *vsc, int ch) {
struct lscreen_softc *sc = vsc;
int ccx, ccy;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
switch (ch) {
case '\n': lscreen_newline(sc); break;
default: lscreen_char(sc, ch); break;
}
switch (ch) {
case '\n':
lscreen_newline(sc);
break;
default:
lscreen_char(sc, ch);
break;
}
/*
* ccx/ccy = corrected cursor position
* (The cursor marks the next space text will appear in. But
* at the very end of the line, it should not move off the edge.)
*/
ccx = sc->ls_cx;
ccy = sc->ls_cy;
if (ccx==sc->ls_width) {
ccx--;
}
/*
* ccx/ccy = corrected cursor position
* (The cursor marks the next space text will appear in. But
* at the very end of the line, it should not move off the edge.)
*/
ccx = sc->ls_cx;
ccy = sc->ls_cy;
if (ccx == sc->ls_width) {
ccx--;
}
/* Set the cursor position */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_POSN, mergexy(ccx, ccy));
/* Set the cursor position */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_POSN,
mergexy(ccx, ccy));
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
////////////////////////////////////////////////////////////
@@ -184,42 +166,36 @@ lscreen_write(void *vsc, int ch)
/*
* Setup routine called by autoconf.c when an lscreen is found.
*/
int
config_lscreen(struct lscreen_softc *sc, int lscreenno)
{
uint32_t val;
int config_lscreen(struct lscreen_softc *sc, int lscreenno) {
uint32_t val;
(void)lscreenno;
(void)lscreenno;
spinlock_init(&sc->ls_lock);
spinlock_init(&sc->ls_lock);
/*
* Enable interrupting.
*/
/*
* Enable interrupting.
*/
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ,
LSCR_IRQ_ENABLE);
/*
* Get screen size.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_SIZE);
splitxy(val, &sc->ls_width, &sc->ls_height);
/*
* Get screen size.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_SIZE);
splitxy(val, &sc->ls_width, &sc->ls_height);
/*
* Get cursor position.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_POSN);
splitxy(val, &sc->ls_cx, &sc->ls_cy);
/*
* Get cursor position.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_POSN);
splitxy(val, &sc->ls_cx, &sc->ls_cy);
/*
* Get a pointer to the memory-mapped screen area.
*/
sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos,
LSCR_SCREEN);
/*
* Get a pointer to the memory-mapped screen area.
*/
sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos, LSCR_SCREEN);
return 0;
return 0;
}

View File

@@ -34,24 +34,24 @@
* Hardware device data for memory-mapped fullscreen text console.
*/
struct lscreen_softc {
/* Initialized by config function */
struct spinlock ls_lock; // protects data and device regs
unsigned ls_width, ls_height; // screen size
unsigned ls_cx, ls_cy; // cursor position
char *ls_screen; // memory-mapped screen buffer
/* Initialized by config function */
struct spinlock ls_lock; // protects data and device regs
unsigned ls_width, ls_height; // screen size
unsigned ls_cx, ls_cy; // cursor position
char *ls_screen; // memory-mapped screen buffer
/* Initialized by lower-level attachment function */
void *ls_busdata; // bus we're on
uint32_t ls_buspos; // position on that bus
/* Initialized by lower-level attachment function */
void *ls_busdata; // bus we're on
uint32_t ls_buspos; // position on that bus
/* Initialized by higher-level attachment function */
void *ls_devdata; // data and functions for
void (*ls_start)(void *devdata); // upper device (perhaps
void (*ls_input)(void *devdata, int ch); // console)
/* Initialized by higher-level attachment function */
void *ls_devdata; // data and functions for
void (*ls_start)(void *devdata); // upper device (perhaps
void (*ls_input)(void *devdata, int ch); // console)
};
/* Functions called by lower-level drivers */
void lscreen_irq(/*struct lser_softc*/ void *sc); // interrupt handler
void lscreen_irq(/*struct lser_softc*/ void *sc); // interrupt handler
/* Functions called by higher-level drivers */
void lscreen_write(/*struct lser_softc*/ void *sc, int ch); // output function

View File

@@ -37,34 +37,33 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Highest revision we support */
#define HIGH_VERSION 1
#define HIGH_VERSION 1
struct lscreen_softc *
attach_lscreen_to_lamebus(int lscreenno, struct lamebus_softc *sc)
{
struct lscreen_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SCREEN,
LOW_VERSION, HIGH_VERSION);
if (slot < 0) {
/* Not found */
return NULL;
}
struct lscreen_softc *attach_lscreen_to_lamebus(int lscreenno,
struct lamebus_softc *sc) {
struct lscreen_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SCREEN, LOW_VERSION,
HIGH_VERSION);
if (slot < 0) {
/* Not found */
return NULL;
}
ls = kmalloc(sizeof(struct lscreen_softc));
if (ls==NULL) {
/* Out of memory */
return NULL;
}
ls = kmalloc(sizeof(struct lscreen_softc));
if (ls == NULL) {
/* Out of memory */
return NULL;
}
/* Record what it's attached to */
ls->ls_busdata = sc;
ls->ls_buspos = slot;
/* Record what it's attached to */
ls->ls_busdata = sc;
ls->ls_buspos = slot;
/* Mark the slot in use and hook the interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lscreen_irq);
/* Mark the slot in use and hook the interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lscreen_irq);
return ls;
return ls;
}

View File

@@ -35,158 +35,139 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LSER_REG_CHAR 0 /* Character in/out */
#define LSER_REG_WIRQ 4 /* Write interrupt status */
#define LSER_REG_RIRQ 8 /* Read interrupt status */
#define LSER_REG_CHAR 0 /* Character in/out */
#define LSER_REG_WIRQ 4 /* Write interrupt status */
#define LSER_REG_RIRQ 8 /* Read interrupt status */
/* Bits in the IRQ registers */
#define LSER_IRQ_ENABLE 1
#define LSER_IRQ_ACTIVE 2
#define LSER_IRQ_FORCE 4
#define LSER_IRQ_ENABLE 1
#define LSER_IRQ_ACTIVE 2
#define LSER_IRQ_FORCE 4
void
lser_irq(void *vsc)
{
struct lser_softc *sc = vsc;
uint32_t x;
bool clear_to_write = false;
bool got_a_read = false;
uint32_t ch = 0;
void lser_irq(void *vsc) {
struct lser_softc *sc = vsc;
uint32_t x;
bool clear_to_write = false;
bool got_a_read = false;
uint32_t ch = 0;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
sc->ls_wbusy = 0;
clear_to_write = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
sc->ls_wbusy = 0;
clear_to_write = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_CHAR);
got_a_read = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_RIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR);
got_a_read = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ, x);
}
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
if (clear_to_write && sc->ls_start != NULL) {
sc->ls_start(sc->ls_devdata);
}
if (got_a_read && sc->ls_input != NULL) {
sc->ls_input(sc->ls_devdata, ch);
}
if (clear_to_write && sc->ls_start != NULL) {
sc->ls_start(sc->ls_devdata);
}
if (got_a_read && sc->ls_input != NULL) {
sc->ls_input(sc->ls_devdata, ch);
}
}
void
lser_write(void *vls, int ch)
{
struct lser_softc *ls = vls;
void lser_write(void *vls, int ch) {
struct lser_softc *ls = vls;
spinlock_acquire(&ls->ls_lock);
spinlock_acquire(&ls->ls_lock);
if (ls->ls_wbusy) {
/*
* We're not clear to write.
*
* This should not happen. It's the job of the driver
* attached to us to not write until we call
* ls->ls_start.
*
* (Note: if we're the console, the panic will go to
* lser_writepolled for printing, because we hold a
* spinlock and interrupts are off; it won't recurse.)
*/
panic("lser: Not clear to write\n");
}
ls->ls_wbusy = true;
if (ls->ls_wbusy) {
/*
* We're not clear to write.
*
* This should not happen. It's the job of the driver
* attached to us to not write until we call
* ls->ls_start.
*
* (Note: if we're the console, the panic will go to
* lser_writepolled for printing, because we hold a
* spinlock and interrupts are off; it won't recurse.)
*/
panic("lser: Not clear to write\n");
}
ls->ls_wbusy = true;
bus_write_register(ls->ls_busdata, ls->ls_buspos, LSER_REG_CHAR, ch);
bus_write_register(ls->ls_busdata, ls->ls_buspos, LSER_REG_CHAR, ch);
spinlock_release(&ls->ls_lock);
spinlock_release(&ls->ls_lock);
}
static
void
lser_poll_until_write(struct lser_softc *sc)
{
uint32_t val;
static void lser_poll_until_write(struct lser_softc *sc) {
uint32_t val;
KASSERT(spinlock_do_i_hold(&sc->ls_lock));
KASSERT(spinlock_do_i_hold(&sc->ls_lock));
do {
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ);
}
while ((val & LSER_IRQ_ACTIVE) == 0);
do {
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
} while ((val & LSER_IRQ_ACTIVE) == 0);
}
void
lser_writepolled(void *vsc, int ch)
{
struct lser_softc *sc = vsc;
bool irqpending;
void lser_writepolled(void *vsc, int ch) {
struct lser_softc *sc = vsc;
bool irqpending;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if (sc->ls_wbusy) {
irqpending = true;
lser_poll_until_write(sc);
/* Clear the ready condition, but leave the IRQ asserted */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ,
LSER_IRQ_FORCE|LSER_IRQ_ENABLE);
}
else {
irqpending = false;
/* Clear the interrupt enable bit */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, 0);
}
if (sc->ls_wbusy) {
irqpending = true;
lser_poll_until_write(sc);
/* Clear the ready condition, but leave the IRQ asserted */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_FORCE | LSER_IRQ_ENABLE);
} else {
irqpending = false;
/* Clear the interrupt enable bit */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, 0);
}
/* Send the character. */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR, ch);
/* Send the character. */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR, ch);
/* Wait until it's done. */
lser_poll_until_write(sc);
/* Wait until it's done. */
lser_poll_until_write(sc);
/*
* If there wasn't already an IRQ pending, clear the ready
* condition and turn interruption back on. But if there was,
* leave the register alone, with the ready condition set (and
* the force bit still on); in due course we'll get to the
* interrupt handler and they'll be cleared.
*/
if (!irqpending) {
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, LSER_IRQ_ENABLE);
}
/*
* If there wasn't already an IRQ pending, clear the ready
* condition and turn interruption back on. But if there was,
* leave the register alone, with the ready condition set (and
* the force bit still on); in due course we'll get to the
* interrupt handler and they'll be cleared.
*/
if (!irqpending) {
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_ENABLE);
}
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
int
config_lser(struct lser_softc *sc, int lserno)
{
(void)lserno;
int config_lser(struct lser_softc *sc, int lserno) {
(void)lserno;
/*
* Enable interrupting.
*/
/*
* Enable interrupting.
*/
spinlock_init(&sc->ls_lock);
sc->ls_wbusy = false;
spinlock_init(&sc->ls_lock);
sc->ls_wbusy = false;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_RIRQ, LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ,
LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_ENABLE);
return 0;
return 0;
}

View File

@@ -33,18 +33,18 @@
#include <spinlock.h>
struct lser_softc {
/* Initialized by config function */
struct spinlock ls_lock; /* protects ls_wbusy and device regs */
volatile bool ls_wbusy; /* true if write in progress */
/* Initialized by config function */
struct spinlock ls_lock; /* protects ls_wbusy and device regs */
volatile bool ls_wbusy; /* true if write in progress */
/* Initialized by lower-level attachment function */
void *ls_busdata;
uint32_t ls_buspos;
/* Initialized by lower-level attachment function */
void *ls_busdata;
uint32_t ls_buspos;
/* Initialized by higher-level attachment function */
void *ls_devdata;
void (*ls_start)(void *devdata);
void (*ls_input)(void *devdata, int ch);
/* Initialized by higher-level attachment function */
void *ls_devdata;
void (*ls_start)(void *devdata);
void (*ls_input)(void *devdata, int ch);
};
/* Functions called by lower-level drivers */

View File

@@ -34,30 +34,29 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct lser_softc *
attach_lser_to_lamebus(int lserno, struct lamebus_softc *sc)
{
struct lser_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SERIAL,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct lser_softc *attach_lser_to_lamebus(int lserno,
struct lamebus_softc *sc) {
struct lser_softc *ls;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SERIAL, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
ls = kmalloc(sizeof(struct lser_softc));
if (ls==NULL) {
return NULL;
}
ls = kmalloc(sizeof(struct lser_softc));
if (ls == NULL) {
return NULL;
}
(void)lserno; // unused
(void)lserno; // unused
ls->ls_busdata = sc;
ls->ls_buspos = slot;
ls->ls_busdata = sc;
ls->ls_buspos = slot;
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lser_irq);
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lser_irq);
return ls;
return ls;
}

View File

@@ -39,92 +39,87 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LT_REG_SEC 0 /* time of day: seconds */
#define LT_REG_NSEC 4 /* time of day: nanoseconds */
#define LT_REG_ROE 8 /* Restart On countdown-timer Expiry flag */
#define LT_REG_IRQ 12 /* Interrupt status register */
#define LT_REG_COUNT 16 /* Time for countdown timer (usec) */
#define LT_REG_SPKR 20 /* Beep control */
#define LT_REG_SEC 0 /* time of day: seconds */
#define LT_REG_NSEC 4 /* time of day: nanoseconds */
#define LT_REG_ROE 8 /* Restart On countdown-timer Expiry flag */
#define LT_REG_IRQ 12 /* Interrupt status register */
#define LT_REG_COUNT 16 /* Time for countdown timer (usec) */
#define LT_REG_SPKR 20 /* Beep control */
/* Granularity of countdown timer (usec) */
#define LT_GRANULARITY 1000000
#define LT_GRANULARITY 1000000
static bool havetimerclock;
/*
* Setup routine called by autoconf stuff when an ltimer is found.
*/
int
config_ltimer(struct ltimer_softc *lt, int ltimerno)
{
/*
* Running on System/161 2.x, we always use the processor
* on-chip timer for hardclock and we don't need ltimer as
* hardclock.
*
* Ideally there should be code here that will use an ltimer
* for hardclock if nothing else is available; e.g. if we
* wanted to make OS/161 2.x run on System/161 1.x. However,
* that requires a good bit more infrastructure for handling
* timers than we have and it doesn't seem worthwhile.
*
* It would also require some hacking, because all CPUs need
* to receive timer interrupts. (Exercise: how would you make
* sure all CPUs receive exactly one timer interrupt? Remember
* that LAMEbus uses level-triggered interrupts, so the
* hardware interrupt line will cause repeated interrupts if
* it's not reset on the device; but if it's reset on the
* device before all CPUs manage to see it, those CPUs won't
* be interrupted at all.)
*
* Note that the beep and rtclock devices *do* attach to
* ltimer.
*/
(void)ltimerno;
lt->lt_hardclock = 0;
int config_ltimer(struct ltimer_softc *lt, int ltimerno) {
/*
* Running on System/161 2.x, we always use the processor
* on-chip timer for hardclock and we don't need ltimer as
* hardclock.
*
* Ideally there should be code here that will use an ltimer
* for hardclock if nothing else is available; e.g. if we
* wanted to make OS/161 2.x run on System/161 1.x. However,
* that requires a good bit more infrastructure for handling
* timers than we have and it doesn't seem worthwhile.
*
* It would also require some hacking, because all CPUs need
* to receive timer interrupts. (Exercise: how would you make
* sure all CPUs receive exactly one timer interrupt? Remember
* that LAMEbus uses level-triggered interrupts, so the
* hardware interrupt line will cause repeated interrupts if
* it's not reset on the device; but if it's reset on the
* device before all CPUs manage to see it, those CPUs won't
* be interrupted at all.)
*
* Note that the beep and rtclock devices *do* attach to
* ltimer.
*/
(void)ltimerno;
lt->lt_hardclock = 0;
/*
* We do, however, use ltimer for the timer clock, since the
* on-chip timer can't do that.
*/
if (!havetimerclock) {
havetimerclock = true;
lt->lt_timerclock = 1;
/*
* We do, however, use ltimer for the timer clock, since the
* on-chip timer can't do that.
*/
if (!havetimerclock) {
havetimerclock = true;
lt->lt_timerclock = 1;
/* Wire it to go off once every second. */
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_ROE, 1);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_COUNT,
LT_GRANULARITY);
}
/* Wire it to go off once every second. */
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_ROE, 1);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_COUNT, LT_GRANULARITY);
}
return 0;
return 0;
}
/*
* Interrupt handler.
*/
void
ltimer_irq(void *vlt)
{
struct ltimer_softc *lt = vlt;
uint32_t val;
void ltimer_irq(void *vlt) {
struct ltimer_softc *lt = vlt;
uint32_t val;
val = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_IRQ);
if (val) {
/*
* Only call hardclock if we're responsible for hardclock.
* (Any additional timer devices are unused.)
*/
if (lt->lt_hardclock) {
hardclock();
}
/*
* Likewise for timerclock.
*/
if (lt->lt_timerclock) {
timerclock();
}
}
val = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_IRQ);
if (val) {
/*
* Only call hardclock if we're responsible for hardclock.
* (Any additional timer devices are unused.)
*/
if (lt->lt_hardclock) {
hardclock();
}
/*
* Likewise for timerclock.
*/
if (lt->lt_timerclock) {
timerclock();
}
}
}
/*
@@ -132,12 +127,10 @@ ltimer_irq(void *vlt)
* doesn't matter what value you write. This function is called if
* the beep device is attached to this timer.
*/
void
ltimer_beep(void *vlt)
{
struct ltimer_softc *lt = vlt;
void ltimer_beep(void *vlt) {
struct ltimer_softc *lt = vlt;
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_SPKR, 440);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_SPKR, 440);
}
/*
@@ -145,43 +138,37 @@ ltimer_beep(void *vlt)
* This function gets called if the rtclock device is attached
* to this timer.
*/
void
ltimer_gettime(void *vlt, struct timespec *ts)
{
struct ltimer_softc *lt = vlt;
uint32_t secs1, secs2;
int spl;
void ltimer_gettime(void *vlt, struct timespec *ts) {
struct ltimer_softc *lt = vlt;
uint32_t secs1, secs2;
int spl;
/*
* Read the seconds twice, on either side of the nanoseconds.
* If nsecs is small, use the *later* value of seconds, in case
* the nanoseconds turned over between the time we got the earlier
* value and the time we got nsecs.
*
* Note that the clock in the ltimer device is accurate down
* to a single processor cycle, so this might actually matter
* now and then.
*
* Do it with interrupts off on the current processor to avoid
* getting garbage if we get an interrupt among the register
* reads.
*/
/*
* Read the seconds twice, on either side of the nanoseconds.
* If nsecs is small, use the *later* value of seconds, in case
* the nanoseconds turned over between the time we got the earlier
* value and the time we got nsecs.
*
* Note that the clock in the ltimer device is accurate down
* to a single processor cycle, so this might actually matter
* now and then.
*
* Do it with interrupts off on the current processor to avoid
* getting garbage if we get an interrupt among the register
* reads.
*/
spl = splhigh();
spl = splhigh();
secs1 = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_SEC);
ts->tv_nsec = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_NSEC);
secs2 = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_SEC);
secs1 = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_SEC);
ts->tv_nsec = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_NSEC);
secs2 = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_SEC);
splx(spl);
splx(spl);
if (ts->tv_nsec < 5000000) {
ts->tv_sec = secs2;
}
else {
ts->tv_sec = secs1;
}
if (ts->tv_nsec < 5000000) {
ts->tv_sec = secs2;
} else {
ts->tv_sec = secs1;
}
}

View File

@@ -36,21 +36,21 @@ struct timespec;
* Hardware device data for LAMEbus timer device
*/
struct ltimer_softc {
/* Initialized by config function */
int lt_hardclock; /* true if we should call hardclock() */
int lt_timerclock; /* true if we should call timerclock() */
/* Initialized by config function */
int lt_hardclock; /* true if we should call hardclock() */
int lt_timerclock; /* true if we should call timerclock() */
/* Initialized by lower-level attach routine */
void *lt_bus; /* bus we're on */
uint32_t lt_buspos; /* position (slot) on that bus */
/* Initialized by lower-level attach routine */
void *lt_bus; /* bus we're on */
uint32_t lt_buspos; /* position (slot) on that bus */
};
/* Functions called by lower-level drivers */
void ltimer_irq(/*struct ltimer_softc*/ void *lt); // interrupt handler
void ltimer_irq(/*struct ltimer_softc*/ void *lt); // interrupt handler
/* Functions called by higher-level devices */
void ltimer_beep(/*struct ltimer_softc*/ void *devdata); // for beep device
void ltimer_beep(/*struct ltimer_softc*/ void *devdata); // for beep device
void ltimer_gettime(/*struct ltimer_softc*/ void *devdata,
struct timespec *ts); // for rtclock
struct timespec *ts); // for rtclock
#endif /* _LAMEBUS_LTIMER_H_ */

View File

@@ -37,34 +37,33 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct ltimer_softc *
attach_ltimer_to_lamebus(int ltimerno, struct lamebus_softc *sc)
{
struct ltimer_softc *lt;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TIMER,
LOW_VERSION, NULL);
if (slot < 0) {
/* No ltimer (or no additional ltimer) found */
return NULL;
}
struct ltimer_softc *attach_ltimer_to_lamebus(int ltimerno,
struct lamebus_softc *sc) {
struct ltimer_softc *lt;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TIMER, LOW_VERSION, NULL);
if (slot < 0) {
/* No ltimer (or no additional ltimer) found */
return NULL;
}
lt = kmalloc(sizeof(struct ltimer_softc));
if (lt==NULL) {
/* out of memory */
return NULL;
}
lt = kmalloc(sizeof(struct ltimer_softc));
if (lt == NULL) {
/* out of memory */
return NULL;
}
(void)ltimerno; // unused
(void)ltimerno; // unused
/* Record what bus it's on */
lt->lt_bus = sc;
lt->lt_buspos = slot;
/* Record what bus it's on */
lt->lt_bus = sc;
lt->lt_buspos = slot;
/* Mark the slot in use and hook that slot's interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lt, ltimer_irq);
/* Mark the slot in use and hook that slot's interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lt, ltimer_irq);
return lt;
return lt;
}

View File

@@ -34,83 +34,67 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LTRACE_REG_TRON 0 /* trace on */
#define LTRACE_REG_TROFF 4 /* trace off */
#define LTRACE_REG_DEBUG 8 /* debug code */
#define LTRACE_REG_DUMP 12 /* dump the system */
#define LTRACE_REG_STOP 16 /* stop for the debugger */
#define LTRACE_REG_PROFEN 20 /* turn profiling on/off */
#define LTRACE_REG_PROFCL 24 /* clear the profile */
#define LTRACE_REG_TRON 0 /* trace on */
#define LTRACE_REG_TROFF 4 /* trace off */
#define LTRACE_REG_DEBUG 8 /* debug code */
#define LTRACE_REG_DUMP 12 /* dump the system */
#define LTRACE_REG_STOP 16 /* stop for the debugger */
#define LTRACE_REG_PROFEN 20 /* turn profiling on/off */
#define LTRACE_REG_PROFCL 24 /* clear the profile */
static struct ltrace_softc *the_trace;
void
ltrace_on(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TRON, code);
}
void ltrace_on(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TRON, code);
}
}
void
ltrace_off(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TROFF, code);
}
void ltrace_off(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TROFF, code);
}
}
void
ltrace_debug(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DEBUG, code);
}
void ltrace_debug(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DEBUG, code);
}
}
void
ltrace_dump(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DUMP, code);
}
void ltrace_dump(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DUMP, code);
}
}
void
ltrace_stop(uint32_t code)
{
if (the_trace != NULL && the_trace->lt_canstop) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_STOP, code);
}
void ltrace_stop(uint32_t code) {
if (the_trace != NULL && the_trace->lt_canstop) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_STOP, code);
}
}
void
ltrace_setprof(uint32_t onoff)
{
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFEN, onoff);
}
void ltrace_setprof(uint32_t onoff) {
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFEN, onoff);
}
}
void
ltrace_eraseprof(void)
{
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFCL, 1);
}
void ltrace_eraseprof(void) {
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFCL, 1);
}
}
int
config_ltrace(struct ltrace_softc *sc, int ltraceno)
{
(void)ltraceno;
the_trace = sc;
return 0;
int config_ltrace(struct ltrace_softc *sc, int ltraceno) {
(void)ltraceno;
the_trace = sc;
return 0;
}

View File

@@ -31,11 +31,11 @@
#define _LAMEBUS_LTRACE_H_
struct ltrace_softc {
/* Initialized by lower-level attachment function */
void *lt_busdata;
uint32_t lt_buspos;
bool lt_canstop;
bool lt_canprof;
/* Initialized by lower-level attachment function */
void *lt_busdata;
uint32_t lt_buspos;
bool lt_canstop;
bool lt_canprof;
};
/*

View File

@@ -34,36 +34,35 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Revision that supports ltrace_stop() */
#define STOP_VERSION 2
#define STOP_VERSION 2
/* Revision that supports ltrace_prof() */
#define PROF_VERSION 3
#define PROF_VERSION 3
struct ltrace_softc *
attach_ltrace_to_lamebus(int ltraceno, struct lamebus_softc *sc)
{
struct ltrace_softc *lt;
uint32_t drl;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TRACE,
LOW_VERSION, &drl);
if (slot < 0) {
return NULL;
}
struct ltrace_softc *attach_ltrace_to_lamebus(int ltraceno,
struct lamebus_softc *sc) {
struct ltrace_softc *lt;
uint32_t drl;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TRACE, LOW_VERSION, &drl);
if (slot < 0) {
return NULL;
}
lt = kmalloc(sizeof(struct ltrace_softc));
if (lt==NULL) {
return NULL;
}
lt = kmalloc(sizeof(struct ltrace_softc));
if (lt == NULL) {
return NULL;
}
(void)ltraceno; // unused
(void)ltraceno; // unused
lt->lt_busdata = sc;
lt->lt_buspos = slot;
lt->lt_canstop = drl >= STOP_VERSION;
lt->lt_canprof = drl >= PROF_VERSION;
lt->lt_busdata = sc;
lt->lt_buspos = slot;
lt->lt_canstop = drl >= STOP_VERSION;
lt->lt_canprof = drl >= PROF_VERSION;
lamebus_mark(sc, slot);
lamebus_mark(sc, slot);
return lt;
return lt;
}

View File

@@ -38,20 +38,19 @@
#include <lamebus/lrandom.h>
#include "autoconf.h"
struct random_softc *
attach_random_to_lrandom(int randomno, struct lrandom_softc *ls)
{
struct random_softc *rs = kmalloc(sizeof(struct random_softc));
if (rs==NULL) {
return NULL;
}
struct random_softc *attach_random_to_lrandom(int randomno,
struct lrandom_softc *ls) {
struct random_softc *rs = kmalloc(sizeof(struct random_softc));
if (rs == NULL) {
return NULL;
}
(void)randomno; // unused
(void)randomno; // unused
rs->rs_devdata = ls;
rs->rs_random = lrandom_random;
rs->rs_randmax = lrandom_randmax;
rs->rs_read = lrandom_read;
rs->rs_devdata = ls;
rs->rs_random = lrandom_random;
rs->rs_randmax = lrandom_randmax;
rs->rs_read = lrandom_read;
return rs;
return rs;
}

View File

@@ -44,23 +44,22 @@
#include <lamebus/ltimer.h>
#include "autoconf.h"
struct rtclock_softc *
attach_rtclock_to_ltimer(int rtclockno, struct ltimer_softc *ls)
{
/*
* No need to probe; ltimer always has a clock.
* Just allocate the rtclock, set our fields, and return it.
*/
struct rtclock_softc *rtc = kmalloc(sizeof(struct rtclock_softc));
if (rtc==NULL) {
/* Out of memory */
return NULL;
}
struct rtclock_softc *attach_rtclock_to_ltimer(int rtclockno,
struct ltimer_softc *ls) {
/*
* No need to probe; ltimer always has a clock.
* Just allocate the rtclock, set our fields, and return it.
*/
struct rtclock_softc *rtc = kmalloc(sizeof(struct rtclock_softc));
if (rtc == NULL) {
/* Out of memory */
return NULL;
}
(void)rtclockno; // unused
(void)rtclockno; // unused
rtc->rtc_devdata = ls;
rtc->rtc_gettime = ltimer_gettime;
rtc->rtc_devdata = ls;
rtc->rtc_gettime = ltimer_gettime;
return rtc;
return rtc;
}