github.com/icexin/eggos@v0.4.2-0.20220216025428-78b167e4f349/drivers/cga/backend.go (about) 1 package cga 2 3 import ( 4 "unsafe" 5 6 "github.com/icexin/eggos/drivers/cga/fbcga" 7 "github.com/icexin/eggos/drivers/vbe" 8 "github.com/icexin/eggos/kernel/sys" 9 ) 10 11 type Backend interface { 12 GetPos() int 13 SetPos(pos int) 14 // WritePos write char at given pos but not update pos 15 WritePos(pos int, char byte) 16 // WriteByte write char and advance pos 17 WriteByte(ch byte) 18 } 19 20 const ( 21 CRTPORT = 0x3d4 22 bs = '\b' 23 del = 0x7f 24 ) 25 26 var ( 27 crt = (*[25 * 80]uint16)(unsafe.Pointer(uintptr(0xb8000))) 28 ) 29 30 type cgabackend struct { 31 } 32 33 func (c *cgabackend) SetPos(pos int) { 34 sys.Outb(CRTPORT, 14) 35 sys.Outb(CRTPORT+1, byte(pos>>8)) 36 sys.Outb(CRTPORT, 15) 37 sys.Outb(CRTPORT+1, byte(pos)) 38 } 39 40 func (c *cgabackend) GetPos() int { 41 var pos int 42 43 // Cursor position: col + 80*row. 44 sys.Outb(CRTPORT, 14) 45 pos = int(sys.Inb(CRTPORT+1)) << 8 46 sys.Outb(CRTPORT, 15) 47 pos |= int(sys.Inb(CRTPORT + 1)) 48 return pos 49 } 50 51 func (c *cgabackend) WritePos(pos int, ch byte) { 52 crt[pos] = uint16(ch) | 0x0700 53 } 54 55 func (c *cgabackend) WriteByte(ch byte) { 56 var pos int 57 58 // Cursor position: col + 80*row. 59 sys.Outb(CRTPORT, 14) 60 pos = int(sys.Inb(CRTPORT+1)) << 8 61 sys.Outb(CRTPORT, 15) 62 pos |= int(sys.Inb(CRTPORT + 1)) 63 64 switch ch { 65 case '\n': 66 pos += 80 - pos%80 67 case bs, del: 68 if pos > 0 { 69 pos-- 70 } 71 default: 72 // black on white 73 crt[pos] = uint16(ch&0xff) | 0x0700 74 pos++ 75 } 76 77 // Scroll up 78 if pos/80 >= 25 { 79 copy(crt[:], crt[80:25*80]) 80 pos -= 80 81 s := crt[pos : 25*80] 82 for i := range s { 83 // 在mac下开启qemu的-M accel=hvf,在滚屏的时候会出现`failed to decode instruction f 7f` 84 // 猜测是memclrNoHeapPointer造成的,具体原因未知 85 if false { 86 } 87 s[i] = 0 88 } 89 } 90 c.SetPos(pos) 91 crt[pos] = ' ' | 0x0700 92 } 93 94 func getbackend() Backend { 95 if vbe.IsEnable() { 96 return &fbcga.Backend 97 } 98 return &backend 99 }