|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6168 (0x1818)
Types: TextFile
Notes: UNIX file
Names: »kb.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦2d53db1df⟧ UNIX Filesystem
└─⟦this⟧ »sys/z8001/rec/kb.c«
/* (-lgl
* The information contained herein is a trade secret of Mark Williams
* Company, and is confidential information. It is provided under a
* license agreement, and may be copied or disclosed only under the
* terms of that agreement. Any reproduction or disclosure of this
* material without the express written authorization of Mark Williams
* Company or persuant to the license agreement is unlawful.
*
* COHERENT Version 0.7.3
* Copyright (c) 1982, 1983, 1984.
* An unpublished work by Mark Williams Company, Chicago.
* All rights reserved.
-lgl) */
/*
* Commodore 900 Keyboard-specific driver.
* NOTE: this driver must be loaded with the
* appropriate memory-mapped video driver.
* These two drivers together with the `kv.c'
* driver form the whole driver.
*/
#include <coherent.h>
#include <errno.h>
#include <tty.h>
#include <io.h>
#include <kbtab.h>
#define KBIRQ 8 /* Interrupt level for keyboard */
void kbintr();
void kbinit();
void kbterm();
void kbintend();
int v0in();
static int kbopenf;
static int kbkeypad; /* Set into keypad mode */
static int kbsstate; /* Shift state */
/*
* Code to drive the Z8036 interface on the Commodore
* 900. This has all the bit defintions.
*/
#define clearint() outb(PACS, 0x20)
/* Port definitions - Z8036 #1 */
#define PADD 0x47 /* Port A Data Direction */
#define PCDD 0x0D /* Port C Data Direction */
#define PADPP 0x45 /* Port A Data Path Polarity */
#define PCDPP 0x0B /* Port C Data Path Polarity */
#define PASIOC 0x49 /* Port A Special I/O Control */
#define PCSIOC 0x0F /* Port C Special I/O Control */
#define PAMS 0x41 /* Port A Mode Specification */
#define PAHS 0x43 /* Port A Handshake Specification */
#define PAPPR 0x4B /* Port A Pattern Polarity */
#define PAPTR 0x4D /* Port A Pattern Transition */
#define PAPMR 0x4F /* Port A Pattern Mask */
#define PAIV 0x05 /* Port A Interrupt Vector */
#define PACS 0x11 /* Port A Command and Status */
#define MICR 0x01 /* Master Interrupt Control */
#define MCC 0x03 /* Master Configuration Control */
#define PADATA 0x1B /* Port A Data */
#define PCDATA 0x1F /* Port C Data */
#define SETKBD 0x78 /* Set pc3 bit (KBDCLR) */
#define CLRKBD 0x70 /* Clear pc3 bit (KBDCLR) */
static void
kbinit()
{
outb(PADD, 0xFF); /* Input data direction Port A */
outb(PCDD, (inb(PCDD)&~0xC)|0x4); /* pc2 input/ pc3 output */
outb(PADPP, 0); /* Non-inverting all of Port A */
outb(PCDPP, inb(PCDPP)&~0xC); /* Non-inverting pc2, pc3 */
outb(PASIOC, 0); /* No special I/O on Port A */
outb(PCSIOC, inb(PCSIOC)&~0xC); /* No special I/O pc2, pc3 */
outb(PAMS, 0x1A); /* Single buffer, int. match, OR */
outb(PAHS, 0); /* No Handshake */
outb(PAPPR, 0x80); /* Pattern polarity: */
outb(PAPTR, 0x00); /* one bit set in 0x80 */
outb(PAPMR, 0x80); /* or pa7 */
outb(PAIV, KBIRQ); /* Interrupt vector */
clearint();
outb(PACS, 0xC0); /* Enable interrupts */
outb(MICR, inb(MICR)|0x80); /* Master interrupt enable */
outb(MCC, inb(MCC)|0x04); /* Enable Port A interrupt */
/*
* This enables the keyboard.
* Unfortunately, there is a bit
* for IEEE REN here (0x01) as well
* which needs to be saved via a
* software copy.
*/
outb(0x205, 0x02);
/*
* Strobe keyboard bit.
*/
outb(PCDATA, CLRKBD);
outb(PCDATA, SETKBD);
}
static void
kbterm()
{
outb(0x205, 0); /* disable keyboard */
outb(MCC, inb(MCC)&~0x04); /* Disable Port A int. enable */
}
/*
* Keyboard load
* Set up interrupts
* and initialise Z8036 hardware.
*/
kbload()
{
setivec(KBIRQ, kbintr);
kbinit();
}
/*
* Keyboard unload
* Make device quiescent and turn off
* interrupts.
*/
kbuload()
{
kbterm();
clrivec(KBIRQ);
}
kbopen(dev, m)
dev_t dev;
int m;
{
++kbopenf;
}
kbclose(dev)
dev_t dev;
{
if (--kbopenf < 0)
kbopenf = 0;
}
kbioctl(dev, com, p)
{
/*
printf("MCC=%x\n", inb(MCC));
printf("MICR=%x\n", inb(MICR));
printf("PACS=%x\n", inb(PACS));
*/
}
static void
kbintr(dev)
dev_t dev;
{
register KEY *kp;
register int f;
register int c;
register int s;
register int u;
/*
* Port A has KD0-KD6 bits in it. KD8 is
* the interrupt pattern bit and should be
* masked off. KD7 is the keyup/keydown bit
* and it in Port C.
*/
s = sphi();
u = inb(PCDATA)&0x04; /* Keyup/Keydown */
c = inb(PADATA)&~0x80;
spl(s);
#if 0
printf("ss=%d, Key %d, %s\n", kbsstate, c, u ? "up" : "down");
#endif
kp = &ktab[c];
/*
* Shift keys are the only ones that
* use keyup and keydown differentiation.
*/
f = kp->k_flag;
if (f & KINV) {
kbintend();
return;
}
if (f & (KSHIFT|KLOCK)) {
if (f & KLOCK) {
if (u)
kbsstate ^= kp->k_control;
} else if (u)
kbsstate &= ~kp->k_control;
else
kbsstate |= kp->k_control;
kbintend();
return;
}
if (u) {
kbintend();
return;
}
/*
* This check is here to ensure that
* shift states map properly (in case
* any keys lock).
*/
if (kbopenf == 0) {
kbintend();
return;
}
if (kbkeypad!=0 && (f&KP)!=0) {
c = kp->k_control;
} else if (kbsstate != 0) {
register int shift = 0x00;
if ((kbsstate & (SS1|SS2)) != 0)
shift = 0x01;
if (kbsstate & (SCL|SNL)) {
if ((f&KCAP)!=0 && (kbsstate&SCL)!=0
|| (f&KNL)!=0 && (kbsstate&SNL)!=0)
shift ^= 0x01;
}
if (kbsstate & SCT) {
if (f & KC)
c = kp->k_control;
else {
kbintend();
return;
}
} else if (shift)
c = kp->k_upper;
else
c = kp->k_lower;
if (kbsstate & SAL)
c |= 0x80;
} else
c = kp->k_lower;
v0in(c);
if (f & KDUP)
v0in(c);
/*
* Send shift state for all
* Function keys
*/
if (c>=FBASE && c<=FEND) {
c = CSHIFT;
if ((kbsstate & (SS1|SS2)) != 0)
c |= SUPPER;
if (kbsstate & SAL)
c |= SALT;
if (kbsstate & SCT)
c |= SCTRL;
v0in(c);
}
kbintend();
}
static void
kbintend()
{
register int s;
s = sphi();
clearint();
/*
* Strobe keyboard.
*/
outb(PCDATA, CLRKBD);
outb(PCDATA, SETKBD);
spl(s);
}
/*
* Set/reset keypad mode.
* Non-zero `f' implies keypad mode in
* which certain keypad keys return
* special sequences rather than numbers, etc.
*/
kbkpmode(f)
int f;
{
kbkeypad = f;
}