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