mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Detect hw and wire active console and TTY
This commit is contained in:
parent
eca1f6c26e
commit
562fae2028
@ -13,3 +13,7 @@ type Driver interface {
|
|||||||
// DriverInit initializes the device driver.
|
// DriverInit initializes the device driver.
|
||||||
DriverInit() *kernel.Error
|
DriverInit() *kernel.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProbeFn is a function that scans for the presence of a particular
|
||||||
|
// piece of hardware and returns a driver for it.
|
||||||
|
type ProbeFn func() Driver
|
||||||
|
@ -5,6 +5,14 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultScrollback defines the terminal scrollback in lines.
|
||||||
|
DefaultScrollback = 80
|
||||||
|
|
||||||
|
// DefaultTabWidth defines the number of spaces that tabs expand to.
|
||||||
|
DefaultTabWidth = 4
|
||||||
|
)
|
||||||
|
|
||||||
// State defines the supported terminal state values.
|
// State defines the supported terminal state values.
|
||||||
type State uint8
|
type State uint8
|
||||||
|
|
||||||
|
11
src/gopheros/device/tty/probe.go
Normal file
11
src/gopheros/device/tty/probe.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package tty
|
||||||
|
|
||||||
|
import "gopheros/device"
|
||||||
|
|
||||||
|
// HWProbes returns a slice of device.ProbeFn that can be used by the hal
|
||||||
|
// package to probe for TTY device hardware.
|
||||||
|
func HWProbes() []device.ProbeFn {
|
||||||
|
return []device.ProbeFn{
|
||||||
|
probeForVT,
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package tty
|
package tty
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"gopheros/device"
|
||||||
"gopheros/device/video/console"
|
"gopheros/device/video/console"
|
||||||
"gopheros/kernel"
|
"gopheros/kernel"
|
||||||
"io"
|
"io"
|
||||||
@ -258,3 +259,7 @@ func (t *VT) DriverVersion() (uint16, uint16, uint16) {
|
|||||||
|
|
||||||
// DriverInit initializes this driver.
|
// DriverInit initializes this driver.
|
||||||
func (t *VT) DriverInit() *kernel.Error { return nil }
|
func (t *VT) DriverInit() *kernel.Error { return nil }
|
||||||
|
|
||||||
|
func probeForVT() device.Driver {
|
||||||
|
return NewVT(DefaultTabWidth, DefaultScrollback)
|
||||||
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"gopheros/device/video/console"
|
"gopheros/device/video/console"
|
||||||
"image/color"
|
"image/color"
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -337,6 +338,28 @@ func TestVTDriverInterface(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVTProbe(t *testing.T) {
|
||||||
|
var (
|
||||||
|
expProbePtr = reflect.ValueOf(probeForVT).Pointer()
|
||||||
|
foundProbe bool
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, probeFn := range HWProbes() {
|
||||||
|
if reflect.ValueOf(probeFn).Pointer() == expProbePtr {
|
||||||
|
foundProbe = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !foundProbe {
|
||||||
|
t.Fatal("expected probeForVT to be part of the probes returned by HWProbes")
|
||||||
|
}
|
||||||
|
|
||||||
|
if drv := probeForVT(); drv == nil {
|
||||||
|
t.Fatal("expected probeForVT to return a driver")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type mockConsole struct {
|
type mockConsole struct {
|
||||||
width, height uint16
|
width, height uint16
|
||||||
fg, bg uint8
|
fg, bg uint8
|
||||||
|
16
src/gopheros/device/video/console/probe.go
Normal file
16
src/gopheros/device/video/console/probe.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package console
|
||||||
|
|
||||||
|
import "gopheros/device"
|
||||||
|
import "gopheros/kernel/hal/multiboot"
|
||||||
|
|
||||||
|
var (
|
||||||
|
getFramebufferInfoFn = multiboot.GetFramebufferInfo
|
||||||
|
)
|
||||||
|
|
||||||
|
// HWProbes returns a slice of device.ProbeFn that can be used by the hal
|
||||||
|
// package to probe for console device hardware.
|
||||||
|
func HWProbes() []device.ProbeFn {
|
||||||
|
return []device.ProbeFn{
|
||||||
|
probeForVgaTextConsole,
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
package console
|
package console
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"gopheros/device"
|
||||||
"gopheros/kernel"
|
"gopheros/kernel"
|
||||||
"gopheros/kernel/cpu"
|
"gopheros/kernel/cpu"
|
||||||
|
"gopheros/kernel/hal/multiboot"
|
||||||
"image/color"
|
"image/color"
|
||||||
"reflect"
|
"reflect"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@ -196,3 +198,15 @@ func (cons *VgaTextConsole) DriverVersion() (uint16, uint16, uint16) {
|
|||||||
|
|
||||||
// DriverInit initializes this driver.
|
// DriverInit initializes this driver.
|
||||||
func (cons *VgaTextConsole) DriverInit() *kernel.Error { return nil }
|
func (cons *VgaTextConsole) DriverInit() *kernel.Error { return nil }
|
||||||
|
|
||||||
|
// probeForVgaTextConsole checks for the presence of a vga text console.
|
||||||
|
func probeForVgaTextConsole() device.Driver {
|
||||||
|
var drv device.Driver
|
||||||
|
|
||||||
|
fbInfo := getFramebufferInfoFn()
|
||||||
|
if fbInfo.Type == multiboot.FramebufferTypeEGA {
|
||||||
|
drv = NewVgaTextConsole(uint16(fbInfo.Width), uint16(fbInfo.Height), uintptr(fbInfo.PhysAddr))
|
||||||
|
}
|
||||||
|
|
||||||
|
return drv
|
||||||
|
}
|
||||||
|
@ -3,7 +3,9 @@ package console
|
|||||||
import (
|
import (
|
||||||
"gopheros/device"
|
"gopheros/device"
|
||||||
"gopheros/kernel/cpu"
|
"gopheros/kernel/cpu"
|
||||||
|
"gopheros/kernel/hal/multiboot"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@ -318,3 +320,39 @@ func TestVgaTextDriverInterface(t *testing.T) {
|
|||||||
t.Fatal("DriverVersion() returned an invalid version number")
|
t.Fatal("DriverVersion() returned an invalid version number")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVgaTextProbe(t *testing.T) {
|
||||||
|
defer func() {
|
||||||
|
getFramebufferInfoFn = multiboot.GetFramebufferInfo
|
||||||
|
}()
|
||||||
|
|
||||||
|
var (
|
||||||
|
expProbePtr = reflect.ValueOf(probeForVgaTextConsole).Pointer()
|
||||||
|
foundProbe bool
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, probeFn := range HWProbes() {
|
||||||
|
if reflect.ValueOf(probeFn).Pointer() == expProbePtr {
|
||||||
|
foundProbe = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !foundProbe {
|
||||||
|
t.Fatal("expected probeForVgaTextConsole to be part of the probes returned by HWProbes")
|
||||||
|
}
|
||||||
|
|
||||||
|
getFramebufferInfoFn = func() *multiboot.FramebufferInfo {
|
||||||
|
return &multiboot.FramebufferInfo{
|
||||||
|
Width: 80,
|
||||||
|
Height: 25,
|
||||||
|
Pitch: 160,
|
||||||
|
PhysAddr: 0xb80000,
|
||||||
|
Type: multiboot.FramebufferTypeEGA,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if drv := probeForVgaTextConsole(); drv == nil {
|
||||||
|
t.Fatal("expected probeForVgaTextConsole to return a driver")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,23 +1,67 @@
|
|||||||
package hal
|
package hal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gopheros/kernel/driver/tty"
|
"gopheros/device"
|
||||||
"gopheros/kernel/driver/video/console"
|
"gopheros/device/tty"
|
||||||
"gopheros/kernel/hal/multiboot"
|
"gopheros/device/video/console"
|
||||||
|
"gopheros/kernel/kfmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// managedDevices contains the devices discovered by the HAL.
|
||||||
egaConsole = &console.Ega{}
|
type managedDevices struct {
|
||||||
|
activeConsole console.Device
|
||||||
// ActiveTerminal points to the currently active terminal.
|
activeTTY tty.Device
|
||||||
ActiveTerminal = &tty.Vt{}
|
}
|
||||||
)
|
|
||||||
|
var devices managedDevices
|
||||||
// InitTerminal provides a basic terminal to allow the kernel to emit some output
|
|
||||||
// till everything is properly setup
|
// ActiveTTY returns the currently active TTY
|
||||||
func InitTerminal() {
|
func ActiveTTY() tty.Device {
|
||||||
fbInfo := multiboot.GetFramebufferInfo()
|
return devices.activeTTY
|
||||||
|
}
|
||||||
egaConsole.Init(uint16(fbInfo.Width), uint16(fbInfo.Height), uintptr(fbInfo.PhysAddr))
|
|
||||||
ActiveTerminal.AttachTo(egaConsole)
|
// DetectHardware probes for hardware devices and initializes the appropriate
|
||||||
|
// drivers.
|
||||||
|
func DetectHardware() {
|
||||||
|
consoles := probe(console.HWProbes())
|
||||||
|
if len(consoles) != 0 {
|
||||||
|
devices.activeConsole = consoles[0].(console.Device)
|
||||||
|
}
|
||||||
|
|
||||||
|
ttys := probe(tty.HWProbes())
|
||||||
|
if len(ttys) != 0 {
|
||||||
|
devices.activeTTY = ttys[0].(tty.Device)
|
||||||
|
devices.activeTTY.AttachTo(devices.activeConsole)
|
||||||
|
kfmt.SetOutputSink(devices.activeTTY)
|
||||||
|
|
||||||
|
// Sync terminal contents with console
|
||||||
|
devices.activeTTY.SetState(tty.StateActive)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// probe executes the supplied hw probe functions and attempts to initialize
|
||||||
|
// each detected device. The function returns a list of device drivers that
|
||||||
|
// were successfully initialized.
|
||||||
|
func probe(hwProbeFns []device.ProbeFn) []device.Driver {
|
||||||
|
var drivers []device.Driver
|
||||||
|
|
||||||
|
for _, probeFn := range hwProbeFns {
|
||||||
|
drv := probeFn()
|
||||||
|
if drv == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
major, minor, patch := drv.DriverVersion()
|
||||||
|
|
||||||
|
kfmt.Printf("[hal] %s(%d.%d.%d): ", drv.DriverName(), major, minor, patch)
|
||||||
|
if err := drv.DriverInit(); err != nil {
|
||||||
|
kfmt.Printf("init failed: %s\n", err.Message)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
drivers = append(drivers, drv)
|
||||||
|
kfmt.Printf("initialized\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return drivers
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"gopheros/kernel/goruntime"
|
"gopheros/kernel/goruntime"
|
||||||
"gopheros/kernel/hal"
|
"gopheros/kernel/hal"
|
||||||
"gopheros/kernel/hal/multiboot"
|
"gopheros/kernel/hal/multiboot"
|
||||||
|
"gopheros/kernel/kfmt"
|
||||||
"gopheros/kernel/mem/pmm/allocator"
|
"gopheros/kernel/mem/pmm/allocator"
|
||||||
"gopheros/kernel/mem/vmm"
|
"gopheros/kernel/mem/vmm"
|
||||||
)
|
)
|
||||||
@ -27,9 +28,6 @@ var (
|
|||||||
func Kmain(multibootInfoPtr, kernelStart, kernelEnd uintptr) {
|
func Kmain(multibootInfoPtr, kernelStart, kernelEnd uintptr) {
|
||||||
multiboot.SetInfoPtr(multibootInfoPtr)
|
multiboot.SetInfoPtr(multibootInfoPtr)
|
||||||
|
|
||||||
hal.InitTerminal()
|
|
||||||
hal.ActiveTerminal.Clear()
|
|
||||||
|
|
||||||
var err *kernel.Error
|
var err *kernel.Error
|
||||||
if err = allocator.Init(kernelStart, kernelEnd); err != nil {
|
if err = allocator.Init(kernelStart, kernelEnd); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -39,7 +37,10 @@ func Kmain(multibootInfoPtr, kernelStart, kernelEnd uintptr) {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use kernel.Panic instead of panic to prevent the compiler from
|
// Detect and initialize hardware
|
||||||
|
hal.DetectHardware()
|
||||||
|
|
||||||
|
// Use kfmt.Panic instead of panic to prevent the compiler from
|
||||||
// treating kernel.Panic as dead-code and eliminating it.
|
// treating kernel.Panic as dead-code and eliminating it.
|
||||||
kernel.Panic(errKmainReturned)
|
kfmt.Panic(errKmainReturned)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user