symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/tc58128.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #include <assert.h>
       
     2 #include "hw.h"
       
     3 #include "sh.h"
       
     4 #include "sysemu.h"
       
     5 
       
     6 #define CE1  0x0100
       
     7 #define CE2  0x0200
       
     8 #define RE   0x0400
       
     9 #define WE   0x0800
       
    10 #define ALE  0x1000
       
    11 #define CLE  0x2000
       
    12 #define RDY1 0x4000
       
    13 #define RDY2 0x8000
       
    14 #define RDY(n) ((n) == 0 ? RDY1 : RDY2)
       
    15 
       
    16 typedef enum { WAIT, READ1, READ2, READ3 } state_t;
       
    17 
       
    18 typedef struct {
       
    19     uint8_t *flash_contents;
       
    20     state_t state;
       
    21     uint32_t address;
       
    22     uint8_t address_cycle;
       
    23 } tc58128_dev;
       
    24 
       
    25 static tc58128_dev tc58128_devs[2];
       
    26 
       
    27 #define FLASH_SIZE (16*1024*1024)
       
    28 
       
    29 static void init_dev(tc58128_dev * dev, const char *filename)
       
    30 {
       
    31     int ret, blocks;
       
    32 
       
    33     dev->state = WAIT;
       
    34     dev->flash_contents = qemu_mallocz(FLASH_SIZE);
       
    35     memset(dev->flash_contents, 0xff, FLASH_SIZE);
       
    36     if (!dev->flash_contents) {
       
    37 	fprintf(stderr, "could not alloc memory for flash\n");
       
    38 	exit(1);
       
    39     }
       
    40     if (filename) {
       
    41 	/* Load flash image skipping the first block */
       
    42 	ret = load_image(filename, dev->flash_contents + 528 * 32);
       
    43 	if (ret < 0) {
       
    44 	    fprintf(stderr, "ret=%d\n", ret);
       
    45 	    fprintf(stderr, "qemu: could not load flash image %s\n",
       
    46 		    filename);
       
    47 	    exit(1);
       
    48 	} else {
       
    49 	    /* Build first block with number of blocks */
       
    50 	    blocks = (ret + 528 * 32 - 1) / (528 * 32);
       
    51 	    dev->flash_contents[0] = blocks & 0xff;
       
    52 	    dev->flash_contents[1] = (blocks >> 8) & 0xff;
       
    53 	    dev->flash_contents[2] = (blocks >> 16) & 0xff;
       
    54 	    dev->flash_contents[3] = (blocks >> 24) & 0xff;
       
    55 	    fprintf(stderr, "loaded %d bytes for %s into flash\n", ret,
       
    56 		    filename);
       
    57 	}
       
    58     }
       
    59 }
       
    60 
       
    61 static void handle_command(tc58128_dev * dev, uint8_t command)
       
    62 {
       
    63     switch (command) {
       
    64     case 0xff:
       
    65 	fprintf(stderr, "reset flash device\n");
       
    66 	dev->state = WAIT;
       
    67 	break;
       
    68     case 0x00:
       
    69 	fprintf(stderr, "read mode 1\n");
       
    70 	dev->state = READ1;
       
    71 	dev->address_cycle = 0;
       
    72 	break;
       
    73     case 0x01:
       
    74 	fprintf(stderr, "read mode 2\n");
       
    75 	dev->state = READ2;
       
    76 	dev->address_cycle = 0;
       
    77 	break;
       
    78     case 0x50:
       
    79 	fprintf(stderr, "read mode 3\n");
       
    80 	dev->state = READ3;
       
    81 	dev->address_cycle = 0;
       
    82 	break;
       
    83     default:
       
    84 	fprintf(stderr, "unknown flash command 0x%02x\n", command);
       
    85 	assert(0);
       
    86     }
       
    87 }
       
    88 
       
    89 static void handle_address(tc58128_dev * dev, uint8_t data)
       
    90 {
       
    91     switch (dev->state) {
       
    92     case READ1:
       
    93     case READ2:
       
    94     case READ3:
       
    95 	switch (dev->address_cycle) {
       
    96 	case 0:
       
    97 	    dev->address = data;
       
    98 	    if (dev->state == READ2)
       
    99 		dev->address |= 0x100;
       
   100 	    else if (dev->state == READ3)
       
   101 		dev->address |= 0x200;
       
   102 	    break;
       
   103 	case 1:
       
   104 	    dev->address += data * 528 * 0x100;
       
   105 	    break;
       
   106 	case 2:
       
   107 	    dev->address += data * 528;
       
   108 	    fprintf(stderr, "address pointer in flash: 0x%08x\n",
       
   109 		    dev->address);
       
   110 	    break;
       
   111 	default:
       
   112 	    /* Invalid data */
       
   113 	    assert(0);
       
   114 	}
       
   115 	dev->address_cycle++;
       
   116 	break;
       
   117     default:
       
   118 	assert(0);
       
   119     }
       
   120 }
       
   121 
       
   122 static uint8_t handle_read(tc58128_dev * dev)
       
   123 {
       
   124 #if 0
       
   125     if (dev->address % 0x100000 == 0)
       
   126 	fprintf(stderr, "reading flash at address 0x%08x\n", dev->address);
       
   127 #endif
       
   128     return dev->flash_contents[dev->address++];
       
   129 }
       
   130 
       
   131 /* We never mark the device as busy, so interrupts cannot be triggered
       
   132    XXXXX */
       
   133 
       
   134 static int tc58128_cb(uint16_t porta, uint16_t portb,
       
   135                       uint16_t * periph_pdtra, uint16_t * periph_portadir,
       
   136                       uint16_t * periph_pdtrb, uint16_t * periph_portbdir)
       
   137 {
       
   138     int dev;
       
   139 
       
   140     if ((porta & CE1) == 0)
       
   141 	dev = 0;
       
   142     else if ((porta & CE2) == 0)
       
   143 	dev = 1;
       
   144     else
       
   145 	return 0;		/* No device selected */
       
   146 
       
   147     if ((porta & RE) && (porta & WE)) {
       
   148 	/* Nothing to do, assert ready and return to input state */
       
   149 	*periph_portadir &= 0xff00;
       
   150 	*periph_portadir |= RDY(dev);
       
   151 	*periph_pdtra |= RDY(dev);
       
   152 	return 1;
       
   153     }
       
   154 
       
   155     if (porta & CLE) {
       
   156 	/* Command */
       
   157 	assert((porta & WE) == 0);
       
   158 	handle_command(&tc58128_devs[dev], porta & 0x00ff);
       
   159     } else if (porta & ALE) {
       
   160 	assert((porta & WE) == 0);
       
   161 	handle_address(&tc58128_devs[dev], porta & 0x00ff);
       
   162     } else if ((porta & RE) == 0) {
       
   163 	*periph_portadir |= 0x00ff;
       
   164 	*periph_pdtra &= 0xff00;
       
   165 	*periph_pdtra |= handle_read(&tc58128_devs[dev]);
       
   166     } else {
       
   167 	assert(0);
       
   168     }
       
   169     return 1;
       
   170 }
       
   171 
       
   172 static sh7750_io_device tc58128 = {
       
   173     RE | WE,			/* Port A triggers */
       
   174     0,				/* Port B triggers */
       
   175     tc58128_cb			/* Callback */
       
   176 };
       
   177 
       
   178 int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2)
       
   179 {
       
   180     init_dev(&tc58128_devs[0], zone1);
       
   181     init_dev(&tc58128_devs[1], zone2);
       
   182     return sh7750_register_io_device(s, &tc58128);
       
   183 }