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