1
0
mirror of https://github.com/PDP-10/klh10.git synced 2026-02-09 09:42:30 +00:00
Files
PDP-10.klh10/src/dvhost.c
Olaf Seibert 58b59dbaa1 Overlay panda-dist/klh10-2.0h
by the late MRC, Mark Crispin.
Source: probably the former http://panda.com/tops-20/ .
panda-dist.tar.gz dated Mar 30  2007.
2015-04-27 23:07:21 +02:00

365 lines
9.4 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* DVHOST.C - Fake "Host" device to provide access to native host platform
*/
/* $Id: dvhost.c,v 2.3 2001/11/10 21:28:59 klh Exp $
*/
/* Copyright © 1994, 2001 Kenneth L. Harrenstien
** All Rights Reserved
**
** This file is part of the KLH10 Distribution. Use, modification, and
** re-distribution is permitted subject to the terms in the file
** named "LICENSE", which contains the full text of the legal notices
** and should always accompany this Distribution.
**
** This software is provided "AS IS" with NO WARRANTY OF ANY KIND.
**
** This notice (including the copyright and warranty disclaimer)
** must be included in all copies or derivations of this software.
*/
/*
* $Log: dvhost.c,v $
* Revision 2.3 2001/11/10 21:28:59 klh
* Final 2.0 distribution checkin
*
*/
/*
*/
#include "klh10.h"
#if !KLH10_DEV_HOST && CENV_SYS_DECOSF
/* Stupid gubbish needed to prevent OSF/1 AXP compiler from
** halting merely because compiled file is empty!
*/
static int decosfcclossage;
#endif
#if KLH10_DEV_HOST /* Moby conditional for entire file */
#include <stddef.h> /* For size_t etc */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "kn10def.h" /* This includes OSD defs */
#include "kn10dev.h"
#include "kn10ops.h"
#include "dvhost.h"
#include "dvlites.h"
#include "kn10clk.h" /* Need access to clock stuff */
#include "prmstr.h" /* For parameter parsing */
#ifdef RCSID
RCSID(dvhost_c,"$Id: dvhost.c,v 2.3 2001/11/10 21:28:59 klh Exp $")
#endif
struct host {
struct device hst_dv; /* Generic 10 device structure */
#if !KLH10_CPU_KS
unsigned long hst_lhcond;
unsigned long hst_cond;
#endif
};
static int nhosts = 0;
#define DVHOST_NSUP 1 /* Should never be anything else! */
struct host dvhost[DVHOST_NSUP];
/* Function predecls */
static int hst_conf(FILE *f, char *s, struct host *hst);
#if KLH10_CPU_KS
static void hst_write(struct device *, /* Unibus register write */
uint18, dvureg_t);
#else
static void hst_cono(struct device *, h10_t); /* CONO 18-bit conds out */
static w10_t hst_coni(struct device *); /* CONI 36-bit conds in */
static void hst_datao(struct device *, w10_t); /* DATAO word out */
static w10_t hst_datai(struct device *); /* DATAI word in */
#endif /* !KLH10_CPU_KS */
/* Configuration Parameters */
#if KLH10_CPU_KS
# define DVHOST_PARAMS \
prmdef(HSTP_DBG, "debug"), /* Initial debug value */\
prmdef(HSTP_BR, "br"), /* BR priority */\
prmdef(HSTP_VEC, "vec"), /* Interrupt vector */\
prmdef(HSTP_ADDR,"addr") /* Unibus address */
#else
# define DVHOST_PARAMS \
prmdef(HSTP_DBG, "debug") /* Initial debug value */
#endif /* KLH10_CPU_KS */
enum {
# define prmdef(i,s) i
DVHOST_PARAMS
# undef prmdef
};
static char *hstprmtab[] = {
# define prmdef(i,s) s
DVHOST_PARAMS
# undef prmdef
, NULL
};
/* HST_CONF - Parse configuration string and set defaults.
** At this point, device has just been created, but not yet bound
** or initialized.
** NOTE that some strings are dynamically allocated! Someday may want
** to clean them up nicely if config fails or device is uncreated.
*/
static int hst_conf(FILE *f, char *s, struct host *hst)
{
int i, ret = TRUE;
struct prmstate_s prm;
char buff[200];
#if KLH10_CPU_KS
long lval;
#endif
/* First set defaults for all configurable parameters
Unfortunately there's currently no way to access the UBA # that
we're gonna be bound to, otherwise could set up defaults. Later
fix this by giving dvhost_create() a ptr to an arg structure, etc.
*/
DVDEBUG(hst) = FALSE;
prm_init(&prm, buff, sizeof(buff),
s, strlen(s),
hstprmtab, sizeof(hstprmtab[0]));
while ((i = prm_next(&prm)) != PRMK_DONE) {
switch (i) {
case PRMK_NONE:
fprintf(f, "Unknown HOST parameter \"%s\"\n", prm.prm_name);
ret = FALSE;
continue;
case PRMK_AMBI:
fprintf(f, "Ambiguous HOST parameter \"%s\"\n", prm.prm_name);
ret = FALSE;
continue;
default: /* Handle matches not supported */
fprintf(f, "Unsupported HOST parameter \"%s\"\n", prm.prm_name);
ret = FALSE;
continue;
case HSTP_DBG: /* Parse as true/false boolean or number */
if (!prm.prm_val) /* No arg => default to 1 */
DVDEBUG(hst) = 1;
else if (!s_tobool(prm.prm_val, &DVDEBUG(hst)))
break;
continue;
#if KLH10_CPU_KS
case HSTP_BR: /* Parse as octal number */
if (!prm.prm_val || !s_tonum(prm.prm_val, &lval))
break;
if (lval < 4 || lval > 7) {
fprintf(f, "HOST BR must be one of 4,5,6,7\n");
ret = FALSE;
} else
hst->hst_dv.dv_brlev = lval;
continue;
case HSTP_VEC: /* Parse as octal number */
if (!prm.prm_val || !s_tonum(prm.prm_val, &lval))
break;
if (lval < 4 || lval > 0400 || (lval&03)) {
fprintf(f, "HOST VEC must be valid multiple of 4\n");
ret = FALSE;
} else
hst->hst_dv.dv_brvec = lval;
continue;
case HSTP_ADDR: /* Parse as octal number */
if (!prm.prm_val || !s_tonum(prm.prm_val, &lval))
break;
#if 0
if (lval < (DVHOST_REG_N<<1) || (lval&037)) {
fprintf(f, "HOST ADDR must be valid Unibus address\n");
ret = FALSE;
} else
#endif
hst->hst_dv.dv_addr = lval;
continue;
#endif /* KLH10_CPU_KS */
}
ret = FALSE;
fprintf(f, "HOST param \"%s\": ", prm.prm_name);
if (prm.prm_val)
fprintf(f, "bad value syntax: \"%s\"\n", prm.prm_val);
else
fprintf(f, "missing value\n");
}
/* Param string all done, do followup checks or cleanup */
#if KLH10_CPU_KS
# if 0
if (!hst->hst_dv.dv_brlev || !hst->hst_dv.dv_brvec || !hst->hst_dv.dv_addr) {
fprintf(f, "HOST missing one of BR, VEC, ADDR params\n");
# else
if (!hst->hst_dv.dv_addr) {
fprintf(f, "HOST missing ADDR param\n");
# endif
ret = FALSE;
}
/* Set 1st invalid addr */
hst->hst_dv.dv_aend = hst->hst_dv.dv_addr + (DVHOST_REG_N * 2);
#endif /* KLH10_CPU_KS */
return ret;
}
/* HOST interface routines to KLH10 */
struct device * dvhost_create(FILE *f, char *s)
{
register struct host *hst;
/* Parse string to determine which device to use, config, etc etc
** But for now, just allocate sequentially. Hack.
*/
if (nhosts >= DVHOST_NSUP) {
fprintf(f, "Too many HOSTs, max: %d\n", DVHOST_NSUP);
return NULL;
}
hst = &dvhost[nhosts++]; /* Pick unused dev */
memset((char *)hst, 0, sizeof(*hst)); /* Clear it out */
/* Initialize generic device part of HOST struct */
iodv_setnull(&hst->hst_dv); /* Initialize as null device */
#if KLH10_CPU_KS
/* Operate as new-style Unibus device */
hst->hst_dv.dv_write = hst_write; /* Write unibus register */
#else
/* Operate as old-style IO-bus device */
hst->hst_dv.dv_cono = hst_cono;
hst->hst_dv.dv_coni = hst_coni;
hst->hst_dv.dv_datao = hst_datao;
hst->hst_dv.dv_datai = hst_datai;
hst->hst_lhcond = 0535450; /* SIXBIT/KLH/ */
hst->hst_cond = DVHOST_CO_STATE | DVHOST_CO_SETAUX | DVHOST_CO_IDLE ;
#endif
/* Configure from parsed string and remember for init
*/
if (!hst_conf(f, s, hst))
return NULL;
return &hst->hst_dv;
}
#if !KLH10_CPU_KS
/* CONO 18-bit conds out
** Args D, ERH
** Returns nothing
*/
static insdef_cono(hst_cono)
{
register struct host *hst = (struct host *)d;
register uint18 cond = erh;
if (DVDEBUG(hst))
fprintf(DVDBF(hst), "[hst_cono: %lo]\r\n", (long)erh);
if (cond & (DVHOST_CO_CPU | DVHOST_CO_DISK | DVHOST_CO_TAPE |
DVHOST_CO_NET | DVHOST_CO_STATE))
lights_status ((cond & DVHOST_CO_CPU) ? 1 : 0,
(cond & DVHOST_CO_DISK) ? 1 : 0,
(cond & DVHOST_CO_TAPE) ? 1 : 0,
(cond & DVHOST_CO_NET) ? 1 : 0,
(cond & DVHOST_CO_STATE) ? 1 : 0);
if (cond & DVHOST_CO_SETAUX)
lights_pgmaux ((cond >> 9) & 07);
if (cond & DVHOST_CO_IDLE)
clk_idle(); /* Invoke CLK_IDLE! */
/* update host CONI */
if (cond & DVHOST_CO_STATE)
hst->hst_cond &= ~(DVHOST_CO_CPU | DVHOST_CO_DISK |
DVHOST_CO_TAPE | DVHOST_CO_NET);
else hst->hst_cond |= (cond & (DVHOST_CO_CPU | DVHOST_CO_DISK |
DVHOST_CO_TAPE | DVHOST_CO_NET));
if (cond & DVHOST_CO_SETAUX) {
hst->hst_cond &= ~DVHOST_CO_AUX;
hst->hst_cond |= cond & DVHOST_CO_AUX;
}
}
/* CONI 36-bit conds in
** Args D
** Returns condition word
*/
static insdef_coni(hst_coni)
{
register w10_t w;
register struct host *hst = (struct host *)d;
if (DVDEBUG(hst))
fprintf(DVDBF(hst), "[hst_coni: %lo,,%lo]\r\n",
(long)hst->hst_lhcond, (long)hst->hst_cond);
LRHSET(w, hst->hst_lhcond, hst->hst_cond);
return w;
}
/* DATAO word out
** Args D, W
** Returns nothing
*/
static insdef_datao(hst_datao)
{
register struct host *hst = (struct host *)d;
lights_pgmlites(LHGET(w), RHGET(w));
if (DVDEBUG(hst))
fprintf(DVDBF(hst), "[hst_datao: %lo,,%lo]\r\n",
(long)LHGET(w), (long)RHGET(w));
}
/* DATAI word in
** Args D
** Returns data word
*/
static insdef_datai(hst_datai)
{
register struct host *hst = (struct host *)d;
register w10_t w;
w = cpu.mr_dsw; /* Read data switches */
if (DVDEBUG(hst))
fprintf(DVDBF(hst), "[hst_datai: %lo,,%lo]\r\n",
(long)LHGET(w), (long)RHGET(w));
return w;
}
#endif /* !KLH10_CPU_KS */
#if KLH10_CPU_KS
/* Unibus interface routines */
static void hst_write(struct device *d, uint18 addr, register dvureg_t val)
{
register struct host *hst = (struct host *)d;
if (DVDEBUG(hst))
fprintf(DVDBF(hst), "[hst_write: %lo]\r\n", (long)val);
if (val == DVHOST_CO_IDLE)
clk_idle(); /* Invoke CLK_IDLE! */
}
#endif /* KLH10_CPU_KS */
#endif /* KLH10_DEV_HOST */