Changeset a71c158 in mainline


Ignore:
Timestamp:
2009-08-21T14:12:45Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0e6dce8, b50b5af2, e5792d1
Parents:
90c8b8d
Message:

kernel output devices now suport multiple instances (except ski and sgcn, which respect the same interface, but behave as singletons)
if more than one output device gets initialized, the output is cloned to all of them
get rid of arch_grab_console() and arch_release_console() (output devices can implement a generic "redraw" method, input devices respect the "silent" global variable)
related cleanups and modifications

Location:
kernel
Files:
32 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/amd64/src/amd64.c

    r90c8b8d ra71c158  
    151151                i8254_init();
    152152               
     153#if (defined(CONFIG_FB) || defined(CONFIG_EGA))
     154                bool vesa = false;
     155#endif
     156               
    153157#ifdef CONFIG_FB
    154                 if (vesa_present())
    155                         vesa_init();
    156                 else
    157 #endif
     158                vesa = vesa_init();
     159#endif
     160               
    158161#ifdef CONFIG_EGA
    159                         ega_init(EGA_BASE, EGA_VIDEORAM);  /* video */
    160 #else
    161                         {}
     162                if (!vesa) {
     163                        outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
     164                        if (egadev)
     165                                stdout_wire(egadev);
     166                }
    162167#endif
    163168               
     
    249254}
    250255
    251 /** Acquire console back for kernel
    252  *
    253  */
    254 void arch_grab_console(void)
    255 {
    256 #ifdef CONFIG_FB
    257         if (vesa_present())
    258                 vesa_redraw();
    259         else
    260 #endif
    261 #ifdef CONFIG_EGA
    262                 ega_redraw();
    263 #else
    264                 {}
    265 #endif
    266 }
    267 
    268 /** Return console to userspace
    269  *
    270  */
    271 void arch_release_console(void)
    272 {
    273 }
    274 
    275256/** Construct function pointer
    276257 *
  • kernel/arch/arm32/include/mach/integratorcp/integratorcp.h

    r90c8b8d ra71c158  
    9898
    9999extern void icp_init(void);
    100 extern void icp_fb_init(void);
    101100extern void icp_output_init(void);
    102101extern void icp_input_init(void);
    103 extern void icp_release_console(void);
    104 extern void icp_grab_console(void);
    105102extern void icp_timer_irq_start(void);
    106103extern void icp_cpu_halt(void);
    107104extern void icp_irq_exception(int exc_no, istate_t *istate);
    108105extern uintptr_t icp_get_memory_size(void);
    109 extern uintptr_t icp_get_fb_address(void);
    110 extern void icp_fb_init(void);
    111106extern void icp_frame_init(void);
    112107
  • kernel/arch/arm32/include/mach/testarm/testarm.h

    r90c8b8d ra71c158  
    6868
    6969extern void gxemul_init(void);
    70 extern void gxemul_fb_init(void);
    7170extern void gxemul_output_init(void);
    7271extern void gxemul_input_init(void);
    73 extern void gxemul_release_console(void);
    74 extern void gxemul_grab_console(void);
    7572extern void gxemul_timer_irq_start(void);
    7673extern void gxemul_cpu_halt(void);
    7774extern void gxemul_irq_exception(int exc_no, istate_t *istate);
    7875extern uintptr_t gxemul_get_memory_size(void);
    79 extern uintptr_t gxemul_get_fb_address(void);
    80 extern void gxemul_fb_init(void);
    8176extern void gxemul_frame_init(void);
    8277
  • kernel/arch/arm32/include/machine_func.h

    r90c8b8d ra71c158  
    4949
    5050struct arm_machine_ops {
    51         void            (*machine_grab_console)(void);
    52         void            (*machine_release_console)(void);
    5351        void            (*machine_init)(void);
    5452        void            (*machine_timer_irq_start)(void);
    5553        void            (*machine_cpu_halt)(void);
    5654        uintptr_t       (*machine_get_memory_size)(void);
    57         void            (*machine_fb_init)(void);
    5855        void            (*machine_irq_exception)(int, istate_t*);
    59         uintptr_t       (*machine_get_fb_address)(void);
    6056        void            (*machine_frame_init)(void);
    6157        void            (*machine_output_init)(void);
     
    6460
    6561extern struct arm_machine_ops machine_ops;
    66 
    67 
    68 /** Acquire console back for kernel. */
    69 extern void machine_grab_console(void);
    70 
    71 /** Return console to userspace. */
    72 extern void machine_release_console(void);
    7362
    7463
     
    9180extern uintptr_t machine_get_memory_size(void);
    9281
    93 /** Initializes the Frame Buffer
    94  *
    95  */
    96 extern void machine_fb_init(void);
    97 
    9882
    9983/** Interrupt exception handler.
     
    10488extern void machine_irq_exception(int exc_no, istate_t *istate);
    10589
    106 
    107 /** Returns address of framebuffer device.
    108  *
    109  *  @return Address of framebuffer device.
    110  */
    111 extern uintptr_t machine_get_fb_address(void);
    11290
    11391/*
  • kernel/arch/arm32/src/arm32.c

    r90c8b8d ra71c158  
    8989        interrupt_init();
    9090       
    91 #ifdef CONFIG_FB
    92         machine_fb_init();
    93 #else
    94 #ifdef CONFIG_ARM_PRN
    9591        machine_output_init();
    96 #endif /* CONFIG_ARM_PRN */
    97 #endif /* CONFIG_FB */
    9892}
    9993
     
    182176}
    183177
    184 /** Acquire console back for kernel. */
    185 void arch_grab_console(void)
    186 {
    187         machine_grab_console();
    188 #ifdef CONFIG_FB
    189         fb_redraw();
    190 #endif
    191 }
    192 
    193 /** Return console to userspace. */
    194 void arch_release_console(void)
    195 {
    196         machine_release_console();
    197 }
    198 
    199178/** @}
    200179 */
  • kernel/arch/arm32/src/mach/integratorcp/integratorcp.c

    r90c8b8d ra71c158  
    5757static irq_t icp_timer_irq;
    5858struct arm_machine_ops machine_ops = {
    59         MACHINE_GENFUNC,
    60         MACHINE_GENFUNC,
    6159        icp_init,
    6260        icp_timer_irq_start,
    6361        icp_cpu_halt,
    6462        icp_get_memory_size,
    65         icp_fb_init,
    6663        icp_irq_exception,
    67         icp_get_fb_address,
    6864        icp_frame_init,
    6965        icp_output_init,
     
    128124}
    129125
    130 /** Initializes the icp frame buffer */
    131 void icp_fb_init(void)
    132 {
    133         fb_properties_t prop = {
    134                 .addr = 0,
    135                 .offset = 0,
    136                 .x = 640,
    137                 .y = 480,
    138                 .scan = 2560,
    139                 .visual = VISUAL_BGR_0_8_8_8,
    140         };
    141         prop.addr = icp_get_fb_address();
    142         fb_init(&prop);
    143         fb_parea.pbase = ICP_FB;
    144         fb_parea.frames = 300;
    145         ddi_parea_register(&fb_parea);
    146 }
    147 
    148126/** Initializes icp_hw_map. */
    149127void icp_init(void)
     
    172150}
    173151
    174 
    175 /** Acquire console back for kernel. */
    176 void icp_grab_console(void)
    177 {
    178 }
    179 
    180 /** Return console to userspace. */
    181 void icp_release_console(void)
    182 {
    183 }
    184 
    185152/** Starts icp Real Time Clock device, which asserts regular interrupts.
    186  * 
     153 *
    187154 * @param frequency Interrupts frequency (0 disables RTC).
    188155 */
     
    296263}
    297264
    298 /** Returns address of framebuffer device.
    299  *
    300  *  @return Address of framebuffer device.
    301  */
    302 uintptr_t icp_get_fb_address(void)
    303 {
     265/*
     266 * Integrator specific frame initialization
     267 */
     268void
     269icp_frame_init(void)
     270{
     271        frame_mark_unavailable(ICP_FB_FRAME, ICP_FB_NUM_FRAME);
     272        frame_mark_unavailable(0, 256);
     273}
     274
     275void icp_output_init(void)
     276{
     277#ifdef CONFIG_FB
    304278        if (!vga_init) {
    305279                icp_vga_init();
    306280                vga_init = true;
    307281        }
    308         return (uintptr_t) ICP_FB;
    309 }
    310 
    311 /*
    312  * Integrator specific frame initialization
    313  */
    314 void
    315 icp_frame_init(void)
    316 {
    317         frame_mark_unavailable(ICP_FB_FRAME, ICP_FB_NUM_FRAME);
    318         frame_mark_unavailable(0, 256);
    319 }
    320 
    321 void icp_output_init(void)
    322 {
     282       
     283        fb_properties_t prop = {
     284                .addr = ICP_FB,
     285                .offset = 0,
     286                .x = 640,
     287                .y = 480,
     288                .scan = 2560,
     289                .visual = VISUAL_BGR_0_8_8_8,
     290        };
     291       
     292        outdev_t *fbdev = fb_init(&prop);
     293        if (fbdev) {
     294                stdout_wire(fbdev);
     295                fb_parea.pbase = ICP_FB;
     296                fb_parea.frames = 300;
     297                ddi_parea_register(&fb_parea);
     298        }
     299#endif
    323300}
    324301
  • kernel/arch/arm32/src/mach/testarm/testarm.c

    r90c8b8d ra71c158  
    5757
    5858struct arm_machine_ops machine_ops = {
    59         MACHINE_GENFUNC,
    60         MACHINE_GENFUNC,
    6159        gxemul_init,
    6260        gxemul_timer_irq_start,
    6361        gxemul_cpu_halt,
    6462        gxemul_get_memory_size,
    65         gxemul_fb_init,
    6663        gxemul_irq_exception,
    67         gxemul_get_fb_address,
    6864        gxemul_frame_init,
    6965        gxemul_output_init,
     
    7874}
    7975
    80 void gxemul_fb_init(void)
    81 {
     76void gxemul_output_init(void)
     77{
     78#ifdef CONFIG_FB
    8279        fb_properties_t prop = {
    8380                .addr = GXEMUL_FB_ADDRESS,
     
    8885                .visual = VISUAL_RGB_8_8_8,
    8986        };
    90         fb_init(&prop);
    91 }
    92 
    93 void gxemul_output_init(void)
    94 {
    95         dsrlnout_init((ioport8_t *) gxemul_kbd);
     87       
     88        outdev_t *fbdev = fb_init(&prop);
     89        if (fbdev)
     90                stdout_wire(fbdev);
     91#endif
     92       
     93#ifdef CONFIG_ARM_PRN
     94        outdev_t *dsrlndev = dsrlnout_init((ioport8_t *) gxemul_kbd);
     95        if (dsrlndev)
     96                stdout_wire(dsrlndev);
     97#endif
    9698}
    9799
     
    233235}
    234236
    235 uintptr_t gxemul_get_fb_address()
    236 {
    237         return ((uintptr_t)GXEMUL_FB_ADDRESS);
    238 }
    239 
    240 
    241237/** @}
    242238 */
  • kernel/arch/arm32/src/machine_func.c

    r90c8b8d ra71c158  
    4141
    4242
    43 /** Acquire console back for kernel. */
    44 void machine_grab_console(void)
    45 {
    46         (machine_ops.machine_grab_console)();
    47 }
    48 
    49 /** Return console to userspace. */
    50 void machine_release_console(void)
    51 {
    52         (machine_ops.machine_release_console)();
    53 }
    54 
    55 
    5643/** Maps HW devices to the kernel address space using #hw_map. */
    5744void machine_init(void)
     
    8471}
    8572
    86 /** Initializes the Frame Buffer
    87  *
    88  */
    89 void machine_fb_init(void)
    90 {
    91         (machine_ops.machine_fb_init)();
    92 }
    93 
    94 
    9573/** Interrupt exception handler.
    9674 *
     
    10381}
    10482
    105 
    106 /** Returns address of framebuffer device.
    107  *
    108  *  @return Address of framebuffer device.
    109  */
    110 uintptr_t machine_get_fb_address(void)
    111 {
    112         return (machine_ops.machine_get_fb_address)();
    113 }
    11483
    11584/*
  • kernel/arch/ia32/include/drivers/vesa.h

    r90c8b8d ra71c158  
    3636#define KERN_ia32_VESA_H_
    3737
    38 extern int vesa_present(void);
    39 extern void vesa_redraw(void);
    40 extern void vesa_init(void);
     38#include <arch/types.h>
     39
     40extern bool vesa_init(void);
    4141
    4242#endif
  • kernel/arch/ia32/src/drivers/vesa.c

    r90c8b8d ra71c158  
    2727 */
    2828
    29 /** @addtogroup ia32   
     29/** @addtogroup ia32
    3030 * @{
    3131 */
     
    4040#include <genarch/fb/visuals.h>
    4141#include <arch/drivers/vesa.h>
     42#include <console/chardev.h>
     43#include <console/console.h>
    4244#include <putchar.h>
    4345#include <mm/page.h>
     
    6668uint8_t vesa_blue_pos;
    6769
    68 int vesa_present(void)
     70bool vesa_init(void)
    6971{
    70         if ((vesa_width != 0xffff) && (vesa_height != 0xffff))
    71                 return true;
     72        if ((vesa_width == 0xffff) || (vesa_height == 0xffff))
     73                return false;
    7274       
    73         return false;
    74 }
    75 
    76 void vesa_init(void)
    77 {
    78         unsigned int visual;
     75        visual_t visual;
    7976       
    8077        switch (vesa_bpp) {
     
    9794                break;
    9895        default:
    99                 panic("Unsupported bits per pixel.");
     96                LOG("Unsupported bits per pixel.");
     97                return false;
    10098        }
    10199       
     
    108106                .visual = visual,
    109107        };
    110         fb_init(&vesa_props);
    111 }
    112 
    113 void vesa_redraw(void)
    114 {
    115         fb_redraw();
     108       
     109        outdev_t *fbdev = fb_init(&vesa_props);
     110        if (!fbdev)
     111                return false;
     112       
     113        stdout_wire(fbdev);
     114        return true;
    116115}
    117116
  • kernel/arch/ia32/src/ia32.c

    r90c8b8d ra71c158  
    112112                i8254_init();
    113113               
     114#if (defined(CONFIG_FB) || defined(CONFIG_EGA))
     115                bool vesa = false;
     116#endif
     117               
    114118#ifdef CONFIG_FB
    115                 if (vesa_present())
    116                         vesa_init();
    117                 else
    118 #endif
     119                vesa = vesa_init();
     120#endif
     121               
    119122#ifdef CONFIG_EGA
    120                         ega_init(EGA_BASE, EGA_VIDEORAM);  /* video */
    121 #else
    122                         {}
     123                if (!vesa) {
     124                        outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
     125                        if (egadev)
     126                                stdout_wire(egadev);
     127                }
    123128#endif
    124129               
     
    201206        THREAD->arch.tls = addr;
    202207        set_tls_desc(addr);
    203 
     208       
    204209        return 0;
    205 }
    206 
    207 /** Acquire console back for kernel
    208  *
    209  */
    210 void arch_grab_console(void)
    211 {
    212 #ifdef CONFIG_FB
    213         if (vesa_present())
    214                 vesa_redraw();
    215         else
    216 #endif
    217 #ifdef CONFIG_EGA
    218                 ega_redraw();
    219 #else
    220                 {}
    221 #endif
    222 }
    223 
    224 /** Return console to userspace
    225  *
    226  */
    227 void arch_release_console(void)
    228 {
    229210}
    230211
  • kernel/arch/ia64/include/drivers/ski.h

    r90c8b8d ra71c158  
    4444} ski_instance_t;
    4545
    46 extern void skiout_init(void);
     46extern outdev_t *skiout_init(void);
    4747
    4848extern ski_instance_t *skiin_init(void);
    4949extern void skiin_wire(ski_instance_t *, indev_t *);
    50 extern void ski_kbd_grab(void);
    51 extern void ski_kbd_release(void);
    5250
    5351#endif
  • kernel/arch/ia64/src/drivers/ski.c

    r90c8b8d ra71c158  
    4747enum {
    4848        /** Interval between polling in microseconds */
    49         POLL_INTERVAL =  10000,  /* 0.01 s */
    50 
     49        POLL_INTERVAL = 10000,  /* 0.01 s */
     50       
    5151        /** Max. number of characters to pull out at a time */
    52         POLL_LIMIT    =    30,
    53 
    54         SKI_INIT_CONSOLE  = 20,
    55         SKI_GETCHAR       = 21,
    56         SKI_PUTCHAR       = 31
     52        POLL_LIMIT = 30,
     53       
     54        SKI_INIT_CONSOLE = 20,
     55        SKI_GETCHAR      = 21,
     56        SKI_PUTCHAR      = 31
    5757};
    5858
    5959static void ski_putchar(outdev_t *, const wchar_t, bool);
    6060
    61 static outdev_operations_t skiout_ops = {
    62         .write = ski_putchar
     61static outdev_operations_t skidev_ops = {
     62        .write = ski_putchar,
     63        .redraw = NULL
    6364};
    6465
    65 static outdev_t skiout;            /**< Ski output device. */
    66 static bool initialized = false;
    67 static bool kbd_disabled = false;
     66static ski_instance_t *instance = NULL;
     67
     68/** Ask debug console if a key was pressed.
     69 *
     70 * Use SSC (Simulator System Call) to
     71 * get character from debug console.
     72 *
     73 * This call is non-blocking.
     74 *
     75 * @return ASCII code of pressed key or 0 if no key pressed.
     76 *
     77 */
     78static wchar_t ski_getchar(void)
     79{
     80        uint64_t ch;
     81       
     82        asm volatile (
     83                "mov r15 = %1\n"
     84                "break 0x80000;;\n"  /* modifies r8 */
     85                "mov %0 = r8;;\n"
     86               
     87                : "=r" (ch)
     88                : "i" (SKI_GETCHAR)
     89                : "r15", "r8"
     90        );
     91       
     92        return (wchar_t) ch;
     93}
     94
     95/** Ask keyboard if a key was pressed.
     96 *
     97 * If so, it will repeat and pull up to POLL_LIMIT characters.
     98 */
     99static void poll_keyboard(ski_instance_t *instance)
     100{
     101        if (silent)
     102                return;
     103       
     104        int count = POLL_LIMIT;
     105       
     106        while (count > 0) {
     107                wchar_t ch = ski_getchar();
     108               
     109                if (ch == '\0')
     110                        break;
     111               
     112                indev_push_character(instance->srlnin, ch);
     113                --count;
     114        }
     115}
     116
     117/** Kernel thread for polling keyboard. */
     118static void kskipoll(void *arg)
     119{
     120        ski_instance_t *instance = (ski_instance_t *) arg;
     121       
     122        while (true) {
     123                if (!silent)
     124                        poll_keyboard(instance);
     125               
     126                thread_usleep(POLL_INTERVAL);
     127        }
     128}
    68129
    69130/** Initialize debug console
     
    75136static void ski_init(void)
    76137{
    77         if (initialized)
     138        if (instance)
    78139                return;
    79140       
     
    86147        );
    87148       
    88         initialized = true;
     149        instance = malloc(sizeof(ski_instance_t), FRAME_ATOMIC);
     150       
     151        if (instance) {
     152                instance->thread = thread_create(kskipoll, instance, TASK, 0,
     153                    "kskipoll", true);
     154               
     155                if (!instance->thread) {
     156                        free(instance);
     157                        instance = NULL;
     158                        return;
     159                }
     160               
     161                instance->srlnin = NULL;
     162        }
    89163}
    90164
     
    124198}
    125199
    126 void skiout_init(void)
     200outdev_t *skiout_init(void)
    127201{
    128202        ski_init();
    129        
    130         outdev_initialize("skiout", &skiout, &skiout_ops);
    131         stdout_wire(&skiout);
    132        
    133         sysinfo_set_item_val("fb", NULL, false);
    134 }
    135 
    136 /** Ask debug console if a key was pressed.
    137  *
    138  * Use SSC (Simulator System Call) to
    139  * get character from debug console.
    140  *
    141  * This call is non-blocking.
    142  *
    143  * @return ASCII code of pressed key or 0 if no key pressed.
    144  *
    145  */
    146 static wchar_t ski_getchar(void)
    147 {
    148         uint64_t ch;
    149        
    150         asm volatile (
    151                 "mov r15 = %1\n"
    152                 "break 0x80000;;\n"  /* modifies r8 */
    153                 "mov %0 = r8;;\n"
    154                
    155                 : "=r" (ch)
    156                 : "i" (SKI_GETCHAR)
    157                 : "r15", "r8"
    158         );
    159        
    160         return (wchar_t) ch;
    161 }
    162 
    163 /** Ask keyboard if a key was pressed.
    164  *
    165  * If so, it will repeat and pull up to POLL_LIMIT characters.
    166  */
    167 static void poll_keyboard(ski_instance_t *instance)
    168 {
    169         wchar_t ch;
    170         int count;
    171 
    172         if (kbd_disabled)
    173                 return;
    174 
    175         count = POLL_LIMIT;
    176 
    177         while (count > 0) {
    178                 ch = ski_getchar();
    179 
    180                 if (ch == '\0')
    181                         break;
    182 
    183                 indev_push_character(instance->srlnin, ch);
    184                 --count;
    185         }
    186 }
    187 
    188 /** Kernel thread for polling keyboard. */
    189 static void kskipoll(void *arg)
    190 {
    191         ski_instance_t *instance = (ski_instance_t *) arg;
    192        
    193         while (true) {
    194                 if (!silent)
    195                         poll_keyboard(instance);
    196                
    197                 thread_usleep(POLL_INTERVAL);
    198         }
     203        if (!instance)
     204                return NULL;
     205       
     206        outdev_t *skidev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
     207        if (!skidev)
     208                return NULL;
     209       
     210        outdev_initialize("skidev", skidev, &skidev_ops);
     211        skidev->data = instance;
     212       
     213        if (!fb_exported) {
     214                /*
     215                 * This is the necessary evil until the userspace driver is entirely
     216                 * self-sufficient.
     217                 */
     218                sysinfo_set_item_val("fb", NULL, false);
     219               
     220                fb_exported = true;
     221        }
     222       
     223        return skidev;
    199224}
    200225
     
    202227{
    203228        ski_init();
    204        
    205         ski_instance_t *instance =
    206             malloc(sizeof(ski_instance_t), FRAME_ATOMIC);
    207        
    208         if (instance) {
    209                 instance->thread = thread_create(kskipoll, instance, TASK, 0,
    210                     "kskipoll", true);
    211                
    212                 if (!instance->thread) {
    213                         free(instance);
    214                         return NULL;
    215                 }
    216                
    217                 instance->srlnin = NULL;
    218         }
    219        
    220229        return instance;
    221230}
     
    233242}
    234243
    235 void ski_kbd_grab(void)
    236 {
    237         kbd_disabled = false;
    238 }
    239 
    240 void ski_kbd_release(void)
    241 {
    242         kbd_disabled = true;
    243 }
    244 
    245244/** @}
    246245 */
  • kernel/arch/ia64/src/ia64.c

    r90c8b8d ra71c158  
    160160        }
    161161       
    162         skiout_init();
     162        outdev_t *skidev = skiout_init();
     163        if (skidev)
     164                stdout_wire(skidev);
    163165#endif
    164166       
    165167#ifdef CONFIG_EGA
    166         ega_init(EGA_BASE, EGA_VIDEORAM);
     168        outdev_t *egadev = ega_init(EGA_BASE, EGA_VIDEORAM);
     169        if (egadev)
     170                stdout_wire(egadev);
    167171#endif
    168172       
     
    249253unative_t sys_tls_set(unative_t addr)
    250254{
    251         return 0;
    252 }
    253 
    254 /** Acquire console back for kernel
    255  *
    256  */
    257 void arch_grab_console(void)
    258 {
    259 #ifdef MACHINE_ski
    260         ski_kbd_grab();
    261 #endif
    262 }
    263 
    264 /** Return console to userspace
    265  *
    266  */
    267 void arch_release_console(void)
    268 {
    269 #ifdef MACHINE_ski
    270         ski_kbd_release();
    271 #endif
     255        return 0;
    272256}
    273257
  • kernel/arch/mips32/src/mips32.c

    r90c8b8d ra71c158  
    144144                .visual = VISUAL_RGB_8_8_8,
    145145        };
    146         fb_init(&gxemul_prop);
    147 #else
     146       
     147        outdev_t *fbdev = fb_init(&gxemul_prop);
     148        if (fbdev)
     149                stdout_wire(fbdev);
     150#endif
     151
    148152#ifdef CONFIG_MIPS_PRN
    149         dsrlnout_init((ioport8_t *) MSIM_KBD_ADDRESS);
    150 #endif /* CONFIG_MIPS_PRN */
    151 #endif /* CONFIG_FB */
     153        outdev_t *dsrlndev = dsrlnout_init((ioport8_t *) MSIM_KBD_ADDRESS);
     154        if (dsrlndev)
     155                stdout_wire(dsrlndev);
     156#endif
    152157}
    153158
     
    252257}
    253258
    254 void arch_grab_console(void)
    255 {
    256 #ifdef CONFIG_FB
    257         fb_redraw();
    258 #endif
    259 }
    260 
    261 /** Return console to userspace
    262  *
    263  */
    264 void arch_release_console(void)
    265 {
    266 }
    267 
    268259/** @}
    269260 */
  • kernel/arch/ppc32/src/ppc32.c

    r90c8b8d ra71c158  
    143143                        .visual = visual,
    144144                };
    145                 fb_init(&fb_prop);
    146         }
    147        
    148         /* Consider only a single device for now */
    149         return false;
     145               
     146                outdev_t *fbdev = fb_init(&fb_prop);
     147                if (fbdev)
     148                        stdout_wire(fbdev);
     149        }
     150       
     151        return true;
    150152}
    151153
     
    235237}
    236238
    237 /** Acquire console back for kernel
    238  *
    239  */
    240 void arch_grab_console(void)
    241 {
    242 #ifdef CONFIG_FB
    243         fb_redraw();
    244 #endif
    245 }
    246 
    247 /** Return console to userspace
    248  *
    249  */
    250 void arch_release_console(void)
    251 {
    252 }
    253 
    254239/** Construct function pointer
    255240 *
  • kernel/arch/sparc64/include/drivers/scr.h

    r90c8b8d ra71c158  
    2727 */
    2828
    29 /** @addtogroup sparc64 
     29/** @addtogroup sparc64
    3030 * @{
    3131 */
     
    5050
    5151extern void scr_init(ofw_tree_node_t *node);
    52 extern void scr_redraw(void);
    5352
    5453#endif
  • kernel/arch/sparc64/include/drivers/sgcn.h

    r90c8b8d ra71c158  
    3939#include <console/chardev.h>
    4040#include <proc/thread.h>
     41#include <synch/spinlock.h>
    4142
    4243/* number of bytes in the TOC magic, including the NULL-terminator */
    43 #define TOC_MAGIC_BYTES         8
     44#define TOC_MAGIC_BYTES  8
    4445
    4546/* number of bytes in the TOC key, including the NULL-terminator */
    46 #define TOC_KEY_SIZE            8
     47#define TOC_KEY_SIZE  8
    4748
    4849/* maximum number of entries in the SRAM table of contents */
    49 #define MAX_TOC_ENTRIES         32
     50#define MAX_TOC_ENTRIES  32
    5051
    5152/* number of bytes in the SGCN buffer magic, including the NULL-terminator */
    52 #define SGCN_MAGIC_BYTES        4
     53#define SGCN_MAGIC_BYTES  4
    5354
    5455/**
    5556 * Entry in the SRAM table of contents. Describes one segment of the SRAM
    5657 * which serves a particular purpose (e.g. OBP serial console, Solaris serial
    57  * console, Solaris mailbox,...). 
     58 * console, Solaris mailbox,...).
    5859 */
    5960typedef struct {
     
    8485/**
    8586 * SGCN buffer header. It is placed at the very beginning of the SGCN
    86  * buffer. 
     87 * buffer.
    8788 */
    8889typedef struct {
     
    104105        /** offset within the SGCN buffer of the input buffer write pointer */
    105106        uint32_t in_wrptr;
    106 
     107       
    107108        /** offset within the SGCN buffer of the output buffer start */
    108109        uint32_t out_begin;
     
    119120
    120121typedef struct {
     122        /** Starting address of SRAM */
     123        uintptr_t sram_begin;
     124       
     125        /** Starting address of the SGCN buffer */
     126        uintptr_t buffer_begin;
     127       
     128        /**
     129         * Ensure that writing to the buffer and consequent
     130         * update of the write pointer are one atomic operation.
     131         */
     132        SPINLOCK_DECLARE(output_lock);
     133       
     134        /**
     135         * Prevent the input buffer read/write pointers from
     136         * getting to inconsistent state.
     137         */
     138        SPINLOCK_DECLARE(input_lock);
     139       
    121140        thread_t *thread;
    122141        indev_t *srlnin;
    123142} sgcn_instance_t;
    124143
    125 extern void sgcn_grab(void);
    126 extern void sgcn_release(void);
    127144extern sgcn_instance_t *sgcnin_init(void);
    128145extern void sgcnin_wire(sgcn_instance_t *, indev_t *);
    129 extern void sgcnout_init(void);
     146extern outdev_t *sgcnout_init(void);
    130147
    131148#endif
  • kernel/arch/sparc64/src/console.c

    r90c8b8d ra71c158  
    103103        }
    104104#endif
     105       
    105106#ifdef CONFIG_SGCN_PRN
    106         sgcnout_init();
     107        outdev_t *sgcndev = sgcnout_init();
     108        if (sgcndev)
     109                stdout_wire(sgcndev);
    107110#endif
    108111}
     
    131134}
    132135
    133 
    134 /** Acquire console back for kernel
    135  *
    136  */
    137 void arch_grab_console(void)
    138 {
    139 #ifdef CONFIG_FB
    140         scr_redraw();
    141 #endif
    142        
    143 #ifdef CONFIG_SGCN_KBD
    144         sgcn_grab();
    145 #endif
    146 }
    147 
    148 /** Return console to userspace
    149  *
    150  */
    151 void arch_release_console(void)
    152 {
    153 #ifdef CONFIG_SGCN_KBD
    154         sgcn_release();
    155 #endif
    156 }
    157 
    158136/** @}
    159137 */
  • kernel/arch/sparc64/src/drivers/scr.c

    r90c8b8d ra71c158  
    4040#include <genarch/fb/fb.h>
    4141#include <genarch/fb/visuals.h>
     42#include <console/chardev.h>
     43#include <console/console.h>
    4244#include <arch/types.h>
    4345#include <string.h>
     
    238240                .visual = visual,
    239241        };
    240         fb_init(&props);
     242       
     243        outdev_t *fbdev = fb_init(&props);
     244        if (fbdev)
     245                stdout_wire(fbdev);
    241246}
    242247
    243 void scr_redraw(void)
    244 {
    245         fb_redraw();
    246 }
    247 
    248248/** @}
    249249 */
  • kernel/arch/sparc64/src/drivers/sgcn.c

    r90c8b8d ra71c158  
    4949#include <synch/spinlock.h>
    5050
    51 #define POLL_INTERVAL           10000
     51#define POLL_INTERVAL  10000
    5252
    5353/*
     
    5757 * not sure whether this value is valid generally.
    5858 */
    59 #define SBBC_START              0x63000000000
     59#define SBBC_START  0x63000000000
    6060
    6161/* offset of SRAM within the SBBC memory */
    62 #define SBBC_SRAM_OFFSET        0x900000
     62#define SBBC_SRAM_OFFSET  0x900000
    6363
    6464/* size (in bytes) of the physical memory area which will be mapped */
    65 #define MAPPED_AREA_SIZE        (128 * 1024)
     65#define MAPPED_AREA_SIZE  (128 * 1024)
    6666
    6767/* magic string contained at the beginning of SRAM */
    68 #define SRAM_TOC_MAGIC          "TOCSRAM"
     68#define SRAM_TOC_MAGIC  "TOCSRAM"
    6969
    7070/*
     
    7878 * Therefore HelenOS needs to make no such arrangements any more.
    7979 */
    80 #define CONSOLE_KEY             "OBPCONS"
     80#define CONSOLE_KEY  "OBPCONS"
    8181
    8282/* magic string contained at the beginning of the console buffer */
    83 #define SGCN_BUFFER_MAGIC       "CON"
     83#define SGCN_BUFFER_MAGIC  "CON"
    8484
    8585/*
     
    8787 * offset from the SRAM beginning.
    8888 */
    89 #define SRAM(type, offset)      ((type *) (sram_begin + (offset)))
     89#define SRAM(type, offset)  ((type *) (instance->sram_begin + (offset)))
    9090
    9191/* Returns a pointer to the SRAM table of contents. */
    92 #define SRAM_TOC                (SRAM(iosram_toc_t, 0))
     92#define SRAM_TOC  (SRAM(iosram_toc_t, 0))
    9393
    9494/*
     
    9797 */
    9898#define SGCN_BUFFER(type, offset) \
    99         ((type *) (sgcn_buffer_begin + (offset)))
     99        ((type *) (instance->buffer_begin + (offset)))
    100100
    101101/** Returns a pointer to the console buffer header. */
    102 #define SGCN_BUFFER_HEADER      (SGCN_BUFFER(sgcn_buffer_header_t, 0))
    103 
    104 /** starting address of SRAM, will be set by the init_sram_begin function */
    105 static uintptr_t sram_begin;
    106 
    107 /**
    108  * starting address of the SGCN buffer, will be set by the
    109  * init_sgcn_buffer_begin function
    110  */
    111 static uintptr_t sgcn_buffer_begin;
    112 
    113 /* true iff the kernel driver should ignore pressed keys */
    114 static bool kbd_disabled;
    115 
    116 /*
    117  * Ensures that writing to the buffer and consequent update of the write pointer
    118  * are together one atomic operation.
    119  */
    120 SPINLOCK_INITIALIZE(sgcn_output_lock);
    121 
    122 /*
    123  * Prevents the input buffer read/write pointers from getting to inconsistent
    124  * state.
    125  */
    126 SPINLOCK_INITIALIZE(sgcn_input_lock);
    127 
    128 
    129 /* functions referenced from definitions of I/O operations structures */
     102#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
     103
    130104static void sgcn_putchar(outdev_t *, const wchar_t, bool);
    131105
    132 /** SGCN output device operations */
    133 static outdev_operations_t sgcnout_ops = {
    134         .write = sgcn_putchar
     106static outdev_operations_t sgcndev_ops = {
     107        .write = sgcn_putchar,
     108        .redraw = NULL
    135109};
    136110
    137 static outdev_t sgcnout;        /**< SGCN output device. */
     111static sgcn_instance_t *instance = NULL;
    138112
    139113/**
     
    158132static void init_sram_begin(void)
    159133{
    160         ofw_tree_node_t *chosen;
    161         ofw_tree_property_t *iosram_toc;
    162         uintptr_t sram_begin_physical;
    163 
    164         chosen = ofw_tree_lookup("/chosen");
     134        ASSERT(instance)
     135       
     136        ofw_tree_node_t *chosen = ofw_tree_lookup("/chosen");
    165137        if (!chosen)
    166138                panic("Cannot find '/chosen'.");
    167 
    168         iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
     139       
     140        ofw_tree_property_t *iosram_toc =
     141            ofw_tree_getprop(chosen, "iosram-toc");
    169142        if (!iosram_toc)
    170143                panic("Cannot find property 'iosram-toc'.");
    171144        if (!iosram_toc->value)
    172145                panic("Cannot find SRAM TOC.");
    173 
    174         sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
     146       
     147        uintptr_t sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
    175148            + *((uint32_t *) iosram_toc->value);
    176         sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
     149        instance->sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
    177150       
    178151        register_sram(sram_begin_physical);
     152}
     153
     154/**
     155 * Function regularly called by the keyboard polling thread. Finds out whether
     156 * there are some unread characters in the input queue. If so, it picks them up
     157 * and sends them to the upper layers of HelenOS.
     158 */
     159static void sgcn_poll(sgcn_instance_t *instance)
     160{
     161        uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
     162        uint32_t end = SGCN_BUFFER_HEADER->in_end;
     163        uint32_t size = end - begin;
     164       
     165        if (silent)
     166                return;
     167       
     168        spinlock_lock(&instance->input_lock);
     169       
     170        /* we need pointers to volatile variables */
     171        volatile char *buf_ptr = (volatile char *)
     172            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
     173        volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
     174        volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
     175       
     176        while (*in_rdptr_ptr != *in_wrptr_ptr) {
     177                buf_ptr = (volatile char *)
     178                    SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
     179                char c = *buf_ptr;
     180                *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
     181               
     182                indev_push_character(instance->srlnin, c);
     183        }
     184       
     185        spinlock_unlock(&instance->input_lock);
     186}
     187
     188/**
     189 * Polling thread function.
     190 */
     191static void ksgcnpoll(void *instance) {
     192        while (true) {
     193                if (!silent)
     194                        sgcn_poll(instance);
     195               
     196                thread_usleep(POLL_INTERVAL);
     197        }
    179198}
    180199
     
    190209 * under the sram.buffer.offset sysinfo key.
    191210 */
    192 static void sgcn_buffer_begin_init(void)
    193 {
    194         static bool initialized;
    195        
    196         if (initialized)
     211static void sgcn_init(void)
     212{
     213        if (instance)
    197214                return;
    198 
    199         init_sram_begin();
    200                
    201         ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
    202        
    203         /* lookup TOC entry with the correct key */
    204         uint32_t i;
    205         for (i = 0; i < MAX_TOC_ENTRIES; i++) {
    206                 if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
    207                         break;
    208         }
    209         ASSERT(i < MAX_TOC_ENTRIES);
    210        
    211         sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
    212        
    213         sysinfo_set_item_val("sram.buffer.offset", NULL,
    214             SRAM_TOC->keys[i].offset);
    215        
    216         initialized = true;
     215       
     216        instance = malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC);
     217       
     218        if (instance) {
     219                instance->thread = thread_create(ksgcnpoll, instance, TASK, 0,
     220                    "ksgcnpoll", true);
     221               
     222                if (!instance->thread) {
     223                        free(instance);
     224                        instance = NULL;
     225                        return;
     226                }
     227               
     228                init_sram_begin();
     229               
     230                ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
     231               
     232                /* Lookup TOC entry with the correct key */
     233                uint32_t i;
     234                for (i = 0; i < MAX_TOC_ENTRIES; i++) {
     235                        if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
     236                                break;
     237                }
     238                ASSERT(i < MAX_TOC_ENTRIES);
     239               
     240                instance->buffer_begin =
     241                    instance->sram_begin + SRAM_TOC->keys[i].offset;
     242               
     243                sysinfo_set_item_val("sram.buffer.offset", NULL,
     244                    SRAM_TOC->keys[i].offset);
     245               
     246                instance->srlnin = NULL;
     247        }
    217248}
    218249
     
    228259        uint32_t size = end - begin;
    229260       
    230         /* we need pointers to volatile variables */
     261        /* We need pointers to volatile variables */
    231262        volatile char *buf_ptr = (volatile char *)
    232263            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
    233264        volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
    234265        volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
    235 
     266       
    236267        /*
    237268         * Write the character and increment the write pointer modulo the
     
    249280         */
    250281        uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
    251         while (*out_rdptr_ptr == new_wrptr)
    252                 ;
     282        while (*out_rdptr_ptr == new_wrptr);
     283       
    253284        *buf_ptr = c;
    254285        *out_wrptr_ptr = new_wrptr;
     
    259290 * character is converted to CRLF.
    260291 */
    261 static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent)
     292static void sgcn_putchar(outdev_t *dev, const wchar_t ch, bool silent)
    262293{
    263294        if (!silent) {
    264                 spinlock_lock(&sgcn_output_lock);
     295                spinlock_lock(&instance->output_lock);
    265296               
    266297                if (ascii_check(ch)) {
     
    271302                        sgcn_do_putchar(U_SPECIAL);
    272303               
    273                 spinlock_unlock(&sgcn_output_lock);
    274         }
    275 }
    276 
    277 /**
    278  * Grabs the input for kernel.
    279  */
    280 void sgcn_grab(void)
    281 {
    282         kbd_disabled = false;
    283 }
    284 
    285 /**
    286  * Releases the input so that userspace can use it.
    287  */
    288 void sgcn_release(void)
    289 {
    290         kbd_disabled = true;
    291 }
    292 
    293 /**
    294  * Function regularly called by the keyboard polling thread. Finds out whether
    295  * there are some unread characters in the input queue. If so, it picks them up
    296  * and sends them to the upper layers of HelenOS.
    297  */
    298 static void sgcn_poll(sgcn_instance_t *instance)
    299 {
    300         uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
    301         uint32_t end = SGCN_BUFFER_HEADER->in_end;
    302         uint32_t size = end - begin;
    303 
    304         if (kbd_disabled)
    305                 return;
    306 
    307         spinlock_lock(&sgcn_input_lock);
    308        
    309         /* we need pointers to volatile variables */
    310         volatile char *buf_ptr = (volatile char *)
    311             SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
    312         volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
    313         volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
    314        
    315         while (*in_rdptr_ptr != *in_wrptr_ptr) {
    316                 buf_ptr = (volatile char *)
    317                     SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
    318                 char c = *buf_ptr;
    319                 *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
    320                        
    321                 indev_push_character(instance->srlnin, c);     
    322         }       
    323 
    324         spinlock_unlock(&sgcn_input_lock);
    325 }
    326 
    327 /**
    328  * Polling thread function.
    329  */
    330 static void ksgcnpoll(void *instance) {
    331         while (1) {
    332                 if (!silent)
    333                         sgcn_poll(instance);
    334                 thread_usleep(POLL_INTERVAL);
     304                spinlock_unlock(&instance->output_lock);
    335305        }
    336306}
     
    341311sgcn_instance_t *sgcnin_init(void)
    342312{
    343         sgcn_buffer_begin_init();
    344        
    345         sgcn_instance_t *instance =
    346             malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC);
    347        
    348         if (instance) {
    349                 instance->srlnin = NULL;
    350                 instance->thread = thread_create(ksgcnpoll, instance, TASK, 0,
    351                     "ksgcnpoll", true);
    352                
    353                 if (!instance->thread) {
    354                         free(instance);
    355                         return NULL;
    356                 }
    357         }
    358        
     313        sgcn_init();
    359314        return instance;
    360315}
     
    364319        ASSERT(instance);
    365320        ASSERT(srlnin);
    366 
     321       
    367322        instance->srlnin = srlnin;
    368323        thread_ready(instance->thread);
    369 
     324       
    370325        sysinfo_set_item_val("kbd", NULL, true);
    371326}
     
    374329 * A public function which initializes output to the Serengeti console.
    375330 */
    376 void sgcnout_init(void)
    377 {
    378         sgcn_buffer_begin_init();
    379 
    380         sysinfo_set_item_val("fb.kind", NULL, 4);
    381 
    382         outdev_initialize("sgcnout", &sgcnout, &sgcnout_ops);
    383         stdout_wire(&sgcnout);
     331outdev_t *sgcnout_init(void)
     332{
     333        sgcn_init();
     334        if (!instance)
     335                return NULL;
     336       
     337        outdev_t *sgcndev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
     338        if (!sgcndev)
     339                return NULL;
     340       
     341        outdev_initialize("sgcndev", sgcndev, &sgcndev_ops);
     342        sgcndev->data = instance;
     343       
     344        if (!fb_exported) {
     345                /*
     346                 * This is the necessary evil until the userspace driver is entirely
     347                 * self-sufficient.
     348                 */
     349                sysinfo_set_item_val("fb.kind", NULL, 4);
     350               
     351                fb_exported = true;
     352        }
     353       
     354        return sgcndev;
    384355}
    385356
  • kernel/genarch/include/drivers/dsrln/dsrlnout.h

    r90c8b8d ra71c158  
    4040#include <arch/types.h>
    4141#include <typedefs.h>
     42#include <console/chardev.h>
    4243
    43 extern void dsrlnout_init(ioport8_t *);
     44extern outdev_t *dsrlnout_init(ioport8_t *);
    4445
    4546#endif
  • kernel/genarch/include/drivers/ega/ega.h

    r90c8b8d ra71c158  
    3838#include <arch/types.h>
    3939#include <typedefs.h>
     40#include <console/chardev.h>
    4041
    4142#define EGA_COLS       80
     
    4849#define EGA_DATA_REG   1
    4950
    50 extern void ega_redraw(void);
    51 extern void ega_init(ioport8_t *, uintptr_t);
     51extern outdev_t *ega_init(ioport8_t *, uintptr_t);
    5252
    5353#endif
  • kernel/genarch/include/fb/fb.h

    r90c8b8d ra71c158  
    3737
    3838#include <arch/types.h>
    39 #include <synch/spinlock.h>
     39#include <console/chardev.h>
     40#include <genarch/fb/visuals.h>
    4041
    4142/**
     
    4546        /** Physical address of the framebuffer device. */
    4647        uintptr_t addr;
    47 
     48       
    4849        /**
    4950         * Address where the first (top left) pixel is mapped,
     
    5152         */
    5253        unsigned int offset;
    53 
     54       
    5455        /** Screen width in pixels. */
    5556        unsigned int x;
    56 
     57       
    5758        /** Screen height in pixels. */
    5859        unsigned int y;
    59 
     60       
    6061        /** Bytes per one scanline. */
    6162        unsigned int scan;
    62 
     63       
    6364        /** Color model. */
    64         unsigned int visual;
     65        visual_t visual;
    6566} fb_properties_t;
    6667
    67 SPINLOCK_EXTERN(fb_lock);
    68 
    69 void fb_redraw(void);
    70 bool fb_init(fb_properties_t *props);
     68outdev_t *fb_init(fb_properties_t *props);
    7169
    7270#endif
  • kernel/genarch/src/drivers/dsrln/dsrlnout.c

    r90c8b8d ra71c158  
    3535 */
    3636
    37 
    3837#include <genarch/drivers/dsrln/dsrlnout.h>
    3938#include <console/chardev.h>
    4039#include <arch/asm.h>
     40#include <mm/slab.h>
    4141#include <console/console.h>
    4242#include <sysinfo/sysinfo.h>
    4343#include <string.h>
    4444
    45 static ioport8_t *dsrlnout_base;
     45typedef struct {
     46        ioport8_t *base;
     47} dsrlnout_instance_t;
    4648
    47 static void dsrlnout_putchar(outdev_t *dev __attribute__((unused)), const wchar_t ch, bool silent)
     49static void dsrlnout_putchar(outdev_t *dev, const wchar_t ch, bool silent)
    4850{
     51        dsrlnout_instance_t *instance = (dsrlnout_instance_t *) dev->data;
     52       
    4953        if (!silent) {
    5054                if (ascii_check(ch))
    51                         pio_write_8(dsrlnout_base, ch);
     55                        pio_write_8(instance->base, ch);
    5256                else
    53                         pio_write_8(dsrlnout_base, U_SPECIAL);
     57                        pio_write_8(instance->base, U_SPECIAL);
    5458        }
    5559}
    5660
    57 static outdev_t dsrlnout_console;
    58 static outdev_operations_t dsrlnout_ops = {
    59         .write = dsrlnout_putchar
     61static outdev_operations_t dsrlndev_ops = {
     62        .write = dsrlnout_putchar,
     63        .redraw = NULL
    6064};
    6165
    62 void dsrlnout_init(ioport8_t *base)
     66outdev_t *dsrlnout_init(ioport8_t *base)
    6367{
    64         /* Initialize the software structure. */
    65         dsrlnout_base = base;
     68        outdev_t *dsrlndev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
     69        if (!dsrlndev)
     70                return NULL;
    6671       
    67         outdev_initialize("dsrlnout", &dsrlnout_console, &dsrlnout_ops);
    68         stdout_wire(&dsrlnout_console);
     72        dsrlnout_instance_t *instance = malloc(sizeof(dsrlnout_instance_t), FRAME_ATOMIC);
     73        if (!instance) {
     74                free(dsrlndev);
     75                return NULL;
     76        }
    6977       
    70         sysinfo_set_item_val("fb", NULL, true);
    71         sysinfo_set_item_val("fb.kind", NULL, 3);
    72         sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(base));
     78        outdev_initialize("dsrlndev", dsrlndev, &dsrlndev_ops);
     79        dsrlndev->data = instance;
     80       
     81        instance->base = base;
     82       
     83        if (!fb_exported) {
     84                /*
     85                 * This is the necessary evil until the userspace driver is entirely
     86                 * self-sufficient.
     87                 */
     88                sysinfo_set_item_val("fb", NULL, true);
     89                sysinfo_set_item_val("fb.kind", NULL, 3);
     90                sysinfo_set_item_val("fb.address.physical", NULL, KA2PA(base));
     91               
     92                fb_exported = true;
     93        }
     94       
     95        return dsrlndev;
    7396}
    7497
  • kernel/genarch/src/drivers/ega/ega.c

    r90c8b8d ra71c158  
    5656 */
    5757
    58 SPINLOCK_INITIALIZE(egalock);
    59 static uint32_t ega_cursor;
    60 static uint8_t *videoram;
    61 static uint8_t *backbuf;
    62 static ioport8_t *ega_base;
    63 
    6458#define SPACE  0x20
    6559#define STYLE  0x1e
     
    6862#define EMPTY_CHAR  ((STYLE << 8) | SPACE)
    6963
     64typedef struct {
     65        SPINLOCK_DECLARE(lock);
     66       
     67        uint32_t cursor;
     68        uint8_t *addr;
     69        uint8_t *backbuf;
     70        ioport8_t *base;
     71} ega_instance_t;
     72
     73static void ega_putchar(outdev_t *dev, wchar_t ch, bool silent);
     74static void ega_redraw(outdev_t *dev);
     75
     76static outdev_operations_t egadev_ops = {
     77        .write = ega_putchar,
     78        .redraw = ega_redraw
     79};
     80
    7081static uint16_t ega_oem_glyph(const wchar_t ch)
    7182{
     
    427438 * This function takes care of scrolling.
    428439 */
    429 static void ega_check_cursor(bool silent)
    430 {
    431         if (ega_cursor < EGA_SCREEN)
     440static void ega_check_cursor(ega_instance_t *instance, bool silent)
     441{
     442        if (instance->cursor < EGA_SCREEN)
    432443                return;
    433444       
    434         memmove((void *) backbuf, (void *) (backbuf + EGA_COLS * 2),
     445        memmove((void *) instance->backbuf,
     446            (void *) (instance->backbuf + EGA_COLS * 2),
    435447            (EGA_SCREEN - EGA_COLS) * 2);
    436         memsetw(backbuf + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
     448        memsetw(instance->backbuf + (EGA_SCREEN - EGA_COLS) * 2,
     449            EGA_COLS, EMPTY_CHAR);
    437450       
    438451        if (!silent) {
    439                 memmove((void *) videoram, (void *) (videoram + EGA_COLS * 2),
     452                memmove((void *) instance->addr,
     453                    (void *) (instance->addr + EGA_COLS * 2),
    440454                    (EGA_SCREEN - EGA_COLS) * 2);
    441                 memsetw(videoram + (EGA_SCREEN - EGA_COLS) * 2, EGA_COLS, EMPTY_CHAR);
    442         }
    443        
    444         ega_cursor = ega_cursor - EGA_COLS;
    445 }
    446 
    447 static void ega_show_cursor(bool silent)
     455                memsetw(instance->addr + (EGA_SCREEN - EGA_COLS) * 2,
     456                    EGA_COLS, EMPTY_CHAR);
     457        }
     458       
     459        instance->cursor = instance->cursor - EGA_COLS;
     460}
     461
     462static void ega_show_cursor(ega_instance_t *instance, bool silent)
    448463{
    449464        if (!silent) {
    450                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
    451                 uint8_t stat = pio_read_8(ega_base + EGA_DATA_REG);
    452                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0a);
    453                 pio_write_8(ega_base + EGA_DATA_REG, stat & (~(1 << 5)));
    454         }
    455 }
    456 
    457 static void ega_move_cursor(bool silent)
     465                pio_write_8(instance->base + EGA_INDEX_REG, 0x0a);
     466                uint8_t stat = pio_read_8(instance->base + EGA_DATA_REG);
     467                pio_write_8(instance->base + EGA_INDEX_REG, 0x0a);
     468                pio_write_8(instance->base + EGA_DATA_REG, stat & (~(1 << 5)));
     469        }
     470}
     471
     472static void ega_move_cursor(ega_instance_t *instance, bool silent)
    458473{
    459474        if (!silent) {
    460                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
    461                 pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) ((ega_cursor >> 8) & 0xff));
    462                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
    463                 pio_write_8(ega_base + EGA_DATA_REG, (uint8_t) (ega_cursor & 0xff));
    464         }
    465 }
    466 
    467 static void ega_sync_cursor(bool silent)
     475                pio_write_8(instance->base + EGA_INDEX_REG, 0x0e);
     476                pio_write_8(instance->base + EGA_DATA_REG,
     477                    (uint8_t) ((instance->cursor >> 8) & 0xff));
     478                pio_write_8(instance->base + EGA_INDEX_REG, 0x0f);
     479                pio_write_8(instance->base + EGA_DATA_REG,
     480                    (uint8_t) (instance->cursor & 0xff));
     481        }
     482}
     483
     484static void ega_sync_cursor(ega_instance_t *instance, bool silent)
    468485{
    469486        if (!silent) {
    470                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0e);
    471                 uint8_t hi = pio_read_8(ega_base + EGA_DATA_REG);
    472                 pio_write_8(ega_base + EGA_INDEX_REG, 0x0f);
    473                 uint8_t lo = pio_read_8(ega_base + EGA_DATA_REG);
     487                pio_write_8(instance->base + EGA_INDEX_REG, 0x0e);
     488                uint8_t hi = pio_read_8(instance->base + EGA_DATA_REG);
     489                pio_write_8(instance->base + EGA_INDEX_REG, 0x0f);
     490                uint8_t lo = pio_read_8(instance->base + EGA_DATA_REG);
    474491               
    475                 ega_cursor = (hi << 8) | lo;
     492                instance->cursor = (hi << 8) | lo;
    476493        } else
    477                 ega_cursor = 0;
    478        
    479         if (ega_cursor >= EGA_SCREEN)
    480                 ega_cursor = 0;
    481        
    482         if ((ega_cursor % EGA_COLS) != 0)
    483                 ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
    484        
    485         memsetw(backbuf + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
     494                instance->cursor = 0;
     495       
     496        if (instance->cursor >= EGA_SCREEN)
     497                instance->cursor = 0;
     498       
     499        if ((instance->cursor % EGA_COLS) != 0)
     500                instance->cursor =
     501                    (instance->cursor + EGA_COLS) - instance->cursor % EGA_COLS;
     502       
     503        memsetw(instance->backbuf + instance->cursor * 2,
     504            EGA_SCREEN - instance->cursor, EMPTY_CHAR);
    486505       
    487506        if (!silent)
    488                 memsetw(videoram + ega_cursor * 2, EGA_SCREEN - ega_cursor, EMPTY_CHAR);
    489        
    490         ega_check_cursor(silent);
    491         ega_move_cursor(silent);
    492         ega_show_cursor(silent);
    493 }
    494 
    495 static void ega_display_char(wchar_t ch, bool silent)
     507                memsetw(instance->addr + instance->cursor * 2,
     508                    EGA_SCREEN - instance->cursor, EMPTY_CHAR);
     509       
     510        ega_check_cursor(instance, silent);
     511        ega_move_cursor(instance, silent);
     512        ega_show_cursor(instance, silent);
     513}
     514
     515static void ega_display_char(ega_instance_t *instance, wchar_t ch, bool silent)
    496516{
    497517        uint16_t index = ega_oem_glyph(ch);
     
    507527        }
    508528       
    509         backbuf[ega_cursor * 2] = glyph;
    510         backbuf[ega_cursor * 2 + 1] = style;
     529        instance->backbuf[instance->cursor * 2] = glyph;
     530        instance->backbuf[instance->cursor * 2 + 1] = style;
    511531       
    512532        if (!silent) {
    513                 videoram[ega_cursor * 2] = glyph;
    514                 videoram[ega_cursor * 2 + 1] = style;
    515         }
    516 }
    517 
    518 static void ega_putchar(outdev_t *dev __attribute__((unused)), wchar_t ch, bool silent)
    519 {
    520         ipl_t ipl;
    521        
    522         ipl = interrupts_disable();
    523         spinlock_lock(&egalock);
     533                instance->addr[instance->cursor * 2] = glyph;
     534                instance->addr[instance->cursor * 2 + 1] = style;
     535        }
     536}
     537
     538static void ega_putchar(outdev_t *dev, wchar_t ch, bool silent)
     539{
     540        ega_instance_t *instance = (ega_instance_t *) dev->data;
     541       
     542        ipl_t ipl = interrupts_disable();
     543        spinlock_lock(&instance->lock);
    524544       
    525545        switch (ch) {
    526546        case '\n':
    527                 ega_cursor = (ega_cursor + EGA_COLS) - ega_cursor % EGA_COLS;
     547                instance->cursor = (instance->cursor + EGA_COLS)
     548                    - instance->cursor % EGA_COLS;
    528549                break;
    529550        case '\t':
    530                 ega_cursor = (ega_cursor + 8) - ega_cursor % 8;
     551                instance->cursor = (instance->cursor + 8)
     552                    - instance->cursor % 8;
    531553                break;
    532554        case '\b':
    533                 if (ega_cursor % EGA_COLS)
    534                         ega_cursor--;
     555                if (instance->cursor % EGA_COLS)
     556                        instance->cursor--;
    535557                break;
    536558        default:
    537                 ega_display_char(ch, silent);
    538                 ega_cursor++;
     559                ega_display_char(instance, ch, silent);
     560                instance->cursor++;
    539561                break;
    540562        }
    541         ega_check_cursor(silent);
    542         ega_move_cursor(silent);
    543        
    544         spinlock_unlock(&egalock);
     563        ega_check_cursor(instance, silent);
     564        ega_move_cursor(instance, silent);
     565       
     566        spinlock_unlock(&instance->lock);
    545567        interrupts_restore(ipl);
    546568}
    547569
    548 static outdev_t ega_console;
    549 static outdev_operations_t ega_ops = {
    550         .write = ega_putchar
    551 };
    552 
    553 void ega_init(ioport8_t *base, uintptr_t videoram_phys)
    554 {
    555         /* Initialize the software structure. */
    556         ega_base = base;
    557        
    558         backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
    559         if (!backbuf)
    560                 panic("Unable to allocate backbuffer.");
    561        
    562         videoram = (uint8_t *) hw_map(videoram_phys, EGA_VRAM_SIZE);
     570static void ega_redraw(outdev_t *dev)
     571{
     572        ega_instance_t *instance = (ega_instance_t *) dev->data;
     573       
     574        ipl_t ipl = interrupts_disable();
     575        spinlock_lock(&instance->lock);
     576       
     577        memcpy(instance->addr, instance->backbuf, EGA_VRAM_SIZE);
     578        ega_move_cursor(instance, silent);
     579        ega_show_cursor(instance, silent);
     580       
     581        spinlock_unlock(&instance->lock);
     582        interrupts_restore(ipl);
     583}
     584
     585outdev_t *ega_init(ioport8_t *base, uintptr_t addr)
     586{
     587        outdev_t *egadev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
     588        if (!egadev)
     589                return NULL;
     590       
     591        ega_instance_t *instance = malloc(sizeof(ega_instance_t), FRAME_ATOMIC);
     592        if (!instance) {
     593                free(egadev);
     594                return NULL;
     595        }
     596       
     597        outdev_initialize("egadev", egadev, &egadev_ops);
     598        egadev->data = instance;
     599       
     600        spinlock_initialize(&instance->lock, "*ega_lock");
     601       
     602        instance->base = base;
     603        instance->addr = (uint8_t *) hw_map(addr, EGA_VRAM_SIZE);
     604        if (!instance->addr) {
     605                LOG("Unable to EGA video memory.");
     606                free(instance);
     607                free(egadev);
     608                return NULL;
     609        }
     610       
     611        instance->backbuf = (uint8_t *) malloc(EGA_VRAM_SIZE, 0);
     612        if (!instance->backbuf) {
     613                LOG("Unable to allocate backbuffer.");
     614                free(instance);
     615                free(egadev);
     616                return NULL;
     617        }
    563618       
    564619        /* Synchronize the back buffer and cursor position. */
    565         memcpy(backbuf, videoram, EGA_VRAM_SIZE);
    566         ega_sync_cursor(silent);
    567        
    568         outdev_initialize("ega", &ega_console, &ega_ops);
    569         stdout_wire(&ega_console);
    570        
    571         sysinfo_set_item_val("fb", NULL, true);
    572         sysinfo_set_item_val("fb.kind", NULL, 2);
    573         sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
    574         sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
    575         sysinfo_set_item_val("fb.blinking", NULL, true);
    576         sysinfo_set_item_val("fb.address.physical", NULL, videoram_phys);
    577 }
    578 
    579 void ega_redraw(void)
    580 {
    581         memcpy(videoram, backbuf, EGA_VRAM_SIZE);
    582         ega_move_cursor(silent);
    583         ega_show_cursor(silent);
     620        memcpy(instance->backbuf, instance->addr, EGA_VRAM_SIZE);
     621        ega_sync_cursor(instance, silent);
     622       
     623        if (!fb_exported) {
     624                /*
     625                 * This is the necessary evil until the userspace driver is entirely
     626                 * self-sufficient.
     627                 */
     628                sysinfo_set_item_val("fb", NULL, true);
     629                sysinfo_set_item_val("fb.kind", NULL, 2);
     630                sysinfo_set_item_val("fb.width", NULL, EGA_COLS);
     631                sysinfo_set_item_val("fb.height", NULL, EGA_ROWS);
     632                sysinfo_set_item_val("fb.blinking", NULL, true);
     633                sysinfo_set_item_val("fb.address.physical", NULL, addr);
     634               
     635                fb_exported = true;
     636        }
     637       
     638        return egadev;
    584639}
    585640
  • kernel/genarch/src/fb/fb.c

    r90c8b8d ra71c158  
    5353#include <byteorder.h>
    5454
    55 SPINLOCK_INITIALIZE(fb_lock);
    56 
    57 static uint8_t *fb_addr;
    58 static uint16_t *backbuf;
    59 static uint8_t *glyphs;
    60 static uint8_t *bgscan;
    61 
    62 static unsigned int xres;
    63 static unsigned int yres;
    64 
    65 static unsigned int ylogo;
    66 static unsigned int ytrim;
    67 static unsigned int rowtrim;
    68 
    69 static unsigned int scanline;
    70 static unsigned int glyphscanline;
    71 
    72 static unsigned int pixelbytes;
    73 static unsigned int glyphbytes;
    74 static unsigned int bgscanbytes;
    75 
    76 static unsigned int cols;
    77 static unsigned int rows;
    78 static unsigned int position = 0;
    79 
    8055#define BG_COLOR     0x000080
    8156#define FG_COLOR     0xffff00
    8257#define INV_COLOR    0xaaaaaa
    8358
    84 #define RED(x, bits)         (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
    85 #define GREEN(x, bits)       (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
    86 #define BLUE(x, bits)        (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
    87 
    88 #define COL2X(col)           ((col) * FONT_WIDTH)
    89 #define ROW2Y(row)           ((row) * FONT_SCANLINES)
    90 
    91 #define X2COL(x)             ((x) / FONT_WIDTH)
    92 #define Y2ROW(y)             ((y) / FONT_SCANLINES)
    93 
    94 #define FB_POS(x, y)         ((y) * scanline + (x) * pixelbytes)
    95 #define BB_POS(col, row)     ((row) * cols + (col))
    96 #define GLYPH_POS(glyph, y)  ((glyph) * glyphbytes + (y) * glyphscanline)
    97 
    98 
    99 static void (*rgb_conv)(void *, uint32_t);
     59#define RED(x, bits)    (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
     60#define GREEN(x, bits)  (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1))
     61#define BLUE(x, bits)   (((x) >> (8 - (bits))) & ((1 << (bits)) - 1))
     62
     63#define COL2X(col)  ((col) * FONT_WIDTH)
     64#define ROW2Y(row)  ((row) * FONT_SCANLINES)
     65
     66#define X2COL(x)  ((x) / FONT_WIDTH)
     67#define Y2ROW(y)  ((y) / FONT_SCANLINES)
     68
     69#define FB_POS(instance, x, y) \
     70        ((y) * (instance)->scanline + (x) * (instance)->pixelbytes)
     71
     72#define BB_POS(instance, col, row) \
     73        ((row) * (instance)->cols + (col))
     74
     75#define GLYPH_POS(instance, glyph, y) \
     76        ((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline)
     77
     78typedef void (* rgb_conv_t)(void *, uint32_t);
     79
     80typedef struct {
     81        SPINLOCK_DECLARE(lock);
     82       
     83        uint8_t *addr;
     84        uint16_t *backbuf;
     85        uint8_t *glyphs;
     86        uint8_t *bgscan;
     87       
     88        rgb_conv_t rgb_conv;
     89       
     90        unsigned int xres;
     91        unsigned int yres;
     92       
     93        unsigned int ylogo;
     94        unsigned int ytrim;
     95        unsigned int rowtrim;
     96       
     97        unsigned int scanline;
     98        unsigned int glyphscanline;
     99       
     100        unsigned int pixelbytes;
     101        unsigned int glyphbytes;
     102        unsigned int bgscanbytes;
     103       
     104        unsigned int cols;
     105        unsigned int rows;
     106       
     107        unsigned int position;
     108} fb_instance_t;
     109
     110static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent);
     111static void fb_redraw_internal(fb_instance_t *instance);
     112static void fb_redraw(outdev_t *dev);
     113
     114static outdev_operations_t fbdev_ops = {
     115        .write = fb_putchar,
     116        .redraw = fb_redraw
     117};
    100118
    101119/*
     
    169187            GREEN(rgb, 6) << 5 | BLUE(rgb, 5));
    170188}
    171 
    172189
    173190/** BGR 3:2:3
     
    179196 * and setting it to simulate the 8-bit truecolor.
    180197 *
    181  * Currently we set the palette on the ia32, amd64 and sparc64 port.
     198 * Currently we set the palette on the ia32, amd64, ppc32 and sparc64 port.
    182199 *
    183200 * Note that the byte is being inverted by this function. The reason is
     
    194211}
    195212
    196 
    197213/** Hide logo and refresh screen
    198214 *
    199215 */
    200 static void logo_hide(bool silent)
    201 {
    202         ylogo = 0;
    203         ytrim = yres;
    204         rowtrim = rows;
     216static void logo_hide(fb_instance_t *instance, bool silent)
     217{
     218        instance->ylogo = 0;
     219        instance->ytrim = instance->yres;
     220        instance->rowtrim = instance->rows;
     221       
    205222        if (!silent)
    206                 fb_redraw();
    207 }
    208 
     223                fb_redraw_internal(instance);
     224}
    209225
    210226/** Draw character at given position
    211227 *
    212228 */
    213 static void glyph_draw(uint16_t glyph, unsigned int col, unsigned int row, bool silent, bool overlay)
     229static void glyph_draw(fb_instance_t *instance, uint16_t glyph,
     230    unsigned int col, unsigned int row, bool silent, bool overlay)
    214231{
    215232        unsigned int x = COL2X(col);
     
    217234        unsigned int yd;
    218235       
    219         if (y >= ytrim)
    220                 logo_hide(silent);
     236        if (y >= instance->ytrim)
     237                logo_hide(instance, silent);
    221238       
    222239        if (!overlay)
    223                 backbuf[BB_POS(col, row)] = glyph;
     240                instance->backbuf[BB_POS(instance, col, row)] = glyph;
    224241       
    225242        if (!silent) {
    226243                for (yd = 0; yd < FONT_SCANLINES; yd++)
    227                         memcpy(&fb_addr[FB_POS(x, y + yd + ylogo)],
    228                             &glyphs[GLYPH_POS(glyph, yd)], glyphscanline);
    229         }
    230 }
    231 
     244                        memcpy(&instance->addr[FB_POS(instance, x, y + yd + instance->ylogo)],
     245                            &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
     246                            instance->glyphscanline);
     247        }
     248}
    232249
    233250/** Scroll screen down by one row
     
    235252 *
    236253 */
    237 static void screen_scroll(bool silent)
    238 {
    239         if (ylogo > 0) {
    240                 logo_hide(silent);
     254static void screen_scroll(fb_instance_t *instance, bool silent)
     255{
     256        if (instance->ylogo > 0) {
     257                logo_hide(instance, silent);
    241258                return;
    242259        }
     
    245262                unsigned int row;
    246263               
    247                 for (row = 0; row < rows; row++) {
     264                for (row = 0; row < instance->rows; row++) {
    248265                        unsigned int y = ROW2Y(row);
    249266                        unsigned int yd;
     
    253270                                unsigned int col;
    254271                               
    255                                 for (col = 0, x = 0; col < cols; col++,
    256                                     x += FONT_WIDTH) {
     272                                for (col = 0, x = 0; col < instance->cols;
     273                                    col++, x += FONT_WIDTH) {
    257274                                        uint16_t glyph;
    258275                                       
    259                                         if (row < rows - 1) {
    260                                                 if (backbuf[BB_POS(col, row)] ==
    261                                                     backbuf[BB_POS(col, row + 1)])
     276                                        if (row < instance->rows - 1) {
     277                                                if (instance->backbuf[BB_POS(instance, col, row)] ==
     278                                                    instance->backbuf[BB_POS(instance, col, row + 1)])
    262279                                                        continue;
    263280                                               
    264                                                 glyph = backbuf[BB_POS(col, row + 1)];
     281                                                glyph = instance->backbuf[BB_POS(instance, col, row + 1)];
    265282                                        } else
    266283                                                glyph = 0;
    267284                                       
    268                                         memcpy(&fb_addr[FB_POS(x, y + yd)],
    269                                             &glyphs[GLYPH_POS(glyph, yd)],
    270                                             glyphscanline);
     285                                        memcpy(&instance->addr[FB_POS(instance, x, y + yd)],
     286                                            &instance->glyphs[GLYPH_POS(instance, glyph, yd)],
     287                                            instance->glyphscanline);
    271288                                }
    272289                        }
     
    274291        }
    275292       
    276         memmove(backbuf, &backbuf[BB_POS(0, 1)], cols * (rows - 1) * sizeof(uint16_t));
    277         memsetw(&backbuf[BB_POS(0, rows - 1)], cols, 0);
    278 }
    279 
    280 
    281 static void cursor_put(bool silent)
    282 {
    283         unsigned int col = position % cols;
    284         unsigned int row = position / cols;
    285        
    286         glyph_draw(fb_font_glyph(U_CURSOR), col, row, silent, true);
    287 }
    288 
    289 
    290 static void cursor_remove(bool silent)
    291 {
    292         unsigned int col = position % cols;
    293         unsigned int row = position / cols;
    294        
    295         glyph_draw(backbuf[BB_POS(col, row)], col, row, silent, true);
    296 }
    297 
    298 
    299 /** Print character to screen
    300  *
    301  * Emulate basic terminal commands.
    302  *
    303  */
    304 static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent)
    305 {
    306         spinlock_lock(&fb_lock);
    307        
    308         switch (ch) {
    309         case '\n':
    310                 cursor_remove(silent);
    311                 position += cols;
    312                 position -= position % cols;
    313                 break;
    314         case '\r':
    315                 cursor_remove(silent);
    316                 position -= position % cols;
    317                 break;
    318         case '\b':
    319                 cursor_remove(silent);
    320                 if (position % cols)
    321                         position--;
    322                 break;
    323         case '\t':
    324                 cursor_remove(silent);
    325                 do {
    326                         glyph_draw(fb_font_glyph(' '), position % cols,
    327                             position / cols, silent, false);
    328                         position++;
    329                 } while ((position % 8) && (position < cols * rows));
    330                 break;
    331         default:
    332                 glyph_draw(fb_font_glyph(ch), position % cols,
    333                     position / cols, silent, false);
    334                 position++;
    335         }
    336        
    337         if (position >= cols * rows) {
    338                 position -= cols;
    339                 screen_scroll(silent);
    340         }
    341        
    342         cursor_put(silent);
    343        
    344         spinlock_unlock(&fb_lock);
    345 }
    346 
    347 static outdev_t fb_console;
    348 static outdev_operations_t fb_ops = {
    349         .write = fb_putchar
    350 };
    351 
     293        memmove(instance->backbuf, &instance->backbuf[BB_POS(instance, 0, 1)],
     294            instance->cols * (instance->rows - 1) * sizeof(uint16_t));
     295        memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)],
     296            instance->cols, 0);
     297}
     298
     299static void cursor_put(fb_instance_t *instance, bool silent)
     300{
     301        unsigned int col = instance->position % instance->cols;
     302        unsigned int row = instance->position / instance->cols;
     303       
     304        glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, silent, true);
     305}
     306
     307static void cursor_remove(fb_instance_t *instance, bool silent)
     308{
     309        unsigned int col = instance->position % instance->cols;
     310        unsigned int row = instance->position / instance->cols;
     311       
     312        glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)],
     313            col, row, silent, true);
     314}
    352315
    353316/** Render glyphs
     
    357320 *
    358321 */
    359 static void glyphs_render(void)
     322static void glyphs_render(fb_instance_t *instance)
    360323{
    361324        /* Prerender glyphs */
     
    376339                       
    377340                        for (x = 0; x < FONT_WIDTH; x++) {
    378                                 void *dst = &glyphs[GLYPH_POS(glyph, y) +
    379                                     x * pixelbytes];
     341                                void *dst =
     342                                    &instance->glyphs[GLYPH_POS(instance, glyph, y) +
     343                                    x * instance->pixelbytes];
    380344                                uint32_t rgb = (fb_font[glyph][y] &
    381345                                    (1 << (7 - x))) ? fg_color : BG_COLOR;
    382                                 rgb_conv(dst, rgb);
     346                                instance->rgb_conv(dst, rgb);
    383347                        }
    384348                }
     
    388352        unsigned int x;
    389353       
    390         for (x = 0; x < xres; x++)
    391                 rgb_conv(&bgscan[x * pixelbytes], BG_COLOR);
    392 }
    393 
    394 
    395 /** Refresh the screen
    396  *
    397  */
    398 void fb_redraw(void)
    399 {
    400         if (ylogo > 0) {
     354        for (x = 0; x < instance->xres; x++)
     355                instance->rgb_conv(&instance->bgscan[x * instance->pixelbytes], BG_COLOR);
     356}
     357
     358/** Print character to screen
     359 *
     360 * Emulate basic terminal commands.
     361 *
     362 */
     363static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent)
     364{
     365        fb_instance_t *instance = (fb_instance_t *) dev->data;
     366        spinlock_lock(&instance->lock);
     367       
     368        switch (ch) {
     369        case '\n':
     370                cursor_remove(instance, silent);
     371                instance->position += instance->cols;
     372                instance->position -= instance->position % instance->cols;
     373                break;
     374        case '\r':
     375                cursor_remove(instance, silent);
     376                instance->position -= instance->position % instance->cols;
     377                break;
     378        case '\b':
     379                cursor_remove(instance, silent);
     380                if (instance->position % instance->cols)
     381                        instance->position--;
     382                break;
     383        case '\t':
     384                cursor_remove(instance, silent);
     385                do {
     386                        glyph_draw(instance, fb_font_glyph(' '),
     387                            instance->position % instance->cols,
     388                            instance->position / instance->cols, silent, false);
     389                        instance->position++;
     390                } while ((instance->position % 8)
     391                    && (instance->position < instance->cols * instance->rows));
     392                break;
     393        default:
     394                glyph_draw(instance, fb_font_glyph(ch),
     395                    instance->position % instance->cols,
     396                    instance->position / instance->cols, silent, false);
     397                instance->position++;
     398        }
     399       
     400        if (instance->position >= instance->cols * instance->rows) {
     401                instance->position -= instance->cols;
     402                screen_scroll(instance, silent);
     403        }
     404       
     405        cursor_put(instance, silent);
     406       
     407        spinlock_unlock(&instance->lock);
     408}
     409
     410static void fb_redraw_internal(fb_instance_t *instance)
     411{
     412        if (instance->ylogo > 0) {
    401413                unsigned int y;
    402414               
     
    404416                        unsigned int x;
    405417                       
    406                         for (x = 0; x < xres; x++)
    407                                 rgb_conv(&fb_addr[FB_POS(x, y)],
     418                        for (x = 0; x < instance->xres; x++)
     419                                instance->rgb_conv(&instance->addr[FB_POS(instance, x, y)],
    408420                                    (x < LOGO_WIDTH) ?
    409421                                    fb_logo[y * LOGO_WIDTH + x] :
     
    414426        unsigned int row;
    415427       
    416         for (row = 0; row < rowtrim; row++) {
    417                 unsigned int y = ylogo + ROW2Y(row);
     428        for (row = 0; row < instance->rowtrim; row++) {
     429                unsigned int y = instance->ylogo + ROW2Y(row);
    418430                unsigned int yd;
    419431               
     
    422434                        unsigned int col;
    423435                       
    424                         for (col = 0, x = 0; col < cols;
     436                        for (col = 0, x = 0; col < instance->cols;
    425437                            col++, x += FONT_WIDTH) {
    426                                 uint16_t glyph = backbuf[BB_POS(col, row)];
    427                                 void *dst = &fb_addr[FB_POS(x, y + yd)];
    428                                 void *src = &glyphs[GLYPH_POS(glyph, yd)];
    429                                 memcpy(dst, src, glyphscanline);
     438                                uint16_t glyph =
     439                                    instance->backbuf[BB_POS(instance, col, row)];
     440                                void *dst = &instance->addr[FB_POS(instance, x, y + yd)];
     441                                void *src = &instance->glyphs[GLYPH_POS(instance, glyph, yd)];
     442                                memcpy(dst, src, instance->glyphscanline);
    430443                        }
    431444                }
    432445        }
    433446       
    434         if (COL2X(cols) < xres) {
     447        if (COL2X(instance->cols) < instance->xres) {
    435448                unsigned int y;
    436                 unsigned int size = (xres - COL2X(cols)) * pixelbytes;
    437                
    438                 for (y = ylogo; y < yres; y++)
    439                         memcpy(&fb_addr[FB_POS(COL2X(cols), y)], bgscan, size);
    440         }
    441        
    442         if (ROW2Y(rowtrim) + ylogo < yres) {
     449                unsigned int size =
     450                    (instance->xres - COL2X(instance->cols)) * instance->pixelbytes;
     451               
     452                for (y = instance->ylogo; y < instance->yres; y++)
     453                        memcpy(&instance->addr[FB_POS(instance, COL2X(instance->cols), y)],
     454                            instance->bgscan, size);
     455        }
     456       
     457        if (ROW2Y(instance->rowtrim) + instance->ylogo < instance->yres) {
    443458                unsigned int y;
    444459               
    445                 for (y = ROW2Y(rowtrim) + ylogo; y < yres; y++)
    446                         memcpy(&fb_addr[FB_POS(0, y)], bgscan, bgscanbytes);
    447         }
    448 }
    449 
     460                for (y = ROW2Y(instance->rowtrim) + instance->ylogo;
     461                    y < instance->yres; y++)
     462                        memcpy(&instance->addr[FB_POS(instance, 0, y)],
     463                            instance->bgscan, instance->bgscanbytes);
     464        }
     465}
     466
     467/** Refresh the screen
     468 *
     469 */
     470static void fb_redraw(outdev_t *dev)
     471{
     472        fb_instance_t *instance = (fb_instance_t *) dev->data;
     473       
     474        spinlock_lock(&instance->lock);
     475        fb_redraw_internal(instance);
     476        spinlock_unlock(&instance->lock);
     477}
    450478
    451479/** Initialize framebuffer as a output character device
    452480 *
    453  * @param addr   Physical address of the framebuffer
    454  * @param x      Screen width in pixels
    455  * @param y      Screen height in pixels
    456  * @param scan   Bytes per one scanline
    457  * @param visual Color model
    458  *
    459  */
    460 bool fb_init(fb_properties_t *props)
     481 */
     482outdev_t *fb_init(fb_properties_t *props)
    461483{
    462484        ASSERT(props);
     
    465487        ASSERT(props->scan > 0);
    466488       
     489        rgb_conv_t rgb_conv;
     490        unsigned int pixelbytes;
     491       
    467492        switch (props->visual) {
    468493        case VISUAL_INDIRECT_8:
     
    512537        default:
    513538                LOG("Unsupported visual.");
    514                 return false;
    515         }
    516        
    517         xres = props->x;
    518         yres = props->y;
    519         scanline = props->scan;
    520        
    521         cols = X2COL(xres);
    522         rows = Y2ROW(yres);
    523        
    524         if (yres > ylogo) {
    525                 ylogo = LOGO_HEIGHT;
    526                 rowtrim = rows - Y2ROW(ylogo);
    527                 if (ylogo % FONT_SCANLINES > 0)
    528                         rowtrim--;
    529                 ytrim = ROW2Y(rowtrim);
     539                return NULL;
     540        }
     541       
     542        outdev_t *fbdev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
     543        if (!fbdev)
     544                return NULL;
     545       
     546        fb_instance_t *instance = malloc(sizeof(fb_instance_t), FRAME_ATOMIC);
     547        if (!instance) {
     548                free(fbdev);
     549                return NULL;
     550        }
     551       
     552        outdev_initialize("fbdev", fbdev, &fbdev_ops);
     553        fbdev->data = instance;
     554       
     555        spinlock_initialize(&instance->lock, "*fb_lock");
     556        instance->rgb_conv = rgb_conv;
     557        instance->pixelbytes = pixelbytes;
     558        instance->xres = props->x;
     559        instance->yres = props->y;
     560        instance->scanline = props->scan;
     561        instance->position = 0;
     562       
     563        instance->cols = X2COL(instance->xres);
     564        instance->rows = Y2ROW(instance->yres);
     565       
     566        if (instance->yres > LOGO_HEIGHT) {
     567                instance->ylogo = LOGO_HEIGHT;
     568                instance->rowtrim = instance->rows - Y2ROW(instance->ylogo);
     569                if (instance->ylogo % FONT_SCANLINES > 0)
     570                        instance->rowtrim--;
     571                instance->ytrim = ROW2Y(instance->rowtrim);
    530572        } else {
    531                 ylogo = 0;
    532                 ytrim = yres;
    533                 rowtrim = rows;
    534         }
    535        
    536         glyphscanline = FONT_WIDTH * pixelbytes;
    537         glyphbytes = ROW2Y(glyphscanline);
    538         bgscanbytes = xres * pixelbytes;
    539        
    540         size_t fbsize = scanline * yres;
    541         size_t bbsize = cols * rows * sizeof(uint16_t);
    542         size_t glyphsize = FONT_GLYPHS * glyphbytes;
    543        
    544         fb_addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize);
    545         if (!fb_addr) {
     573                instance->ylogo = 0;
     574                instance->ytrim = instance->yres;
     575                instance->rowtrim = instance->rows;
     576        }
     577       
     578        instance->glyphscanline = FONT_WIDTH * instance->pixelbytes;
     579        instance->glyphbytes = ROW2Y(instance->glyphscanline);
     580        instance->bgscanbytes = instance->xres * instance->pixelbytes;
     581       
     582        size_t fbsize = instance->scanline * instance->yres;
     583        size_t bbsize = instance->cols * instance->rows * sizeof(uint16_t);
     584        size_t glyphsize = FONT_GLYPHS * instance->glyphbytes;
     585       
     586        instance->addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize);
     587        if (!instance->addr) {
    546588                LOG("Unable to map framebuffer.");
    547                 return false;
    548         }
    549        
    550         backbuf = (uint16_t *) malloc(bbsize, 0);
    551         if (!backbuf) {
     589                free(instance);
     590                free(fbdev);
     591                return NULL;
     592        }
     593       
     594        instance->backbuf = (uint16_t *) malloc(bbsize, 0);
     595        if (!instance->backbuf) {
    552596                LOG("Unable to allocate backbuffer.");
    553                 return false;
    554         }
    555        
    556         glyphs = (uint8_t *) malloc(glyphsize, 0);
    557         if (!glyphs) {
    558                 free(backbuf);
     597                free(instance);
     598                free(fbdev);
     599                return NULL;
     600        }
     601       
     602        instance->glyphs = (uint8_t *) malloc(glyphsize, 0);
     603        if (!instance->glyphs) {
    559604                LOG("Unable to allocate glyphs.");
    560                 return false;
    561         }
    562        
    563         bgscan = malloc(bgscanbytes, 0);
    564         if (!bgscan) {
    565                 free(glyphs);
    566                 free(backbuf);
     605                free(instance->backbuf);
     606                free(instance);
     607                free(fbdev);
     608                return NULL;
     609        }
     610       
     611        instance->bgscan = malloc(instance->bgscanbytes, 0);
     612        if (!instance->bgscan) {
    567613                LOG("Unable to allocate background pixel.");
    568                 return false;
    569         }
    570        
    571         memsetw(backbuf, cols * rows, 0);
    572         glyphs_render();
    573        
    574         sysinfo_set_item_val("fb", NULL, true);
    575         sysinfo_set_item_val("fb.kind", NULL, 1);
    576         sysinfo_set_item_val("fb.width", NULL, xres);
    577         sysinfo_set_item_val("fb.height", NULL, yres);
    578         sysinfo_set_item_val("fb.scanline", NULL, scanline);
    579         sysinfo_set_item_val("fb.visual", NULL, props->visual);
    580         sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
    581        
    582         fb_redraw();
    583        
    584         outdev_initialize("fb", &fb_console, &fb_ops);
    585         stdout_wire(&fb_console);
    586        
    587         return true;
     614                free(instance->glyphs);
     615                free(instance->backbuf);
     616                free(instance);
     617                free(fbdev);
     618                return NULL;
     619        }
     620       
     621        memsetw(instance->backbuf, instance->cols * instance->rows, 0);
     622        glyphs_render(instance);
     623       
     624        if (!fb_exported) {
     625                /*
     626                 * This is the necessary evil until the userspace driver is entirely
     627                 * self-sufficient.
     628                 */
     629                sysinfo_set_item_val("fb", NULL, true);
     630                sysinfo_set_item_val("fb.kind", NULL, 1);
     631                sysinfo_set_item_val("fb.width", NULL, instance->xres);
     632                sysinfo_set_item_val("fb.height", NULL, instance->yres);
     633                sysinfo_set_item_val("fb.scanline", NULL, instance->scanline);
     634                sysinfo_set_item_val("fb.visual", NULL, props->visual);
     635                sysinfo_set_item_val("fb.address.physical", NULL, props->addr);
     636               
     637                fb_exported = true;
     638        }
     639       
     640        fb_redraw(fbdev);
     641        return fbdev;
    588642}
    589643
  • kernel/generic/include/console/chardev.h

    r90c8b8d ra71c158  
    7474        /** Write character to output. */
    7575        void (* write)(struct outdev *, wchar_t, bool);
     76       
     77        /** Redraw any previously cached characters. */
     78        void (* redraw)(struct outdev *);
    7679} outdev_operations_t;
    7780
  • kernel/generic/include/console/console.h

    r90c8b8d ra71c158  
    6060extern unative_t sys_debug_disable_console(void);
    6161
    62 extern void arch_grab_console(void);
    63 extern void arch_release_console(void);
    64 
    6562#endif /* KERN_CONSOLE_H_ */
    6663
  • kernel/generic/include/sysinfo/sysinfo.h

    r90c8b8d ra71c158  
    3838#include <arch/types.h>
    3939#include <string.h>
     40
     41extern bool fb_exported;
    4042
    4143typedef union sysinfo_item_val {
  • kernel/generic/src/console/console.c

    r90c8b8d ra71c158  
    7171
    7272/** Kernel log spinlock */
    73 SPINLOCK_INITIALIZE(klog_lock);
     73SPINLOCK_STATIC_INITIALIZE_NAME(klog_lock, "*klog_lock");
    7474
    7575/** Physical memory area used for klog buffer */
     
    8484
    8585static void stdout_write(outdev_t *dev, wchar_t ch, bool silent);
     86static void stdout_redraw(outdev_t *dev);
    8687
    8788static outdev_operations_t stdout_ops = {
    88         .write = stdout_write
     89        .write = stdout_write,
     90        .redraw = stdout_redraw
    8991};
    9092
     
    122124        for (cur = dev->list.next; cur != &dev->list; cur = cur->next) {
    123125                outdev_t *sink = list_get_instance(cur, outdev_t, link);
    124                 sink->op->write(sink, ch, silent);
     126                if ((sink) && (sink->op->write))
     127                        sink->op->write(sink, ch, silent);
     128        }
     129}
     130
     131static void stdout_redraw(outdev_t *dev)
     132{
     133        link_t *cur;
     134       
     135        for (cur = dev->list.next; cur != &dev->list; cur = cur->next) {
     136                outdev_t *sink = list_get_instance(cur, outdev_t, link);
     137                if ((sink) && (sink->op->redraw))
     138                        sink->op->redraw(sink);
    125139        }
    126140}
     
    156170       
    157171        silent = false;
    158         arch_grab_console();
     172        if ((stdout) && (stdout->op->redraw))
     173                stdout->op->redraw(stdout);
    159174       
    160175        /* Force the console to print the prompt */
     
    165180void release_console(void)
    166181{
     182        // FIXME arch_release_console
    167183        silent = true;
    168         arch_release_console();
    169184}
    170185
  • kernel/generic/src/sysinfo/sysinfo.c

    r90c8b8d ra71c158  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @{
    3131 */
     
    3838#include <syscall/copy.h>
    3939
     40bool fb_exported = false;
    4041sysinfo_item_t *_root = NULL;
    41 
    4242
    4343static sysinfo_item_t *sysinfo_find_item(const char *name, sysinfo_item_t *subtree)
Note: See TracChangeset for help on using the changeset viewer.