(linenum→info "unix/slp.c:2238")

qemu/0.9.1/hw/mips_malta.c

    1: /*
    2:  * QEMU Malta board support
    3:  *
    4:  * Copyright (c) 2006 Aurelien Jarno
    5:  *
    6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7:  * of this software and associated documentation files (the "Software"), to deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: 
   25: #include "hw.h"
   26: #include "pc.h"
   27: #include "fdc.h"
   28: #include "net.h"
   29: #include "boards.h"
   30: #include "smbus.h"
   31: #include "block.h"
   32: #include "flash.h"
   33: #include "mips.h"
   34: #include "pci.h"
   35: #include "qemu-char.h"
   36: #include "sysemu.h"
   37: #include "audio/audio.h"
   38: #include "boards.h"
   39: 
   40: //#define DEBUG_BOARD_INIT
   41: 
   42: #ifdef TARGET_WORDS_BIGENDIAN
   43: #define BIOS_FILENAME "mips_bios.bin"
   44: #else
   45: #define BIOS_FILENAME "mipsel_bios.bin"
   46: #endif
   47: 
   48: #ifdef TARGET_MIPS64
   49: #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
   50: #else
   51: #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
   52: #endif
   53: 
   54: #define ENVP_ADDR (int32_t)0x80002000
   55: #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
   56: 
   57: #define ENVP_NB_ENTRIES         16
   58: #define ENVP_ENTRY_SIZE         256
   59: 
   60: #define MAX_IDE_BUS 2
   61: 
   62: extern FILE *logfile;
   63: 
   64: typedef struct {
   65:     uint32_t leds;
   66:     uint32_t brk;
   67:     uint32_t gpout;
   68:     uint32_t i2cin;
   69:     uint32_t i2coe;
   70:     uint32_t i2cout;
   71:     uint32_t i2csel;
   72:     CharDriverState *display;
   73:     char display_text[9];
   74:     SerialState *uart;
   75: } MaltaFPGAState;
   76: 
   77: static PITState *pit;
   78: 
   79: static struct _loaderparams {
   80:     int ram_size;
   81:     const char *kernel_filename;
   82:     const char *kernel_cmdline;
   83:     const char *initrd_filename;
   84: } loaderparams;
   85: 
   86: /* Malta FPGA */
   87: static void malta_fpga_update_display(void *opaque)
   88: {
   89:     char leds_text[9];
   90:     int i;
   91:     MaltaFPGAState *s = opaque;
   92: 
   93:     for (i = 7 ; i >= 0 ; i--) {
   94:         if (s->leds & (1 << i))
   95:             leds_text[i] = '#';
   96:         else
   97:             leds_text[i] = ' ';
   98:     }
   99:     leds_text[8] = '\0';
  100: 
  101:     qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
  102:     qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
  103: }
  104: 
  105: /*
  106:  * EEPROM 24C01 / 24C02 emulation.
  107:  *
  108:  * Emulation for serial EEPROMs:
  109:  * 24C01 - 1024 bit (128 x 8)
  110:  * 24C02 - 2048 bit (256 x 8)
  111:  *
  112:  * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02.
  113:  */
  114: 
  115: //~ #define DEBUG
  116: 
  117: #if defined(DEBUG)
  118: #  define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)
  119: #else
  120: #  define logout(fmt, args...) ((void)0)
  121: #endif
  122: 
  123: struct _eeprom24c0x_t {
  124:   uint8_t tick;
  125:   uint8_t address;
  126:   uint8_t command;
  127:   uint8_t ack;
  128:   uint8_t scl;
  129:   uint8_t sda;
  130:   uint8_t data;
  131:   //~ uint16_t size;
  132:   uint8_t contents[256];
  133: };
  134: 
  135: typedef struct _eeprom24c0x_t eeprom24c0x_t;
  136: 
  137: static eeprom24c0x_t eeprom = {
  138:     contents: {
  139:         /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
  140:         /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
  141:         /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
  142:         /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
  143:         /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
  144:         /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  145:         /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  146:         /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0,
  147:         /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  148:         /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  149:         /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  150:         /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  151:         /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  152:         /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  153:         /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  154:         /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4,
  155:     },
  156: };
  157: 
  158: static uint8_t eeprom24c0x_read()
  159: {
  160:     logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
  161:         eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data);
  162:     return eeprom.sda;
  163: }
  164: 
  165: static void eeprom24c0x_write(int scl, int sda)
  166: {
  167:     if (eeprom.scl && scl && (eeprom.sda != sda)) {
  168:         logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n",
  169:                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start");
  170:         if (!sda) {
  171:             eeprom.tick = 1;
  172:             eeprom.command = 0;
  173:         }
  174:     } else if (eeprom.tick == 0 && !eeprom.ack) {
  175:         /* Waiting for start. */
  176:         logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n",
  177:                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
  178:     } else if (!eeprom.scl && scl) {
  179:         logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n",
  180:                 eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
  181:         if (eeprom.ack) {
  182:             logout("\ti2c ack bit = 0\n");
  183:             sda = 0;
  184:             eeprom.ack = 0;
  185:         } else if (eeprom.sda == sda) {
  186:             uint8_t bit = (sda != 0);
  187:             logout("\ti2c bit = %d\n", bit);
  188:             if (eeprom.tick < 9) {
  189:                 eeprom.command <<= 1;
  190:                 eeprom.command += bit;
  191:                 eeprom.tick++;
  192:                 if (eeprom.tick == 9) {
  193:                     logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write");
  194:                     eeprom.ack = 1;
  195:                 }
  196:             } else if (eeprom.tick < 17) {
  197:                 if (eeprom.command & 1) {
  198:                     sda = ((eeprom.data & 0x80) != 0);
  199:                 }
  200:                 eeprom.address <<= 1;
  201:                 eeprom.address += bit;
  202:                 eeprom.tick++;
  203:                 eeprom.data <<= 1;
  204:                 if (eeprom.tick == 17) {
  205:                     eeprom.data = eeprom.contents[eeprom.address];
  206:                     logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data);
  207:                     eeprom.ack = 1;
  208:                     eeprom.tick = 0;
  209:                 }
  210:             } else if (eeprom.tick >= 17) {
  211:                 sda = 0;
  212:             }
  213:         } else {
  214:             logout("\tsda changed with raising scl\n");
  215:         }
  216:     } else {
  217:         logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda);
  218:     }
  219:     eeprom.scl = scl;
  220:     eeprom.sda = sda;
  221: }
  222: 
  223: static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr)
  224: {
  225:     MaltaFPGAState *s = opaque;
  226:     uint32_t val = 0;
  227:     uint32_t saddr;
  228: 
  229:     saddr = (addr & 0xfffff);
  230: 
  231:     switch (saddr) {
  232: 
  233:     /* SWITCH Register */
  234:     case 0x00200:
  235:         val = 0x00000000;               /* All switches closed */
  236:         break;
  237: 
  238:     /* STATUS Register */
  239:     case 0x00208:
  240: #ifdef TARGET_WORDS_BIGENDIAN
  241:         val = 0x00000012;
  242: #else
  243:         val = 0x00000010;
  244: #endif
  245:         break;
  246: 
  247:     /* JMPRS Register */
  248:     case 0x00210:
  249:         val = 0x00;
  250:         break;
  251: 
  252:     /* LEDBAR Register */
  253:     case 0x00408:
  254:         val = s->leds;
  255:         break;
  256: 
  257:     /* BRKRES Register */
  258:     case 0x00508:
  259:         val = s->brk;
  260:         break;
  261: 
  262:     /* UART Registers are handled directly by the serial device */
  263: 
  264:     /* GPOUT Register */
  265:     case 0x00a00:
  266:         val = s->gpout;
  267:         break;
  268: 
  269:     /* XXX: implement a real I2C controller */
  270: 
  271:     /* GPINP Register */
  272:     case 0x00a08:
  273:         /* IN = OUT until a real I2C control is implemented */
  274:         if (s->i2csel)
  275:             val = s->i2cout;
  276:         else
  277:             val = 0x00;
  278:         break;
  279: 
  280:     /* I2CINP Register */
  281:     case 0x00b00:
  282:         val = ((s->i2cin & ~1) | eeprom24c0x_read());
  283:         break;
  284: 
  285:     /* I2COE Register */
  286:     case 0x00b08:
  287:         val = s->i2coe;
  288:         break;
  289: 
  290:     /* I2COUT Register */
  291:     case 0x00b10:
  292:         val = s->i2cout;
  293:         break;
  294: 
  295:     /* I2CSEL Register */
  296:     case 0x00b18:
  297:         val = s->i2csel;
  298:         break;
  299: 
  300:     default:
  301: #if 0
  302:         printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n",
  303:                 addr);
  304: #endif
  305:         break;
  306:     }
  307:     return val;
  308: }
  309: 
  310: static void malta_fpga_writel(void *opaque, target_phys_addr_t addr,
  311:                               uint32_t val)
  312: {
  313:     MaltaFPGAState *s = opaque;
  314:     uint32_t saddr;
  315: 
  316:     saddr = (addr & 0xfffff);
  317: 
  318:     switch (saddr) {
  319: 
  320:     /* SWITCH Register */
  321:     case 0x00200:
  322:         break;
  323: 
  324:     /* JMPRS Register */
  325:     case 0x00210:
  326:         break;
  327: 
  328:     /* LEDBAR Register */
  329:     /* XXX: implement a 8-LED array */
  330:     case 0x00408:
  331:         s->leds = val & 0xff;
  332:         break;
  333: 
  334:     /* ASCIIWORD Register */
  335:     case 0x00410:
  336:         snprintf(s->display_text, 9, "%08X", val);
  337:         malta_fpga_update_display(s);
  338:         break;
  339: 
  340:     /* ASCIIPOS0 to ASCIIPOS7 Registers */
  341:     case 0x00418:
  342:     case 0x00420:
  343:     case 0x00428:
  344:     case 0x00430:
  345:     case 0x00438:
  346:     case 0x00440:
  347:     case 0x00448:
  348:     case 0x00450:
  349:         s->display_text[(saddr - 0x00418) >> 3] = (char) val;
  350:         malta_fpga_update_display(s);
  351:         break;
  352: 
  353:     /* SOFTRES Register */
  354:     case 0x00500:
  355:         if (val == 0x42)
  356:             qemu_system_reset_request ();
  357:         break;
  358: 
  359:     /* BRKRES Register */
  360:     case 0x00508:
  361:         s->brk = val & 0xff;
  362:         break;
  363: 
  364:     /* UART Registers are handled directly by the serial device */
  365: 
  366:     /* GPOUT Register */
  367:     case 0x00a00:
  368:         s->gpout = val & 0xff;
  369:         break;
  370: 
  371:     /* I2COE Register */
  372:     case 0x00b08:
  373:         s->i2coe = val & 0x03;
  374:         break;
  375: 
  376:     /* I2COUT Register */
  377:     case 0x00b10:
  378:         eeprom24c0x_write(val & 0x02, val & 0x01);
  379:         s->i2cout = val;
  380:         break;
  381: 
  382:     /* I2CSEL Register */
  383:     case 0x00b18:
  384:         s->i2csel = val & 0x01;
  385:         break;
  386: 
  387:     default:
  388: #if 0
  389:         printf ("malta_fpga_write: Bad register offset 0x" TARGET_FMT_lx "\n",
  390:                 addr);
  391: #endif
  392:         break;
  393:     }
  394: }
  395: 
  396: static CPUReadMemoryFunc *malta_fpga_read[] = {
  397:    malta_fpga_readl,
  398:    malta_fpga_readl,
  399:    malta_fpga_readl
  400: };
  401: 
  402: static CPUWriteMemoryFunc *malta_fpga_write[] = {
  403:    malta_fpga_writel,
  404:    malta_fpga_writel,
  405:    malta_fpga_writel
  406: };
  407: 
  408: static void malta_fpga_reset(void *opaque)
  409: {
  410:     MaltaFPGAState *s = opaque;
  411: 
  412:     s->leds   = 0x00;
  413:     s->brk    = 0x0a;
  414:     s->gpout  = 0x00;
  415:     s->i2cin  = 0x3;
  416:     s->i2coe  = 0x0;
  417:     s->i2cout = 0x3;
  418:     s->i2csel = 0x1;
  419: 
  420:     s->display_text[8] = '\0';
  421:     snprintf(s->display_text, 9, "        ");
  422:     malta_fpga_update_display(s);
  423: }
  424: 
  425: static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, CPUState *env)
  426: {
  427:     MaltaFPGAState *s;
  428:     CharDriverState *uart_chr;
  429:     int malta;
  430: 
  431:     s = (MaltaFPGAState *)qemu_mallocz(sizeof(MaltaFPGAState));
  432: 
  433:     malta = cpu_register_io_memory(0, malta_fpga_read,
  434:                                    malta_fpga_write, s);
  435: 
  436:     cpu_register_physical_memory(base, 0x900, malta);
  437:     cpu_register_physical_memory(base + 0xa00, 0x100000 - 0xa00, malta);
  438: 
  439:     s->display = qemu_chr_open("vc");
  440:     qemu_chr_printf(s->display, "\e[HMalta LEDBAR\r\n");
  441:     qemu_chr_printf(s->display, "+--------+\r\n");
  442:     qemu_chr_printf(s->display, "+        +\r\n");
  443:     qemu_chr_printf(s->display, "+--------+\r\n");
  444:     qemu_chr_printf(s->display, "\n");
  445:     qemu_chr_printf(s->display, "Malta ASCII\r\n");
  446:     qemu_chr_printf(s->display, "+--------+\r\n");
  447:     qemu_chr_printf(s->display, "+        +\r\n");
  448:     qemu_chr_printf(s->display, "+--------+\r\n");
  449: 
  450:     uart_chr = qemu_chr_open("vc");
  451:     qemu_chr_printf(uart_chr, "CBUS UART\r\n");
  452:     s->uart = serial_mm_init(base + 0x900, 3, env->irq[2], uart_chr, 1);
  453: 
  454:     malta_fpga_reset(s);
  455:     qemu_register_reset(malta_fpga_reset, s);
  456: 
  457:     return s;
  458: }
  459: 
  460: /* Audio support */
  461: #ifdef HAS_AUDIO
  462: static void audio_init (PCIBus *pci_bus)
  463: {
  464:     struct soundhw *c;
  465:     int audio_enabled = 0;
  466: 
  467:     for (c = soundhw; !audio_enabled && c->name; ++c) {
  468:         audio_enabled = c->enabled;
  469:     }
  470: 
  471:     if (audio_enabled) {
  472:         AudioState *s;
  473: 
  474:         s = AUD_init ();
  475:         if (s) {
  476:             for (c = soundhw; c->name; ++c) {
  477:                 if (c->enabled)
  478:                     c->init.init_pci (pci_bus, s);
  479:             }
  480:         }
  481:     }
  482: }
  483: #endif
  484: 
  485: /* Network support */
  486: static void network_init (PCIBus *pci_bus)
  487: {
  488:     int i;
  489:     NICInfo *nd;
  490: 
  491:     for(i = 0; i < nb_nics; i++) {
  492:         nd = &nd_table[i];
  493:         if (!nd->model) {
  494:             nd->model = "pcnet";
  495:         }
  496:         if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
  497:             /* The malta board has a PCNet card using PCI SLOT 11 */
  498:             pci_nic_init(pci_bus, nd, 88);
  499:         } else {
  500:             pci_nic_init(pci_bus, nd, -1);
  501:         }
  502:     }
  503: }
  504: 
  505: /* ROM and pseudo bootloader
  506: 
  507:    The following code implements a very very simple bootloader. It first
  508:    loads the registers a0 to a3 to the values expected by the OS, and
  509:    then jump at the kernel address.
  510: 
  511:    The bootloader should pass the locations of the kernel arguments and
  512:    environment variables tables. Those tables contain the 32-bit address
  513:    of NULL terminated strings. The environment variables table should be
  514:    terminated by a NULL address.
  515: 
  516:    For a simpler implementation, the number of kernel arguments is fixed
  517:    to two (the name of the kernel and the command line), and the two
  518:    tables are actually the same one.
  519: 
  520:    The registers a0 to a3 should contain the following values:
  521:      a0 - number of kernel arguments
  522:      a1 - 32-bit address of the kernel arguments table
  523:      a2 - 32-bit address of the environment variables table
  524:      a3 - RAM size in bytes
  525: */
  526: 
  527: static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_entry)
  528: {
  529:     uint32_t *p;
  530: 
  531:     /* Small bootloader */
  532:     p = (uint32_t *) (phys_ram_base + bios_offset);
  533:     stl_raw(p++, 0x0bf00160);                                      /* j 0x1fc00580 */
  534:     stl_raw(p++, 0x00000000);                                      /* nop */
  535: 
  536:     /* YAMON service vector */
  537:     stl_raw(phys_ram_base + bios_offset + 0x500, 0xbfc00580);      /* start: */
  538:     stl_raw(phys_ram_base + bios_offset + 0x504, 0xbfc0083c);      /* print_count: */
  539:     stl_raw(phys_ram_base + bios_offset + 0x520, 0xbfc00580);      /* start: */
  540:     stl_raw(phys_ram_base + bios_offset + 0x52c, 0xbfc00800);      /* flush_cache: */
  541:     stl_raw(phys_ram_base + bios_offset + 0x534, 0xbfc00808);      /* print: */
  542:     stl_raw(phys_ram_base + bios_offset + 0x538, 0xbfc00800);      /* reg_cpu_isr: */
  543:     stl_raw(phys_ram_base + bios_offset + 0x53c, 0xbfc00800);      /* unred_cpu_isr: */
  544:     stl_raw(phys_ram_base + bios_offset + 0x540, 0xbfc00800);      /* reg_ic_isr: */
  545:     stl_raw(phys_ram_base + bios_offset + 0x544, 0xbfc00800);      /* unred_ic_isr: */
  546:     stl_raw(phys_ram_base + bios_offset + 0x548, 0xbfc00800);      /* reg_esr: */
  547:     stl_raw(phys_ram_base + bios_offset + 0x54c, 0xbfc00800);      /* unreg_esr: */
  548:     stl_raw(phys_ram_base + bios_offset + 0x550, 0xbfc00800);      /* getchar: */
  549:     stl_raw(phys_ram_base + bios_offset + 0x554, 0xbfc00800);      /* syscon_read: */
  550: 
  551: 
  552:     /* Second part of the bootloader */
  553:     p = (uint32_t *) (phys_ram_base + bios_offset + 0x580);
  554:     stl_raw(p++, 0x24040002);                                      /* addiu a0, zero, 2 */
  555:     stl_raw(p++, 0x3c1d0000 | (((ENVP_ADDR - 64) >> 16) & 0xffff)); /* lui sp, high(ENVP_ADDR) */
  556:     stl_raw(p++, 0x37bd0000 | ((ENVP_ADDR - 64) & 0xffff));        /* ori sp, sp, low(ENVP_ADDR) */
  557:     stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */
  558:     stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a1, low(ENVP_ADDR) */
  559:     stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
  560:     stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */
  561:     stl_raw(p++, 0x3c070000 | (loaderparams.ram_size >> 16));     /* lui a3, high(ram_size) */
  562:     stl_raw(p++, 0x34e70000 | (loaderparams.ram_size &