comparison romdb.c @ 1395:efa7225e0f07

Initial work to support parallel NOR flash and the Magistr 16
author Michael Pavone <pavone@retrodev.com>
date Wed, 07 Jun 2017 23:06:14 -0700
parents ae3b1721b226
children 71b6e2298e4a
comparison
equal deleted inserted replaced
1394:ae3b1721b226 1395:efa7225e0f07
17 #define RAM_ID 0x1B0 17 #define RAM_ID 0x1B0
18 #define RAM_FLAGS 0x1B2 18 #define RAM_FLAGS 0x1B2
19 #define RAM_START 0x1B4 19 #define RAM_START 0x1B4
20 #define RAM_END 0x1B8 20 #define RAM_END 0x1B8
21 #define REGION_START 0x1F0 21 #define REGION_START 0x1F0
22
23 char const *save_type_name(uint8_t save_type)
24 {
25 if (save_type == SAVE_I2C) {
26 return "EEPROM";
27 } else if(save_type == SAVE_NOR) {
28 return "NOR Flash";
29 }
30 return "SRAM";
31 }
22 32
23 enum { 33 enum {
24 I2C_IDLE, 34 I2C_IDLE,
25 I2C_START, 35 I2C_START,
26 I2C_DEVICE_ACK, 36 I2C_DEVICE_ACK,
185 uint8_t get_sda(eeprom_state *state) 195 uint8_t get_sda(eeprom_state *state)
186 { 196 {
187 return state->host_sda & state->slave_sda; 197 return state->host_sda & state->slave_sda;
188 } 198 }
189 199
200 enum {
201 NOR_NORMAL,
202 NOR_PRODUCTID,
203 NOR_BOOTBLOCK
204 };
205
206 enum {
207 NOR_CMD_IDLE,
208 NOR_CMD_AA,
209 NOR_CMD_55
210 };
211
212 //Technically this value shoudl be slightly different between NTSC and PAL
213 //as it's defined as 200 micro-seconds, not in clock cycles
214 #define NOR_WRITE_PAUSE 10690
215
216 void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags)
217 {
218 state->buffer = buffer;
219 state->page_buffer = malloc(page_size);
220 memset(state->page_buffer, 0xFF, page_size);
221 state->size = size;
222 state->page_size = page_size;
223 state->product_id = product_id;
224 state->last_write_cycle = 0xFFFFFFFF;
225 state->mode = NOR_NORMAL;
226 state->cmd_state = NOR_CMD_IDLE;
227 state->alt_cmd = 0;
228 state->bus_flags = bus_flags;
229 }
230
231 void nor_run(nor_state *state, uint32_t cycle)
232 {
233 if (state->last_write_cycle == 0xFFFFFFFF) {
234 return;
235 }
236 if (cycle - state->last_write_cycle >= NOR_WRITE_PAUSE) {
237 state->last_write_cycle = 0xFFFFFFFF;
238 for (uint32_t i = 0; i < state->page_size; i++) {
239 state->buffer[state->current_page + i] = state->page_buffer[i];
240 }
241 memset(state->page_buffer, 0xFF, state->page_size);
242 }
243 }
244
245 uint8_t nor_flash_read_b(uint32_t address, void *vcontext)
246 {
247 m68k_context *m68k = vcontext;
248 genesis_context *gen = m68k->system;
249 nor_state *state = &gen->nor;
250 if (
251 ((address & 1) && state->bus_flags == RAM_FLAG_EVEN) ||
252 (!(address & 1) && state->bus_flags == RAM_FLAG_ODD)
253 ) {
254 return 0xFF;
255 }
256 if (state->bus_flags != RAM_FLAG_BOTH) {
257 address = address >> 1;
258 }
259
260 nor_run(state, m68k->current_cycle);
261 switch (state->mode)
262 {
263 case NOR_NORMAL:
264 return state->buffer[address & (state->size-1)];
265 break;
266 case NOR_PRODUCTID:
267 switch (address & (state->size - 1))
268 {
269 case 0:
270 return state->product_id >> 8;
271 case 1:
272 return state->product_id;
273 case 2:
274 //TODO: Implement boot block protection
275 return 0xFE;
276 default:
277 return 0xFE;
278 }
279 break;
280 case NOR_BOOTBLOCK:
281 break;
282 }
283 return 0xFF;
284 }
285
286 uint16_t nor_flash_read_w(uint32_t address, void *context)
287 {
288 uint16_t value = nor_flash_read_b(address, context) << 8;
289 value |= nor_flash_read_b(address+1, context);
290 return value;
291 }
292
293 void nor_write_byte(nor_state *state, uint32_t address, uint8_t value, uint32_t cycle)
294 {
295 switch(state->mode)
296 {
297 case NOR_NORMAL:
298 if (state->last_write_cycle != 0xFFFFFFFF) {
299 state->current_page = address & (state->size - 1) & ~(state->page_size - 1);
300 }
301 state->page_buffer[address & (state->page_size - 1)] = value;
302 break;
303 case NOR_PRODUCTID:
304 break;
305 case NOR_BOOTBLOCK:
306 //TODO: Implement boot block protection
307 state->mode = NOR_NORMAL;
308 break;
309 }
310 }
311
312 void *nor_flash_write_b(uint32_t address, void *vcontext, uint8_t value)
313 {
314 m68k_context *m68k = vcontext;
315 genesis_context *gen = m68k->system;
316 nor_state *state = &gen->nor;
317 if (
318 ((address & 1) && state->bus_flags == RAM_FLAG_EVEN) ||
319 (!(address & 1) && state->bus_flags == RAM_FLAG_ODD)
320 ) {
321 return vcontext;
322 }
323 if (state->bus_flags != RAM_FLAG_BOTH) {
324 address = address >> 1;
325 }
326
327 nor_run(state, m68k->current_cycle);
328 switch (state->cmd_state)
329 {
330 case NOR_CMD_IDLE:
331 if (value == 0xAA && (address & (state->size - 1)) == 0x5555) {
332 state->cmd_state = NOR_CMD_AA;
333 } else {
334 nor_write_byte(state, address, value, m68k->current_cycle);
335 state->cmd_state = NOR_CMD_IDLE;
336 }
337 break;
338 case NOR_CMD_AA:
339 if (value == 0x55 && (address & (state->size - 1)) == 0x2AAA) {
340 state->cmd_state = NOR_CMD_55;
341 } else {
342 nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle);
343 nor_write_byte(state, address, value, m68k->current_cycle);
344 state->cmd_state = NOR_CMD_IDLE;
345 }
346 break;
347 case NOR_CMD_55:
348 if ((address & (state->size - 1)) == 0x5555) {
349 if (state->alt_cmd) {
350 switch(value)
351 {
352 case 0x10:
353 puts("UNIMPLEMENTED: NOR flash erase");
354 break;
355 case 0x20:
356 puts("UNIMPLEMENTED: NOR flash disable protection");
357 break;
358 case 0x40:
359 state->mode = NOR_BOOTBLOCK;
360 break;
361 case 0x60:
362 state->mode = NOR_PRODUCTID;
363 break;
364 }
365 } else {
366 switch(value)
367 {
368 case 0x80:
369 state->alt_cmd = 1;
370 break;
371 case 0x90:
372 state->mode = NOR_PRODUCTID;
373 break;
374 case 0xA0:
375 puts("UNIMPLEMENTED: NOR flash enable protection");
376 break;
377 case 0xF0:
378 state->mode = NOR_NORMAL;
379 break;
380 default:
381 printf("Unrecognized unshifted NOR flash command %X\n", value);
382 }
383 }
384 } else {
385 nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle);
386 nor_write_byte(state, 0x2AAA, 0x55, m68k->current_cycle);
387 nor_write_byte(state, address, value, m68k->current_cycle);
388 }
389 state->cmd_state = NOR_CMD_IDLE;
390 break;
391 }
392 return vcontext;
393 }
394
395 void *nor_flash_write_w(uint32_t address, void *vcontext, uint16_t value)
396 {
397 nor_flash_write_b(address, vcontext, value >> 8);
398 return nor_flash_write_b(address + 1, vcontext, value);
399 }
400
190 uint16_t read_sram_w(uint32_t address, m68k_context * context) 401 uint16_t read_sram_w(uint32_t address, m68k_context * context)
191 { 402 {
192 genesis_context * gen = context->system; 403 genesis_context * gen = context->system;
193 address &= gen->save_ram_mask; 404 address &= gen->save_ram_mask;
194 switch(gen->save_type) 405 switch(gen->save_type)
737 state->info->eeprom_map = malloc(sizeof(eeprom_map) * state->num_els); 948 state->info->eeprom_map = malloc(sizeof(eeprom_map) * state->num_els);
738 memset(state->info->eeprom_map, 0, sizeof(eeprom_map) * state->num_els); 949 memset(state->info->eeprom_map, 0, sizeof(eeprom_map) * state->num_els);
739 } 950 }
740 } 951 }
741 952
953 void process_nor_def(char *key, map_iter_state *state)
954 {
955 if (!state->info->save_size) {
956 char *size = tern_find_path(state->root, "NOR\0size\0", TVAL_PTR).ptrval;
957 if (!size) {
958 fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR size is not defined\n", state->index, key);
959 }
960 state->info->save_size = atoi(size);
961 if (!state->info->save_size) {
962 fatal_error("NOR size %s is invalid\n", size);
963 }
964 char *page_size = tern_find_path(state->root, "NOR\0page_size\0", TVAL_PTR).ptrval;
965 if (!page_size) {
966 fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR page size is not defined\n", state->index, key);
967 }
968 state->info->save_page_size = atoi(size);
969 if (!state->info->save_page_size) {
970 fatal_error("NOR page size %s is invalid\n", size);
971 }
972 char *product_id = tern_find_path(state->root, "NOR\0product_id\0", TVAL_PTR).ptrval;
973 if (!product_id) {
974 fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR product ID is not defined\n", state->index, key);
975 }
976 state->info->save_product_id = strtol(product_id, NULL, 16);
977 char *bus = tern_find_path(state->root, "NOR\0bus\0", TVAL_PTR).ptrval;
978 if (!strcmp(bus, "odd")) {
979 state->info->save_bus = RAM_FLAG_ODD;
980 } else if(!strcmp(bus, "even")) {
981 state->info->save_bus = RAM_FLAG_EVEN;
982 } else {
983 state->info->save_bus = RAM_FLAG_BOTH;
984 }
985 state->info->save_type = SAVE_NOR;
986 state->info->save_buffer = malloc(state->info->save_size);
987 memset(state->info->save_buffer, 0xFF, state->info->save_size);
988 }
989 }
990
742 void add_eeprom_map(tern_node *node, uint32_t start, uint32_t end, map_iter_state *state) 991 void add_eeprom_map(tern_node *node, uint32_t start, uint32_t end, map_iter_state *state)
743 { 992 {
744 eeprom_map *eep_map = state->info->eeprom_map + state->info->num_eeprom; 993 eeprom_map *eep_map = state->info->eeprom_map + state->info->num_eeprom;
745 eep_map->start = start; 994 eep_map->start = start;
746 eep_map->end = end; 995 eep_map->end = end;
819 } else if (!strcmp(bus, "even")) { 1068 } else if (!strcmp(bus, "even")) {
820 map->flags |= MMAP_ONLY_EVEN; 1069 map->flags |= MMAP_ONLY_EVEN;
821 } else { 1070 } else {
822 map->flags |= MMAP_CODE; 1071 map->flags |= MMAP_CODE;
823 } 1072 }
1073 } else if (!strcmp(dtype, "NOR")) {
1074 process_nor_def(key, state);
1075
1076 map->write_16 = nor_flash_write_w;
1077 map->write_8 = nor_flash_write_b;
1078 map->read_16 = nor_flash_read_w;
1079 map->read_8 = nor_flash_read_b;
1080 map->mask = 0xFFFFFF;
824 } else if (!strcmp(dtype, "Sega mapper")) { 1081 } else if (!strcmp(dtype, "Sega mapper")) {
825 state->info->mapper_start_index = state->ptr_index++; 1082 state->info->mapper_start_index = state->ptr_index++;
826 state->info->map_chunks+=7; 1083 state->info->map_chunks+=7;
827 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); 1084 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
828 memset(state->info->map + state->info->map_chunks - 7, 0, sizeof(memmap_chunk) * 7); 1085 memset(state->info->map + state->info->map_chunks - 7, 0, sizeof(memmap_chunk) * 7);