remove PARAMS from include/cgen
[deliverable/binutils-gdb.git] / sim / common / dv-cfi.c
CommitLineData
66ee2731
MF
1/* Common Flash Memory Interface (CFI) model.
2 http://www.spansion.com/Support/AppNotes/CFI_Spec_AN_03.pdf
3 http://www.spansion.com/Support/AppNotes/cfi_100_20011201.pdf
4
ecd75fc8 5 Copyright (C) 2010-2014 Free Software Foundation, Inc.
66ee2731
MF
6 Contributed by Analog Devices, Inc.
7
8 This file is part of simulators.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
22
23/* TODO: support vendor query tables. */
24
25#include "cconfig.h"
26
27#include <math.h>
28#include <errno.h>
29#include <fcntl.h>
66f8d993 30#include <stdbool.h>
66ee2731
MF
31#include <unistd.h>
32#ifdef HAVE_SYS_MMAN_H
33#include <sys/mman.h>
34#endif
35
36#include "sim-main.h"
d56a2aae
MF
37#include "hw-base.h"
38#include "hw-main.h"
66ee2731
MF
39#include "dv-cfi.h"
40
41/* Flashes are simple state machines, so here we cover all the
42 different states a device might be in at any particular time. */
43enum cfi_state
44{
45 CFI_STATE_READ,
46 CFI_STATE_READ_ID,
47 CFI_STATE_CFI_QUERY,
48 CFI_STATE_PROTECT,
49 CFI_STATE_STATUS,
50 CFI_STATE_ERASE,
51 CFI_STATE_WRITE,
52 CFI_STATE_WRITE_BUFFER,
53 CFI_STATE_WRITE_BUFFER_CONFIRM,
54};
55
56/* This is the structure that all CFI conforming devices must provided
57 when asked for it. This allows a single driver to dynamically support
58 different flash geometries without having to hardcode specs.
59
60 If you want to start mucking about here, you should just grab the
61 CFI spec and review that (see top of this file for URIs). */
62struct cfi_query
63{
64 /* This is always 'Q' 'R' 'Y'. */
65 unsigned char qry[3];
66 /* Primary vendor ID. */
67 unsigned char p_id[2];
68 /* Primary query table address. */
69 unsigned char p_adr[2];
70 /* Alternate vendor ID. */
71 unsigned char a_id[2];
72 /* Alternate query table address. */
73 unsigned char a_adr[2];
74 union
75 {
76 /* Voltage levels. */
77 unsigned char voltages[4];
78 struct
79 {
80 /* Normal min voltage level. */
81 unsigned char vcc_min;
82 /* Normal max voltage level. */
83 unsigned char vcc_max;
84 /* Programming min volage level. */
85 unsigned char vpp_min;
86 /* Programming max volage level. */
87 unsigned char vpp_max;
88 };
89 };
90 union
91 {
92 /* Operational timeouts. */
93 unsigned char timeouts[8];
94 struct
95 {
96 /* Typical timeout for writing a single "unit". */
97 unsigned char timeout_typ_unit_write;
98 /* Typical timeout for writing a single "buffer". */
99 unsigned char timeout_typ_buf_write;
100 /* Typical timeout for erasing a block. */
101 unsigned char timeout_typ_block_erase;
102 /* Typical timeout for erasing the chip. */
103 unsigned char timeout_typ_chip_erase;
104 /* Max timeout for writing a single "unit". */
105 unsigned char timeout_max_unit_write;
106 /* Max timeout for writing a single "buffer". */
107 unsigned char timeout_max_buf_write;
108 /* Max timeout for erasing a block. */
109 unsigned char timeout_max_block_erase;
110 /* Max timeout for erasing the chip. */
111 unsigned char timeout_max_chip_erase;
112 };
113 };
114 /* Flash size is 2^dev_size bytes. */
115 unsigned char dev_size;
116 /* Flash device interface description. */
117 unsigned char iface_desc[2];
118 /* Max length of a single buffer write is 2^max_buf_write_len bytes. */
119 unsigned char max_buf_write_len[2];
120 /* Number of erase regions. */
121 unsigned char num_erase_regions;
122 /* The erase regions would now be an array after this point, but since
123 it is dynamic, we'll provide that from "struct cfi" when requested. */
124 /*unsigned char erase_region_info;*/
125};
126
127/* Flashes may have regions with different erase sizes. There is one
128 structure per erase region. */
129struct cfi_erase_region
130{
131 unsigned blocks;
132 unsigned size;
133 unsigned start;
134 unsigned end;
135};
136
137struct cfi;
138
139/* Flashes are accessed via commands -- you write a certain number to
140 a special address to change the flash state and access info other
141 than the data. Diff companies have implemented their own command
142 set. This structure abstracts the different command sets so that
143 we can support multiple ones with just a single sim driver. */
144struct cfi_cmdset
145{
146 unsigned id;
147 void (*setup) (struct hw *me, struct cfi *cfi);
148 bool (*write) (struct hw *me, struct cfi *cfi, const void *source,
149 unsigned offset, unsigned value, unsigned nr_bytes);
150 bool (*read) (struct hw *me, struct cfi *cfi, void *dest,
151 unsigned offset, unsigned shifted_offset, unsigned nr_bytes);
152};
153
154/* The per-flash state. Much of this comes from the device tree which
155 people declare themselves. See top of attach_cfi_regs() for more
156 info. */
157struct cfi
158{
159 unsigned width, dev_size, status;
160 enum cfi_state state;
161 unsigned char *data, *mmap;
162
163 struct cfi_query query;
164 const struct cfi_cmdset *cmdset;
165
166 unsigned char *erase_region_info;
167 struct cfi_erase_region *erase_regions;
168};
169
170/* Helpful strings which are used with HW_TRACE. */
171static const char * const state_names[] =
172{
173 "READ", "READ_ID", "CFI_QUERY", "PROTECT", "STATUS", "ERASE", "WRITE",
174 "WRITE_BUFFER", "WRITE_BUFFER_CONFIRM",
175};
176\f
177/* Erase the block specified by the offset into the given CFI flash. */
178static void
179cfi_erase_block (struct hw *me, struct cfi *cfi, unsigned offset)
180{
181 unsigned i;
182 struct cfi_erase_region *region;
183
184 /* If no erase regions, then we can only do whole chip erase. */
185 /* XXX: Is this within spec ? Or must there always be at least one ? */
186 if (!cfi->query.num_erase_regions)
187 memset (cfi->data, 0xff, cfi->dev_size);
188
189 for (i = 0; i < cfi->query.num_erase_regions; ++i)
190 {
191 region = &cfi->erase_regions[i];
192
193 if (offset >= region->end)
194 continue;
195
196 /* XXX: Does spec require the erase addr to be erase block aligned ?
197 Maybe this is check is overly cautious ... */
198 offset &= ~(region->size - 1);
199 memset (cfi->data + offset, 0xff, region->size);
200 break;
201 }
202}
203
204/* Depending on the bus width, addresses might be bit shifted. This
205 helps us normalize everything without cluttering up the rest of
206 the code. */
207static unsigned
208cfi_unshift_addr (struct cfi *cfi, unsigned addr)
209{
210 switch (cfi->width)
211 {
212 case 4: addr >>= 1; /* fallthrough. */
213 case 2: addr >>= 1;
214 }
215 return addr;
216}
217
218/* CFI requires all values to be little endian in its structure, so
219 this helper writes a 16bit value into a little endian byte buffer. */
220static void
221cfi_encode_16bit (unsigned char *data, unsigned num)
222{
223 data[0] = num;
224 data[1] = num >> 8;
225}
226\f
227/* The functions required to implement the Intel command set. */
228
229static bool
230cmdset_intel_write (struct hw *me, struct cfi *cfi, const void *source,
231 unsigned offset, unsigned value, unsigned nr_bytes)
232{
233 switch (cfi->state)
234 {
235 case CFI_STATE_READ:
236 case CFI_STATE_READ_ID:
237 switch (value)
238 {
239 case INTEL_CMD_ERASE_BLOCK:
240 cfi->state = CFI_STATE_ERASE;
241 break;
242 case INTEL_CMD_WRITE:
243 case INTEL_CMD_WRITE_ALT:
244 cfi->state = CFI_STATE_WRITE;
245 break;
246 case INTEL_CMD_STATUS_CLEAR:
247 cfi->status = INTEL_SR_DWS;
248 break;
249 case INTEL_CMD_LOCK_SETUP:
250 cfi->state = CFI_STATE_PROTECT;
251 break;
252 default:
253 return false;
254 }
255 break;
256
257 case CFI_STATE_ERASE:
258 if (value == INTEL_CMD_ERASE_CONFIRM)
259 {
260 cfi_erase_block (me, cfi, offset);
261 cfi->status &= ~(INTEL_SR_PS | INTEL_SR_ES);
262 }
263 else
264 cfi->status |= INTEL_SR_PS | INTEL_SR_ES;
265 cfi->state = CFI_STATE_STATUS;
266 break;
267
268 case CFI_STATE_PROTECT:
269 switch (value)
270 {
271 case INTEL_CMD_LOCK_BLOCK:
272 case INTEL_CMD_UNLOCK_BLOCK:
273 case INTEL_CMD_LOCK_DOWN_BLOCK:
274 /* XXX: Handle the command. */
275 break;
276 default:
277 /* Kick out. */
278 cfi->status |= INTEL_SR_PS | INTEL_SR_ES;
279 break;
280 }
281 cfi->state = CFI_STATE_STATUS;
282 break;
283
284 default:
285 return false;
286 }
287
288 return true;
289}
290
291static bool
292cmdset_intel_read (struct hw *me, struct cfi *cfi, void *dest,
293 unsigned offset, unsigned shifted_offset, unsigned nr_bytes)
294{
295 unsigned char *sdest = dest;
296
297 switch (cfi->state)
298 {
299 case CFI_STATE_STATUS:
300 case CFI_STATE_ERASE:
301 *sdest = cfi->status;
302 break;
303
304 case CFI_STATE_READ_ID:
305 switch (shifted_offset & 0x1ff)
306 {
307 case 0x00: /* Manufacturer Code. */
308 cfi_encode_16bit (dest, INTEL_ID_MANU);
309 break;
310 case 0x01: /* Device ID Code. */
311 /* XXX: Push to device tree ? */
312 cfi_encode_16bit (dest, 0xad);
313 break;
314 case 0x02: /* Block lock state. */
315 /* XXX: This is per-block ... */
316 *sdest = 0x00;
317 break;
318 case 0x05: /* Read Configuration Register. */
319 cfi_encode_16bit (dest, (1 << 15));
320 break;
321 default:
322 return false;
323 }
324 break;
325
326 default:
327 return false;
328 }
329
330 return true;
331}
332
333static void
334cmdset_intel_setup (struct hw *me, struct cfi *cfi)
335{
336 cfi->status = INTEL_SR_DWS;
337}
338
339static const struct cfi_cmdset cfi_cmdset_intel =
340{
341 CFI_CMDSET_INTEL, cmdset_intel_setup, cmdset_intel_write, cmdset_intel_read,
342};
343\f
344/* All of the supported command sets get listed here. We then walk this
345 array to see if the user requested command set is implemented. */
346static const struct cfi_cmdset * const cfi_cmdsets[] =
347{
348 &cfi_cmdset_intel,
349};
350\f
351/* All writes to the flash address space come here. Using the state
352 machine, we figure out what to do with this specific write. All
353 common code sits here and if there is a request we can't process,
354 we hand it off to the command set-specific write function. */
355static unsigned
356cfi_io_write_buffer (struct hw *me, const void *source, int space,
357 address_word addr, unsigned nr_bytes)
358{
359 struct cfi *cfi = hw_data (me);
360 const unsigned char *ssource = source;
361 enum cfi_state old_state;
362 unsigned offset, shifted_offset, value;
363
364 offset = addr & (cfi->dev_size - 1);
365 shifted_offset = cfi_unshift_addr (cfi, offset);
366
367 if (cfi->width != nr_bytes)
368 {
369 HW_TRACE ((me, "write 0x%08lx length %u does not match flash width %u",
370 (unsigned long) addr, nr_bytes, cfi->width));
371 return nr_bytes;
372 }
373
374 if (cfi->state == CFI_STATE_WRITE)
375 {
376 /* NOR flash can only go from 1 to 0. */
377 unsigned i;
378
379 HW_TRACE ((me, "program %#x length %u", offset, nr_bytes));
380
381 for (i = 0; i < nr_bytes; ++i)
382 cfi->data[offset + i] &= ssource[i];
383
384 cfi->state = CFI_STATE_STATUS;
385
386 return nr_bytes;
387 }
388
389 value = ssource[0];
390
391 old_state = cfi->state;
392
393 if (value == CFI_CMD_READ || value == CFI_CMD_RESET)
394 {
395 cfi->state = CFI_STATE_READ;
396 goto done;
397 }
398
399 switch (cfi->state)
400 {
401 case CFI_STATE_READ:
402 case CFI_STATE_READ_ID:
403 if (value == CFI_CMD_CFI_QUERY)
404 {
405 if (shifted_offset == CFI_ADDR_CFI_QUERY_START)
406 cfi->state = CFI_STATE_CFI_QUERY;
407 goto done;
408 }
409
410 if (value == CFI_CMD_READ_ID)
411 {
412 cfi->state = CFI_STATE_READ_ID;
413 goto done;
414 }
415
416 /* Fall through. */
417
418 default:
419 if (!cfi->cmdset->write (me, cfi, source, offset, value, nr_bytes))
420 HW_TRACE ((me, "unhandled command %#x at %#x", value, offset));
421 break;
422 }
423
424 done:
425 HW_TRACE ((me, "write 0x%08lx command {%#x,%#x,%#x,%#x}; state %s -> %s",
426 (unsigned long) addr, ssource[0],
427 nr_bytes > 1 ? ssource[1] : 0,
428 nr_bytes > 2 ? ssource[2] : 0,
429 nr_bytes > 3 ? ssource[3] : 0,
430 state_names[old_state], state_names[cfi->state]));
431
432 return nr_bytes;
433}
434
435/* All reads to the flash address space come here. Using the state
436 machine, we figure out what to return -- actual data stored in the
437 flash, the CFI query structure, some status info, or something else ?
438 Any requests that we can't handle are passed to the command set-
439 specific read function. */
440static unsigned
441cfi_io_read_buffer (struct hw *me, void *dest, int space,
442 address_word addr, unsigned nr_bytes)
443{
444 struct cfi *cfi = hw_data (me);
445 unsigned char *sdest = dest;
446 unsigned offset, shifted_offset;
447
448 offset = addr & (cfi->dev_size - 1);
449 shifted_offset = cfi_unshift_addr (cfi, offset);
450
451 /* XXX: Is this OK to enforce ? */
452#if 0
453 if (cfi->state != CFI_STATE_READ && cfi->width != nr_bytes)
454 {
455 HW_TRACE ((me, "read 0x%08lx length %u does not match flash width %u",
456 (unsigned long) addr, nr_bytes, cfi->width));
457 return nr_bytes;
458 }
459#endif
460
461 HW_TRACE ((me, "%s read 0x%08lx length %u",
462 state_names[cfi->state], (unsigned long) addr, nr_bytes));
463
464 switch (cfi->state)
465 {
466 case CFI_STATE_READ:
467 memcpy (dest, cfi->data + offset, nr_bytes);
468 break;
469
470 case CFI_STATE_CFI_QUERY:
471 if (shifted_offset >= CFI_ADDR_CFI_QUERY_RESULT &&
472 shifted_offset < CFI_ADDR_CFI_QUERY_RESULT + sizeof (cfi->query) +
473 (cfi->query.num_erase_regions * 4))
474 {
475 unsigned char *qry;
476
477 shifted_offset -= CFI_ADDR_CFI_QUERY_RESULT;
478 if (shifted_offset >= sizeof (cfi->query))
479 {
480 qry = cfi->erase_region_info;
481 shifted_offset -= sizeof (cfi->query);
482 }
483 else
484 qry = (void *) &cfi->query;
485
486 sdest[0] = qry[shifted_offset];
487 memset (sdest + 1, 0, nr_bytes - 1);
488
489 break;
490 }
491
492 default:
493 if (!cfi->cmdset->read (me, cfi, dest, offset, shifted_offset, nr_bytes))
494 HW_TRACE ((me, "unhandled state %s", state_names[cfi->state]));
495 break;
496 }
497
498 return nr_bytes;
499}
500
501/* Clean up any state when this device is removed (e.g. when shutting
502 down, or when reloading via gdb). */
503static void
504cfi_delete_callback (struct hw *me)
505{
506#ifdef HAVE_MMAP
507 struct cfi *cfi = hw_data (me);
508
509 if (cfi->mmap)
510 munmap (cfi->mmap, cfi->dev_size);
511#endif
512}
513
514/* Helper function to easily add CFI erase regions to the existing set. */
515static void
516cfi_add_erase_region (struct hw *me, struct cfi *cfi,
517 unsigned blocks, unsigned size)
518{
519 unsigned num_regions = cfi->query.num_erase_regions;
520 struct cfi_erase_region *region;
521 unsigned char *qry_region;
522
523 /* Store for our own usage. */
524 region = &cfi->erase_regions[num_regions];
525 region->blocks = blocks;
526 region->size = size;
527 if (num_regions == 0)
528 region->start = 0;
529 else
530 region->start = region[-1].end;
531 region->end = region->start + (blocks * size);
532
533 /* Regions are 4 bytes long. */
534 qry_region = cfi->erase_region_info + 4 * num_regions;
535
536 /* [0][1] = number erase blocks - 1 */
537 if (blocks > 0xffff + 1)
538 hw_abort (me, "erase blocks %u too big to fit into region info", blocks);
539 cfi_encode_16bit (&qry_region[0], blocks - 1);
540
541 /* [2][3] = block size / 256 bytes */
542 if (size > 0xffff * 256)
543 hw_abort (me, "erase size %u too big to fit into region info", size);
544 cfi_encode_16bit (&qry_region[2], size / 256);
545
546 /* Yet another region. */
547 cfi->query.num_erase_regions = num_regions + 1;
548}
549
550/* Device tree options:
551 Required:
552 .../reg <addr> <len>
553 .../cmdset <primary; integer> [alt; integer]
554 Optional:
555 .../size <device size (must be pow of 2)>
556 .../width <8|16|32>
557 .../write_size <integer (must be pow of 2)>
558 .../erase_regions <number blocks> <block size> \
559 [<number blocks> <block size> ...]
560 .../voltage <vcc min> <vcc max> <vpp min> <vpp max>
561 .../timeouts <typ unit write> <typ buf write> \
562 <typ block erase> <typ chip erase> \
563 <max unit write> <max buf write> \
564 <max block erase> <max chip erase>
565 .../file <file> [ro|rw]
566 Defaults:
567 size: <len> from "reg"
568 width: 8
569 write_size: 0 (not supported)
570 erase_region: 1 (can only erase whole chip)
571 voltage: 0.0V (for all)
572 timeouts: typ: 1µs, not supported, 1ms, not supported
573 max: 1µs, 1ms, 1ms, not supported
574
575 TODO: Verify user args are valid (e.g. voltage is 8 bits). */
576static void
577attach_cfi_regs (struct hw *me, struct cfi *cfi)
578{
579 address_word attach_address;
580 int attach_space;
581 unsigned attach_size;
582 reg_property_spec reg;
583 bool fd_writable;
584 int i, ret, fd;
585 signed_cell ival;
586
587 if (hw_find_property (me, "reg") == NULL)
588 hw_abort (me, "Missing \"reg\" property");
589 if (hw_find_property (me, "cmdset") == NULL)
590 hw_abort (me, "Missing \"cmdset\" property");
591
592 if (!hw_find_reg_array_property (me, "reg", 0, &reg))
593 hw_abort (me, "\"reg\" property must contain three addr/size entries");
594
595 hw_unit_address_to_attach_address (hw_parent (me),
596 &reg.address,
597 &attach_space, &attach_address, me);
598 hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
599
600 hw_attach_address (hw_parent (me),
601 0, attach_space, attach_address, attach_size, me);
602
603 /* Extract the desired flash command set. */
604 ret = hw_find_integer_array_property (me, "cmdset", 0, &ival);
605 if (ret != 1 && ret != 2)
606 hw_abort (me, "\"cmdset\" property takes 1 or 2 entries");
607 cfi_encode_16bit (cfi->query.p_id, ival);
608
609 for (i = 0; i < ARRAY_SIZE (cfi_cmdsets); ++i)
610 if (cfi_cmdsets[i]->id == ival)
611 cfi->cmdset = cfi_cmdsets[i];
612 if (cfi->cmdset == NULL)
613 hw_abort (me, "cmdset %u not supported", ival);
614
615 if (ret == 2)
616 {
617 hw_find_integer_array_property (me, "cmdset", 1, &ival);
618 cfi_encode_16bit (cfi->query.a_id, ival);
619 }
620
621 /* Extract the desired device size. */
622 if (hw_find_property (me, "size"))
623 cfi->dev_size = hw_find_integer_property (me, "size");
624 else
625 cfi->dev_size = attach_size;
626 cfi->query.dev_size = log2 (cfi->dev_size);
627
628 /* Extract the desired flash width. */
629 if (hw_find_property (me, "width"))
630 {
631 cfi->width = hw_find_integer_property (me, "width");
632 if (cfi->width != 8 && cfi->width != 16 && cfi->width != 32)
633 hw_abort (me, "\"width\" must be 8 or 16 or 32, not %u", cfi->width);
634 }
635 else
636 /* Default to 8 bit. */
637 cfi->width = 8;
638 /* Turn 8/16/32 into 1/2/4. */
639 cfi->width /= 8;
640
641 /* Extract optional write buffer size. */
642 if (hw_find_property (me, "write_size"))
643 {
644 ival = hw_find_integer_property (me, "write_size");
645 cfi_encode_16bit (cfi->query.max_buf_write_len, log2 (ival));
646 }
647
648 /* Extract optional erase regions. */
649 if (hw_find_property (me, "erase_regions"))
650 {
651 ret = hw_find_integer_array_property (me, "erase_regions", 0, &ival);
652 if (ret % 2)
653 hw_abort (me, "\"erase_regions\" must be specified in sets of 2");
654
655 cfi->erase_region_info = HW_NALLOC (me, unsigned char, ret / 2);
656 cfi->erase_regions = HW_NALLOC (me, struct cfi_erase_region, ret / 2);
657
658 for (i = 0; i < ret; i += 2)
659 {
660 unsigned blocks, size;
661
662 hw_find_integer_array_property (me, "erase_regions", i, &ival);
663 blocks = ival;
664
665 hw_find_integer_array_property (me, "erase_regions", i + 1, &ival);
666 size = ival;
667
668 cfi_add_erase_region (me, cfi, blocks, size);
669 }
670 }
671
672 /* Extract optional voltages. */
673 if (hw_find_property (me, "voltage"))
674 {
675 unsigned num = ARRAY_SIZE (cfi->query.voltages);
676
677 ret = hw_find_integer_array_property (me, "voltage", 0, &ival);
678 if (ret > num)
679 hw_abort (me, "\"voltage\" may have only %u arguments", num);
680
681 for (i = 0; i < ret; ++i)
682 {
683 hw_find_integer_array_property (me, "voltage", i, &ival);
684 cfi->query.voltages[i] = ival;
685 }
686 }
687
688 /* Extract optional timeouts. */
689 if (hw_find_property (me, "timeout"))
690 {
691 unsigned num = ARRAY_SIZE (cfi->query.timeouts);
692
693 ret = hw_find_integer_array_property (me, "timeout", 0, &ival);
694 if (ret > num)
695 hw_abort (me, "\"timeout\" may have only %u arguments", num);
696
697 for (i = 0; i < ret; ++i)
698 {
699 hw_find_integer_array_property (me, "timeout", i, &ival);
700 cfi->query.timeouts[i] = ival;
701 }
702 }
703
704 /* Extract optional file. */
705 fd = -1;
706 fd_writable = false;
707 if (hw_find_property (me, "file"))
708 {
709 const char *file;
710
711 ret = hw_find_string_array_property (me, "file", 0, &file);
712 if (ret > 2)
713 hw_abort (me, "\"file\" may take only one argument");
714 if (ret == 2)
715 {
716 const char *writable;
717
718 hw_find_string_array_property (me, "file", 1, &writable);
719 fd_writable = !strcmp (writable, "rw");
720 }
721
722 fd = open (file, fd_writable ? O_RDWR : O_RDONLY);
723 if (fd < 0)
724 hw_abort (me, "unable to read file `%s': %s", file, strerror (errno));
725 }
726
727 /* Figure out where our initial flash data is coming from. */
728 if (fd != -1 && fd_writable)
729 {
a13852d9 730#if defined (HAVE_MMAP) && defined (HAVE_POSIX_FALLOCATE)
66ee2731
MF
731 posix_fallocate (fd, 0, cfi->dev_size);
732
733 cfi->mmap = mmap (NULL, cfi->dev_size,
734 PROT_READ | (fd_writable ? PROT_WRITE : 0),
735 MAP_SHARED, fd, 0);
736
737 if (cfi->mmap == MAP_FAILED)
738 cfi->mmap = NULL;
739 else
740 cfi->data = cfi->mmap;
741#else
742 sim_io_eprintf (hw_system (me),
743 "cfi: sorry, file write support requires mmap()\n");
744#endif
745 }
746 if (!cfi->data)
747 {
748 size_t read_len;
749
750 cfi->data = HW_NALLOC (me, unsigned char, cfi->dev_size);
751
752 if (fd != -1)
753 {
754 /* Use stdio to avoid EINTR issues with read(). */
755 FILE *fp = fdopen (fd, "r");
756
757 if (fp)
758 read_len = fread (cfi->data, 1, cfi->dev_size, fp);
759 else
760 read_len = 0;
761
762 /* Don't need to fclose() with fdopen("r"). */
763 }
764 else
765 read_len = 0;
766
767 memset (cfi->data, 0xff, cfi->dev_size - read_len);
768 }
769
770 close (fd);
771}
772
773/* Once we've been declared in the device tree, this is the main
774 entry point. So allocate state, attach memory addresses, and
775 all that fun stuff. */
776static void
777cfi_finish (struct hw *me)
778{
779 struct cfi *cfi;
780
781 cfi = HW_ZALLOC (me, struct cfi);
782
783 set_hw_data (me, cfi);
784 set_hw_io_read_buffer (me, cfi_io_read_buffer);
785 set_hw_io_write_buffer (me, cfi_io_write_buffer);
786 set_hw_delete (me, cfi_delete_callback);
787
788 attach_cfi_regs (me, cfi);
789
790 /* Initialize the CFI. */
791 cfi->state = CFI_STATE_READ;
792 memcpy (cfi->query.qry, "QRY", 3);
793 cfi->cmdset->setup (me, cfi);
794}
795
796/* Every device is required to declare this. */
797const struct hw_descriptor dv_cfi_descriptor[] =
798{
799 {"cfi", cfi_finish,},
800 {NULL, NULL},
801};
This page took 0.173059 seconds and 4 git commands to generate.