103 lines
1.6 KiB
Go
103 lines
1.6 KiB
Go
package main
|
|
|
|
import "log"
|
|
|
|
// i8255 is a generic Intel 8255-compatible I/O controller chip.
|
|
//
|
|
// Only mode 0 is supported.
|
|
type i8255 struct {
|
|
pa, pb, pc uint8
|
|
|
|
onOut func(port i8255Port)
|
|
onIn func(port i8255Port)
|
|
}
|
|
|
|
type i8255Port string
|
|
|
|
const (
|
|
PA i8255Port = "PA"
|
|
PB i8255Port = "PB"
|
|
PC i8255Port = "PC"
|
|
)
|
|
|
|
func (i *i8255) getPort(p i8255Port) uint8 {
|
|
switch p {
|
|
case PA:
|
|
return i.pa
|
|
case PB:
|
|
return i.pb
|
|
case PC:
|
|
return i.pc
|
|
default:
|
|
log.Fatalf("invalid port")
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func (i *i8255) Out(addr, value uint8) {
|
|
switch addr {
|
|
case 0:
|
|
i.pa = value
|
|
if i.onOut != nil {
|
|
i.onOut(PA)
|
|
}
|
|
case 1:
|
|
i.pb = value
|
|
if i.onOut != nil {
|
|
i.onOut(PB)
|
|
}
|
|
case 2:
|
|
i.pc = value
|
|
if i.onOut != nil {
|
|
i.onOut(PC)
|
|
}
|
|
case 3:
|
|
if (value >> 7) == 0 {
|
|
// BSR mode
|
|
bitno := (value >> 1) & 0b111
|
|
bitval := value & 1
|
|
if bitval == 1 {
|
|
i.pc |= (1 << bitno)
|
|
} else {
|
|
i.pc &= 0xff ^ (1 << bitno)
|
|
}
|
|
} else {
|
|
// Input/Output mode
|
|
gaMode := (value >> 5) & 0b11
|
|
gbMode := (value >> 5) & 0b11
|
|
if gaMode != 0 {
|
|
log.Fatalf("I8255 implementation only supports mode 0 on Port A")
|
|
}
|
|
if gbMode != 0 {
|
|
log.Fatalf("I8255 implementation only supports mode 0 on Port B")
|
|
}
|
|
// Don't care about the rest (input/output settings per group/port).
|
|
}
|
|
default:
|
|
log.Printf("I8255: invalid out")
|
|
}
|
|
}
|
|
|
|
func (i *i8255) In(addr uint8) uint8 {
|
|
switch addr {
|
|
case 0:
|
|
if i.onIn != nil {
|
|
i.onIn(PA)
|
|
}
|
|
return i.pa
|
|
case 1:
|
|
if i.onIn != nil {
|
|
i.onIn(PB)
|
|
}
|
|
return i.pb
|
|
case 2:
|
|
if i.onIn != nil {
|
|
i.onIn(PC)
|
|
}
|
|
return i.pc
|
|
default:
|
|
log.Printf("I8255: invalid in")
|
|
return 0
|
|
}
|
|
}
|