uboot/lib_i386/video_bios.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <pci.h>
  26#include <malloc.h>
  27#include <asm/ptrace.h>
  28#include <asm/realmode.h>
  29#include <asm/io.h>
  30#include <asm/pci.h>
  31
  32#undef PCI_BIOS_DEBUG
  33#undef VGA_BIOS_DEBUG
  34
  35#ifdef  VGA_BIOS_DEBUG
  36#define PRINTF(fmt,args...)     printf (fmt ,##args)
  37#else
  38#define PRINTF(fmt,args...)
  39#endif
  40
  41#ifdef CONFIG_PCI
  42
  43#ifdef PCI_BIOS_DEBUG
  44#define RELOC_16(seg, off) *(u32*)(seg << 4 | (u32)&off)
  45extern u32 num_pci_bios_present;
  46extern u32 num_pci_bios_find_device;
  47extern u32 num_pci_bios_find_class;
  48extern u32 num_pci_bios_generate_special_cycle;
  49extern u32 num_pci_bios_read_cfg_byte;
  50extern u32 num_pci_bios_read_cfg_word;
  51extern u32 num_pci_bios_read_cfg_dword;
  52extern u32 num_pci_bios_write_cfg_byte;
  53extern u32 num_pci_bios_write_cfg_word;
  54extern u32 num_pci_bios_write_cfg_dword;
  55extern u32 num_pci_bios_get_irq_routing;
  56extern u32 num_pci_bios_set_irq;
  57extern u32 num_pci_bios_unknown_function;
  58
  59void print_bios_bios_stat(void)
  60{
  61        printf("16 bit functions:\n");
  62        printf("pci_bios_present:                %d\n", RELOC_16(0xf000, num_pci_bios_present));
  63        printf("pci_bios_find_device:            %d\n", RELOC_16(0xf000, num_pci_bios_find_device));
  64        printf("pci_bios_find_class:             %d\n", RELOC_16(0xf000, num_pci_bios_find_class));
  65        printf("pci_bios_generate_special_cycle: %d\n", RELOC_16(0xf000, num_pci_bios_generate_special_cycle));
  66        printf("pci_bios_read_cfg_byte:          %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_byte));
  67        printf("pci_bios_read_cfg_word:          %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_word));
  68        printf("pci_bios_read_cfg_dword:         %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_dword));
  69        printf("pci_bios_write_cfg_byte:         %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_byte));
  70        printf("pci_bios_write_cfg_word:         %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_word));
  71        printf("pci_bios_write_cfg_dword:        %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_dword));
  72        printf("pci_bios_get_irq_routing:        %d\n", RELOC_16(0xf000, num_pci_bios_get_irq_routing));
  73        printf("pci_bios_set_irq:                %d\n", RELOC_16(0xf000, num_pci_bios_set_irq));
  74        printf("pci_bios_unknown_function:       %d\n", RELOC_16(0xf000, num_pci_bios_unknown_function));
  75
  76}
  77#endif
  78
  79#define PCI_CLASS_VIDEO             3
  80#define PCI_CLASS_VIDEO_STD         0
  81#define PCI_CLASS_VIDEO_PROG_IF_VGA 0
  82
  83
  84static u32 probe_pci_video(void)
  85{
  86        pci_dev_t devbusfn;
  87
  88        if ((devbusfn = pci_find_class(PCI_CLASS_VIDEO,
  89                                       PCI_CLASS_VIDEO_STD,
  90                                       PCI_CLASS_VIDEO_PROG_IF_VGA, 0)) != -1) {
  91                u32 old;
  92                u32 addr;
  93
  94                /* PCI video device detected */
  95                printf("Found PCI VGA device at %02x.%02x.%x\n",
  96                       PCI_BUS(devbusfn), PCI_DEV(devbusfn), PCI_FUNC(devbusfn));
  97
  98                /* Enable I/O decoding as well, PCI viudeo boards
  99                 * support I/O accesses, but they provide no
 100                 * bar register for this since the ports are fixed.
 101                 */
 102                pci_write_config_word(devbusfn, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
 103
 104                /* Test the ROM decoder, do the device support a rom? */
 105                pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &old);
 106                pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_MASK);
 107                pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &addr);
 108                pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, old);
 109
 110                if (!addr) {
 111                        printf("PCI VGA have no ROM?\n");
 112                        return 0;
 113                }
 114
 115                /* device have a rom */
 116                if (pci_shadow_rom(devbusfn, (void*)0xc0000)) {
 117                        printf("Shadowing of PCI VGA BIOS failed\n");
 118                        return 0;
 119                }
 120
 121                /* Now enable lagacy VGA port access */
 122                if (pci_enable_legacy_video_ports(pci_bus_to_hose(PCI_BUS(devbusfn)))) {
 123                        printf("PCI VGA enable failed\n");
 124                        return 0;
 125                }
 126
 127
 128                /* return the pci device info, that we'll need later */
 129                return PCI_BUS(devbusfn) << 8 |
 130                        PCI_DEV(devbusfn) << 3 | (PCI_FUNC(devbusfn)&7);
 131        }
 132
 133        return 0;
 134}
 135
 136
 137#endif
 138
 139#ifdef CONFIG_VIDEO
 140
 141static int probe_isa_video(void)
 142{
 143        u32 ptr;
 144        char *buf;
 145
 146        if (0 == (ptr = isa_map_rom(0xc0000, 0x8000))) {
 147                return -1;
 148        }
 149        if (NULL == (buf=malloc(0x8000))) {
 150                isa_unmap_rom(ptr);
 151                return -1;
 152        }
 153        if (readw(ptr) != 0xaa55) {
 154                free(buf);
 155                isa_unmap_rom(ptr);
 156                return -1;
 157        }
 158
 159        /* shadow the rom */
 160        memcpy(buf, (void*)ptr, 0x8000);
 161        isa_unmap_rom(ptr);
 162        memcpy((void*)0xc0000, buf, 0x8000);
 163
 164        free(buf);
 165
 166        return 0;
 167}
 168
 169int video_bios_init(void)
 170{
 171        struct pt_regs regs;
 172
 173        /* clear the video bios area in case we warmbooted */
 174        memset((void*)0xc0000, 0, 0x8000);
 175        memset(&regs, 0, sizeof(struct pt_regs));
 176
 177        if (probe_isa_video()) {
 178                /* No ISA board found, try the PCI bus */
 179                regs.eax = probe_pci_video();
 180        }
 181
 182        /* Did we succeed in mapping any video bios */
 183        if (readw(0xc0000) == 0xaa55) {
 184                int size;
 185                int i;
 186                u8 sum;
 187
 188                PRINTF("Found video bios signature\n");
 189                size = 512*readb(0xc0002);
 190                PRINTF("size %d\n", size);
 191                sum=0;
 192                for (i=0;i<size;i++) {
 193                        sum += readb(0xc0000 + i);
 194                }
 195                PRINTF("Checksum is %sOK\n",sum?"NOT ":"");
 196                if (sum) {
 197                        return 1;
 198                }
 199
 200                /* some video bioses (ATI Mach64) seem to think that
 201                 * the original int 10 handler is always at
 202                 * 0xf000:0xf065 , place an iret instruction there
 203                 */
 204                writeb(0xcf, 0xff065);
 205
 206                regs.esp = 0x8000;
 207                regs.xss = 0x2000;
 208                enter_realmode(0xc000, 3, &regs, &regs);
 209                PRINTF("INT 0x10 vector after:  %04x:%04x\n",
 210                       readw(0x42), readw(0x40));
 211                PRINTF("BIOS returned %scarry\n", regs.eflags & 1?"":"NOT ");
 212#ifdef PCI_BIOS_DEBUG
 213                print_bios_bios_stat();
 214#endif
 215                return (regs.eflags & 1);
 216
 217        }
 218
 219        return 1;
 220
 221}
 222#endif
 223