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 } }