1 // license:BSD-3-Clause
2 // copyright-holders:Raphael Nabet, Michael Zapf
3 /*
4 Intel 28F640J5 Flash ROM emulation (could also handle 28F320J5 with minor
5 changes, and possibly 28F256J3, 28F128J3, 28F640J3 and 28F320J3)
6
7 The 28F640J5 is a 64Mbit FEEPROM that can be accessed either on an 8-bit or
8 a 16-bit bus.
9
10 References:
11 Datasheets were found on Intel's site (www.intel.com)
12
13 Raphael Nabet 2004, based on MAME's intelfsh.c core
14
15 Device is currently only used in ti99/tn_usbsm
16
17 Rewritten as class
18 Michael Zapf, 2014
19
20 TODO: Make it work
21 */
22
23 #include "emu.h"
24 #include "strata.h"
25
26
27 #define FEEPROM_SIZE 0x800000 // 64Mbit
28 #define BLOCK_SIZE 0x020000
29
30 #define BLOCKLOCK_SIZE ((FEEPROM_SIZE/BLOCK_SIZE+7)/8)
31 #define WRBUF_SIZE 32
32 #define PROT_REGS_SIZE 18
33
34 #define COMPLETE_SIZE FEEPROM_SIZE + WRBUF_SIZE + PROT_REGS_SIZE + BLOCKLOCK_SIZE
35
36 #define ADDRESS_MASK 0x7fffff
37 #define BLOCK_ADDRESS_MASK 0x7e0000
38 #define BLOCK_ADDRESS_SHIFT 17
39 #define BYTE_ADDRESS_MASK 0x01ffff
40
41 /* accessors for individual block lock flags */
42 #define READ_BLOCKLOCK(block) ((m_blocklock[(block) >> 3] >> ((block) & 7)) & 1)
43 #define SET_BLOCKLOCK(block) (m_blocklock[(block) >> 3] |= 1 << ((block) & 7))
44 #define CLEAR_BLOCKLOCK(block) (m_blocklock[(block) >> 3] &= ~(1 << ((block) & 7)))
45
46 DEFINE_DEVICE_TYPE(STRATAFLASH, strataflash_device, "strataflash", "Intel 28F640J5")
47
strataflash_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)48 strataflash_device::strataflash_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
49 : device_t(mconfig, STRATAFLASH, tag, owner, clock)
50 , device_nvram_interface(mconfig, *this)
51 {
52 }
53
54 //-------------------------------------------------
55 // nvram_default - called to initialize NVRAM to
56 // its default state
57 //-------------------------------------------------
58
nvram_default()59 void strataflash_device::nvram_default()
60 {
61 memset(m_flashmemory.get(), 0, COMPLETE_SIZE);
62 }
63
64 //-------------------------------------------------
65 // nvram_read - called to read NVRAM from the
66 // .nv file
67 //-------------------------------------------------
68
nvram_read(emu_file & file)69 void strataflash_device::nvram_read(emu_file &file)
70 {
71 file.read(m_flashmemory.get(), COMPLETE_SIZE);
72
73 // TODO
74
75 /*
76 uint8_t buf;
77 int i;
78
79 // version flag
80 if (file->read(& buf, 1) != 1)
81 return 1;
82 if (buf != 0)
83 return 1;
84
85 // chip state: master lock
86 if (file->read(& buf, 1) != 1)
87 return 1;
88 m_master_lock = buf & 1;
89
90 // main FEEPROM area
91 if (file->read(m_flashmemory, FEEPROM_SIZE) != FEEPROM_SIZE)
92 return 1;
93 for (i = 0; i < FEEPROM_SIZE; i += 2)
94 {
95 uint16_t *ptr = (uint16_t *) (&m_flashmemory[i]);
96 *ptr = little_endianize_int16(*ptr);
97 }
98
99 // protection registers
100 if (file->read(m_prot_regs, PROT_REGS_SIZE) != PROT_REGS_SIZE)
101 return 1;
102 for (i = 0; i < PROT_REGS_SIZE; i += 2)
103 {
104 uint16_t *ptr = (uint16_t *) (&m_prot_regs[i]);
105 *ptr = little_endianize_int16(*ptr);
106 }
107
108 // block lock flags
109 if (file->read(m_blocklock, BLOCKLOCK_SIZE) != BLOCKLOCK_SIZE)
110 return 1;
111
112 return 0;
113 */
114 }
115
116 //-------------------------------------------------
117 // nvram_write - called to write NVRAM to the
118 // .nv file
119 //-------------------------------------------------
120
nvram_write(emu_file & file)121 void strataflash_device::nvram_write(emu_file &file)
122 {
123 // TODO
124
125 /*
126 uint8_t buf;
127 int i;
128
129 // version flag
130 buf = 0;
131 if (file->write(& buf, 1) != 1)
132 return 1;
133
134 // chip state: lower boot block lockout, higher boot block lockout,
135 software data protect
136 buf = m_master_lock;
137 if (file->write(& buf, 1) != 1)
138 return 1;
139
140 // main FEEPROM area
141 for (i = 0; i < FEEPROM_SIZE; i += 2)
142 {
143 uint16_t *ptr = (uint16_t *) (&m_flashmemory[i]);
144 *ptr = little_endianize_int16(*ptr);
145 }
146 if (file->write(m_flashmemory, FEEPROM_SIZE) != FEEPROM_SIZE)
147 return 1;
148 for (i = 0; i < FEEPROM_SIZE; i += 2)
149 {
150 uint16_t *ptr = (uint16_t *) (&m_flashmemory[i]);
151 *ptr = little_endianize_int16(*ptr);
152 }
153
154 // protection registers
155 for (i = 0; i < PROT_REGS_SIZE; i += 2)
156 {
157 uint16_t *ptr = (uint16_t *) (&m_prot_regs[i]);
158 *ptr = little_endianize_int16(*ptr);
159 }
160 if (file->write(m_prot_regs, PROT_REGS_SIZE) != PROT_REGS_SIZE)
161 return 1;
162 for (i = 0; i < PROT_REGS_SIZE; i += 2)
163 {
164 uint16_t *ptr = (uint16_t *) (&m_prot_regs[i]);
165 *ptr = little_endianize_int16(*ptr);
166 }
167
168 // block lock flags
169 if (file->write(m_blocklock, BLOCKLOCK_SIZE) != BLOCKLOCK_SIZE)
170 return 1;
171
172 return 0;
173 */
174
175 file.write(m_flashmemory.get(), COMPLETE_SIZE);
176 }
177
178 //-------------------------------------------------
179 // device_start - device-specific startup
180 //-------------------------------------------------
device_start()181 void strataflash_device::device_start()
182 {
183 m_mode = FM_NORMAL;
184 m_status = 0x80;
185 m_master_lock = 0;
186 m_flashmemory = std::make_unique<uint8_t[]>(COMPLETE_SIZE);
187
188 m_wrbuf = m_flashmemory.get() + FEEPROM_SIZE;
189 m_prot_regs = m_wrbuf + WRBUF_SIZE;
190 m_blocklock = m_prot_regs + PROT_REGS_SIZE;
191
192 // clear various FEEPROM areas
193 memset(m_prot_regs, 0xff, 18);
194 memset(m_flashmemory.get(), 0xff, FEEPROM_SIZE);
195 memset(m_blocklock, 0x00, BLOCKLOCK_SIZE);
196
197 // set-up factory-programmed protection register segment
198 m_prot_regs[BYTE_XOR_LE(0)] &= 0xfe;
199 for (int i=2; i<10; i++)
200 m_prot_regs[i] = machine().rand();
201 }
202
203 /*
204 read a 8/16-bit word from FEEPROM
205 */
read8_16(offs_t offset,bus_width_t bus_width)206 uint16_t strataflash_device::read8_16(offs_t offset, bus_width_t bus_width)
207 {
208 switch (bus_width)
209 {
210 case bw_8:
211 offset &= ADDRESS_MASK;
212 break;
213 case bw_16:
214 offset &= ADDRESS_MASK & ~1;
215 }
216
217 switch (m_mode)
218 {
219 default:
220 case FM_NORMAL:
221 switch (bus_width)
222 {
223 case bw_8:
224 return m_flashmemory[BYTE_XOR_LE(offset)];
225 case bw_16:
226 return *(uint16_t*)(m_flashmemory.get()+offset);
227 }
228 break;
229 case FM_READSTATUS:
230 return m_status;
231 case FM_WRBUFPART1:
232 return 0x80;
233 case FM_READID:
234 if ((offset >= 0x100) && (offset < 0x112))
235 { /* protection registers */
236 switch (bus_width)
237 {
238 case bw_8:
239 return m_prot_regs[BYTE_XOR_LE(offset)];
240 case bw_16:
241 return *(uint16_t*)(m_prot_regs+offset);
242 }
243 }
244 else
245 switch (offset >> 1)
246 {
247 case 0: // maker ID
248 return 0x89; // Intel
249 case 1: // chip ID
250 return 0x15; // 64 Mbit
251 default:
252 if (((offset & BYTE_ADDRESS_MASK) >> 1) == 2)
253 { // block lock config
254 return READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT);
255 }
256 return 0; // default case
257 case 3: // master lock config
258 if (m_master_lock)
259 return 1;
260 else
261 return 0;
262 }
263 break;
264 case FM_READQUERY:
265 switch (offset >> 1)
266 {
267 case 0x00: // maker ID
268 return 0x89; // Intel
269 case 0x01: // chip ID
270 return 0x15; // 64 Mbit
271 default:
272 if (((offset & BYTE_ADDRESS_MASK) >> 1) == 2)
273 { // block lock config
274 return READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT);
275 }
276 return 0; // default case
277 #if 0
278 case 0x03: // master lock config
279 if (m_flash_master_lock)
280 return 1;
281 else
282 return 0;
283 #endif
284
285 /* CFI query identification string */
286 case 0x10:
287 return 'Q';
288 case 0x11:
289 return 'R';
290 case 0x12:
291 return 'Y';
292 case 0x13:
293 return 0x01;
294 case 0x14:
295 return 0x00;
296 case 0x15:
297 return 0x31;
298 case 0x16:
299 return 0x00;
300 case 0x17:
301 case 0x18:
302 case 0x19:
303 case 0x1a:
304 return 0x00;
305
306 /* system interface information: voltage */
307 case 0x1b:
308 return 0x45;
309 case 0x1c:
310 return 0x55;
311 case 0x1d:
312 return 0x00;
313 case 0x1e:
314 return 0x00;
315
316 /* system interface information: timings */
317 case 0x1f:
318 return /*0x07*/0x00;
319 case 0x20:
320 return /*0x07*/0x00;
321 case 0x21:
322 return /*0x0a*/0x00;
323 case 0x22:
324 return 0x00;
325 case 0x23:
326 return /*0x04*/0x00;
327 case 0x24:
328 return /*0x04*/0x00;
329 case 0x25:
330 return /*0x04*/0x00;
331 case 0x26:
332 return 0x00;
333
334 /* device geometry definition */
335 case 0x27:
336 return 0x17;
337 case 0x28:
338 return 0x02;
339 case 0x29:
340 return 0x00;
341 case 0x2a:
342 return 0x05;
343 case 0x2b:
344 return 0x00;
345 case 0x2c:
346 return 0x01;
347 case 0x2d:
348 return 0x3f;
349 case 0x2e:
350 return 0x00;
351 case 0x2f:
352 return 0x00;
353 case 0x30:
354 return 0x02;
355
356 /* primary vendor-specific extended query */
357 case 0x31:
358 return 'P';
359 case 0x32:
360 return 'R';
361 case 0x33:
362 return 'I';
363 case 0x34:
364 return '1';
365 case 0x35:
366 return '1';
367 case 0x36:
368 return 0x0a;
369 case 0x37:
370 return 0x00;
371 case 0x38:
372 return 0x00;
373 case 0x39:
374 return 0x00;
375 case 0x3a:
376 return 0x01;
377 case 0x3b:
378 return 0x01;
379 case 0x3c:
380 return 0x00;
381 case 0x3d:
382 return 0x50;
383 case 0x3e:
384 return 0x00;
385 case 0x3f:
386 return 0x00;
387 }
388 }
389
390 return 0;
391 }
392
393 /*
394 write a 8/16-bit word to FEEPROM
395 */
write8_16(offs_t offset,uint16_t data,bus_width_t bus_width)396 void strataflash_device::write8_16(offs_t offset, uint16_t data, bus_width_t bus_width)
397 {
398 switch (bus_width)
399 {
400 case bw_8:
401 offset &= ADDRESS_MASK;
402 break;
403 case bw_16:
404 offset &= ADDRESS_MASK & ~1;
405 break;
406 }
407
408 switch (m_mode)
409 {
410 case FM_NORMAL:
411 case FM_READID:
412 case FM_READQUERY:
413 case FM_READSTATUS:
414 switch (data)
415 {
416 case 0xff: // read array
417 m_mode = FM_NORMAL;
418 break;
419 case 0x90: // read identifier codes
420 m_mode = FM_READID;
421 break;
422 case 0x98: // read query
423 m_mode = FM_READQUERY;
424 break;
425 case 0x70: // read status register
426 m_mode = FM_READSTATUS;
427 break;
428 case 0x50: // clear status register
429 m_mode = FM_READSTATUS;
430 m_status &= 0xC5;
431 break;
432 case 0xe8: // write to buffer
433 m_mode = FM_WRBUFPART1;
434 m_wrbuf_base = offset & BLOCK_ADDRESS_MASK;
435 /*m_status &= 0xC5;*/
436 break;
437 case 0x40:
438 case 0x10: // program
439 m_mode = FM_WRITEPART1;
440 m_status &= 0xC5;
441 break;
442 case 0x20: // block erase
443 m_mode = FM_CLEARPART1;
444 m_status &= 0xC5;
445 break;
446 case 0xb0: // block erase, program suspend
447 /* not emulated (erase is instantaneous) */
448 break;
449 case 0xd0: // block erase, program resume
450 /* not emulated (erase is instantaneous) */
451 break;
452 case 0xb8: // configuration
453 m_mode = FM_CONFPART1;
454 m_status &= 0xC5;
455 break;
456 case 0x60: // set master lock
457 m_mode = FM_SETLOCK;
458 m_status &= 0xC5;
459 break;
460 case 0xc0: // protection program
461 m_mode = FM_WRPROTPART1;
462 m_status &= 0xC5;
463 break;
464 default:
465 logerror("Unknown flash mode byte %x\n", data);
466 break;
467 }
468 break;
469 case FM_WRBUFPART1:
470 m_mode = FM_WRBUFPART2;
471 if (((offset & BLOCK_ADDRESS_MASK) != m_wrbuf_base) || (data >= 0x20))
472 {
473 m_status |= 0x30;
474 m_wrbuf_len = 0;
475 m_wrbuf_count = data;
476 }
477 else
478 {
479 switch (bus_width)
480 {
481 case bw_8:
482 m_wrbuf_len = data+1;
483 break;
484 case bw_16:
485 m_wrbuf_len = (data+1) << 1;
486 break;
487 }
488 m_wrbuf_count = data;
489 }
490 break;
491 case FM_WRBUFPART2:
492 m_mode = FM_WRBUFPART3;
493 if (((offset & BLOCK_ADDRESS_MASK) != m_wrbuf_base)
494 || (((offset & BYTE_ADDRESS_MASK) + m_wrbuf_len) > BLOCK_SIZE))
495 {
496 m_status |= 0x30;
497 m_wrbuf_len = 0;
498 m_wrbuf_base = 0;
499 }
500 else
501 m_wrbuf_base = offset;
502 memset(m_wrbuf, 0xff, m_wrbuf_len); /* right??? */
503 case FM_WRBUFPART3:
504 if ((offset < m_wrbuf_base) || (offset >= (m_wrbuf_base + m_wrbuf_len)))
505 m_status |= 0x30;
506 else
507 {
508 switch (bus_width)
509 {
510 case bw_8:
511 m_wrbuf[offset-m_wrbuf_base] = data;
512 break;
513 case bw_16:
514 m_wrbuf[offset-m_wrbuf_base] = data & 0xff;
515 m_wrbuf[offset-m_wrbuf_base+1] = data >> 8;
516 break;
517 }
518 }
519 if (m_wrbuf_count == 0)
520 m_mode = FM_WRBUFPART4;
521 else
522 m_wrbuf_count--;
523 break;
524 case FM_WRBUFPART4:
525 if (((offset & BLOCK_ADDRESS_MASK) != (m_wrbuf_base & BLOCK_ADDRESS_MASK)) || (data != 0xd0))
526 {
527 m_status |= 0x30;
528 }
529 else if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock)
530 {
531 m_status |= 0x12;
532 }
533 else if (!(m_status & 0x30))
534 {
535 int i;
536 for (i=0; i<m_wrbuf_len; i++)
537 m_flashmemory[BYTE_XOR_LE(m_wrbuf_base+i)] &= m_wrbuf[i];
538 m_mode = FM_READSTATUS;
539 }
540 break;
541 case FM_WRITEPART1:
542 if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock)
543 {
544 m_status |= 0x12;
545 }
546 else
547 {
548 switch (bus_width)
549 {
550 case bw_8:
551 m_flashmemory[BYTE_XOR_LE(offset)] &= data;
552 break;
553 case bw_16:
554 *(uint16_t*)(m_flashmemory.get()+offset) &= data;
555 break;
556 }
557 }
558 m_mode = FM_READSTATUS;
559 break;
560 case FM_CLEARPART1:
561 if (data == 0xd0)
562 {
563 // clear the 128k block containing the current address
564 // to all 0xffs
565 if (READ_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT) && !m_hard_unlock)
566 {
567 m_status |= 0x22;
568 }
569 else
570 {
571 offset &= BLOCK_ADDRESS_MASK;
572 memset(&m_flashmemory[offset], 0xff, BLOCK_SIZE);
573 }
574 m_mode = FM_READSTATUS;
575 }
576 break;
577 case FM_SETLOCK:
578 switch (data)
579 {
580 case 0xf1:
581 if (!m_hard_unlock)
582 m_status |= 0x12;
583 else
584 m_master_lock = 1;
585 break;
586 case 0x01:
587 if (m_master_lock && !m_hard_unlock)
588 m_status |= 0x12;
589 else
590 SET_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT);
591 break;
592 case 0xd0:
593 if (m_master_lock && !m_hard_unlock)
594 m_status |= 0x22;
595 else
596 CLEAR_BLOCKLOCK(offset >> BLOCK_ADDRESS_SHIFT);
597 break;
598 case 0x03: // Set Read configuration
599 /* ignore command */
600 break;
601 default:
602 m_status |= 0x30;
603 break;
604 }
605 m_mode = FM_READSTATUS;
606 break;
607 case FM_CONFPART1:
608 /* configuration register is not emulated because the sts pin is not */
609 //m_configuration = data;
610 m_mode = FM_READSTATUS; /* right??? */
611 break;
612 case FM_WRPROTPART1:
613 if ((offset < 0x100) || (offset >= 0x112))
614 m_status |= 0x10;
615 else if ((offset >= 0x102) && !((m_prot_regs[BYTE_XOR_LE(0)] >> ((offset - 0x102) >> 3)) & 1))
616 m_status |= 0x12;
617 else
618 {
619 switch (bus_width)
620 {
621 case bw_8:
622 m_prot_regs[BYTE_XOR_LE(offset-0x100)] &= data;
623 break;
624 case bw_16:
625 *(uint16_t*)(m_prot_regs+(offset-0x100)) &= data;
626 break;
627 }
628 }
629 m_mode = FM_READSTATUS; /* right??? */
630 break;
631 }
632 }
633
634 /*
635 read a byte from FEEPROM
636 */
read8(offs_t offset)637 uint8_t strataflash_device::read8(offs_t offset)
638 {
639 return read8_16(offset, bw_8);
640 }
641
642 /*
643 Write a byte to FEEPROM
644 */
write8(offs_t offset,uint8_t data)645 void strataflash_device::write8(offs_t offset, uint8_t data)
646 {
647 write8_16(offset, data, bw_8);
648 }
649
650 /*
651 read a 16-bit word from FEEPROM
652 */
read16(offs_t offset)653 uint16_t strataflash_device::read16(offs_t offset)
654 {
655 return read8_16(offset, bw_16);
656 }
657
658 /*
659 Write a byte to FEEPROM
660 */
write16(offs_t offset,uint16_t data)661 void strataflash_device::write16(offs_t offset, uint16_t data)
662 {
663 write8_16(offset, data, bw_16);
664 }
665