Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
sdext.c
Go to the documentation of this file.
1 /* Xep128: Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Copyright (C)2015-2022 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
3  http://xep128.lgb.hu/
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 /* General SD information:
20  http://elm-chan.org/docs/mmc/mmc_e.html
21  http://www.mikroe.com/downloads/get/1624/microsd_card_spec.pdf
22  http://users.ece.utexas.edu/~valvano/EE345M/SD_Physical_Layer_Spec.pdf
23  Flash IC used (AM29F400BT) on the cartridge:
24  http://www.mouser.com/ds/2/380/spansion%20inc_am29f400b_eol_21505e8-329620.pdf
25 */
26 
27 #include "xemu/emutools.h"
28 #include "xemu/emutools_files.h"
29 #include "xemu/z80.h"
30 #include "sdext.h"
31 #include <unistd.h>
32 #include <errno.h>
33 #include <sys/types.h>
34 #include <fcntl.h>
35 #include <limits.h>
36 
37 
38 #ifndef CONFIG_SDEXT_SUPPORT
39 #warning "SDEXT support is disabled by configuration."
40 #else
41 #define DEBUG_SDEXT
42 
43 #ifdef DEBUG_SDEXT
44 # define SD_DEBUG DEBUG
45 #else
46 # define SD_DEBUG(...)
47 #endif
48 
49 
50 int sdext_enabled = 0;
51 char sdimg_path[PATH_MAX + 1];
52 static int rom_page_ofs = 0;
53 static int is_hs_read;
54 static Uint8 _spi_last_w;
55 static int cs0, cs1;
56 static Uint8 status;
57 static int sd_is_ro;
58 
59 static Uint8 sd_ram_ext[7 * 1024]; // 7K of accessible SRAM
60 static Uint8 sd_rom_ext[SDCARD_ROM_SIZE];
61 
62 static Uint8 cmd[6], cmd_index, _read_b, _write_b, _write_specified;
63 static const Uint8 *ans_p;
64 static int ans_index, ans_size;
65 static int writing;
66 static int delay_answer;
67 static void (*ans_callback)(void);
68 
69 static int sdfd;
70 static Uint8 _buffer[1024];
71 off_t sd_card_size = 0;
72 
73 #define MAX_CARD_SIZE 2147483648UL
74 #define MIN_CARD_SIZE 8388608UL
75 
76 /* ID files:
77  * C0 71 00 00 │ 00 5D 01 32 │ 13 59 80 E3 │ 76 D9 CF FF │ 16 40 00 4F │ 01 50 41 53
78  * 30 31 36 42 │ 41 35 E4 39 │ 06 00 35 03 │ 80 FF 80 00 │ 00 00 00 00 │ 00 00 00 00
79  * 4 bytes: size in sectors: C0 71 00 00
80  * CSD register 00 5D 01 32 │ 13 59 80 E3 │ 76 D9 CF FF │ 16 40 00 4F
81  * CID register 01 50 41 53 | 30 31 36 42 │ 41 35 E4 39 │ 06 00 35 03
82  * OCR register 80 FF 80 00
83  */
84 
85 
86 static const Uint8 _stop_transmission_answer[] = {
87  0, 0, 0, 0, // "stuff byte" and some of it is the R1 answer anyway
88  0xFF // SD card is ready again
89 };
90 #define __CSD_OFS 2
91 #define CSD(a) _read_csd_answer[(__CSD_OFS) + (a)]
92 static Uint8 _read_csd_answer[] = {
93  0xFF, // waiting a bit
94  0xFE, // data token
95  // the CSD itself
96  0x00, 0x5D, 0x01, 0x32, 0x13, 0x59, 0x80, 0xE3, 0x76, 0xD9, 0xCF, 0xFF, 0x16, 0x40, 0x00, 0x4F,
97  0, 0 // CRC bytes
98 };
99 static const Uint8 _read_cid_answer[] = {
100  0xFF, // waiting a bit
101  0xFE, // data token
102  // the CID itself
103  0x01, 0x50, 0x41, 0x53, 0x30, 0x31, 0x36, 0x42, 0x41, 0x35, 0xE4, 0x39, 0x06, 0x00, 0x35, 0x03,
104  0, 0 // CRC bytes
105 };
106 static const Uint8 _read_ocr_answer[] = { // no data token, nor CRC! (technically this is the R3 answer minus the R1 part at the beginning ...)
107  // the OCR itself
108  0x80, 0xFF, 0x80, 0x00
109 };
110 
111 #define ADD_ANS(ans) { ans_p = (ans); ans_index = 0; ans_size = sizeof(ans); }
112 
113 #if 0
114 #include "xemu/../rom/ep128/vhd_compressed.c"
115 static int decompress_vhd ( const Uint8 *p, int fd )
116 {
117  int filelen = 0;
118  for (;;) {
119  Uint32 l = p[0] | (p[1] << 8) | (p[2] << 16) | ((p[3] & 0x7F) << 24);
120  if (!l)
121  break;
122  p += 4;
123  filelen += l;
124  if (p[-1] & 0x80) {
125  // printf("Zero seq len = %d\n", l);
126  if (lseek(fd, filelen, SEEK_SET) != filelen)
127  return 1;
128  } else {
129  // printf("Data len = %d\n", l);
130  while (l) {
131  int r = write(fd, p, l);
132  if (r <= 0)
133  return 1;
134  l -= r;
135  p += r;
136  }
137  }
138  }
139  return 0;
140 }
141 #endif
142 
143 
144 void sdext_clear_ram(void)
145 {
146  memset(sd_ram_ext, 0xFF, sizeof sd_ram_ext);
147 }
148 
149 
150 #if 0
151 static int sdext_detect_rom ( void )
152 {
153  Uint8 *p = memory + 7 * 0x4000;
154  Uint8 *p2 = p + 0x2000 - strlen(sdext_rom_signature);
155  if (memcmp(p, "EXOS_ROM", 8))
156  return 1; // No EXOS_ROM header
157  for (; p < p2; p++ ) {
158  if (!memcmp(p, sdext_rom_signature, strlen(sdext_rom_signature)))
159  return 0; // found our extra ID
160  }
161  return 1; // our ID cannot be found
162 }
163 #endif
164 
165 
166 #if 0
167 static inline off_t _assert_on_csd_size_mismatch ( off_t expected_size, int expected_mult, int expected_blocknr, int expected_blocklen )
168 {
169  int mult = 2 ** (i["C_SIZE_MULT"] + 2)
170  int blocknr = (i["C_SIZE"] + 1) * mult
171  int blocklen = 2 ** i["READ_BL_LEN"]
172  off_t size = (off_t)blocknr * (off_t)blocklen;
173  if (size != expected_size || mult != expected_mult || blocknr != excepted_blocknr || blocklen != expected_blocklen)
174  FATAL("Internal CSD size calculation failure!\nExpected=" PRINTF_LLD " Got=" PRINTF_LLD " (mult=%d blocknr=%d blocklen=%d)",
175  (long long)expected_size, (long long)size,
176  mult, blocknr, blocklen
177  );
178 }
179 #endif
180 
181 
182 
183 static int _size_calc ( off_t size )
184 {
185  int blen_i;
186  for (blen_i = 9; blen_i < 12; blen_i++) {
187  int mult_i;
188  int blen = 1 << blen_i;
189  for (mult_i = 0; mult_i < 8; mult_i++) {
190  int mult = 1 << (mult_i + 2);
191  int res = size / blen;
192  if (!(size % blen) && !(res % mult)) {
193  res = (res / mult) - 1;
194  if (res < 4096 && res > 0) {
195  //printf("MAY HIT with blen=%d[%d],mult=%d[%d],result=%d\n",
196  // blen, blen_i, mult, mult_i, res
197  //);
198  CSD( 5) = (CSD( 5) & 0xF0) | blen_i;
199  CSD( 6) = (CSD( 6) & 0xFC) | (res >> 10);
200  CSD( 7) = (res >> 2) & 0xFF;
201  CSD( 8) = (CSD( 8) & 0x3F) | ((res & 3) << 6);
202  CSD( 9) = (CSD( 9) & 0xFC) | (mult_i >> 1);
203  CSD(10) = (CSD(10) & 0x7F) | ((mult_i & 1) << 7);
204  // CHECKING the result follows now!
205  //_assert_on_csd_size_mismatch(size, mult, res, blen);
206  return 0;
207  }
208  }
209  }
210  }
211  return 1;
212 }
213 
214 
215 
216 static int sdext_check_and_set_size ( void )
217 {
218  off_t new_size;
219  int is_vhd;
220  if (sd_card_size < MIN_CARD_SIZE) {
221  ERROR_WINDOW(
222  "SD card image file \"%s\" is too small, minimal size is " PRINTF_LLD " Mbytes, but this one is " PRINTF_LLD " bytes long (about " PRINTF_LLD " Mbytes). SD access has been disabled!",
223  sdimg_path, (long long)(MIN_CARD_SIZE >> 20), (long long)sd_card_size, (long long)(sd_card_size >> 20)
224  );
225  return 1;
226  }
227  /* check for VHD footer (not the real part of the image, +512 bytes structure at the end) */
228  is_vhd = -1;
229  if (lseek(sdfd, sd_card_size - 512, SEEK_SET) == sd_card_size - 512) {
230  if (read(sdfd, _buffer, 512) == 512) {
231  Uint8 *p = NULL;
232  if (!memcmp(_buffer + 1, "conectix", 8)) {
233  sd_card_size++; // old, buggy Microsoft tool maybe, 511 bytes footer instead of 512. Treating size as the normalized one
234  p = _buffer + 1;
235  DEBUG("SDEXT: warning, old buggy Microsoft VHD file, activating workaround!" NL);
236  } else if (!memcmp(_buffer, "conectix", 8))
237  p = _buffer;
238  if (p) {
239  if (p[60] || p[61] || p[62] || p[63] != 2) {
240  ERROR_WINDOW("SD card image \"%s\" is an unsupported VHD file (not fixed, maybe dynamic?)", sdimg_path);
241  return 1;
242  }
243  is_vhd = 1;
244  } else
245  is_vhd = 0;
246  }
247  }
248  if (is_vhd < 0) {
249  ERROR_WINDOW("SD card image \"%s\" I/O error while detecting type: %s.\nSD access has been disabled!", sdimg_path, strerror(errno));
250  return 1;
251  }
252  if (is_vhd) {
253  DEBUG("SDEXT: VHD file detected as card image." NL);
254  sd_card_size -= 512;
255  } else
256  DEBUG("SDEXT: VHD file is not detected." NL);
257  if (sd_card_size > MAX_CARD_SIZE) { // do this check here, as VHD footer could overflow on 2G boundary at the beginning what we have support for in Xep128
258  ERROR_WINDOW(
259  "SD card image file \"%s\" is too large, maximal allowed size is " PRINTF_LLD " Mbytes, but this one is " PRINTF_LLD " bytes long (about " PRINTF_LLD " Mbytes). "
260  "SD access has been disabled!",
261  sdimg_path, (long long)(MAX_CARD_SIZE >> 20), (long long)sd_card_size, (long long)(sd_card_size >> 20)
262  );
263  return 1;
264  }
265  if ((sd_card_size & 511)) { // do this check here, as buggy MS tool can create 511 "tail" as footer
266  ERROR_WINDOW("SD card image file \"%s\" size is not multiple of 512 bytes! SD access has been disabled!", sdimg_path);
267  return 1;
268  }
269  /* probing size, optionally extending on request */
270  new_size = sd_card_size;
271  while (_size_calc(new_size))
272  new_size += 512;
273  if (new_size == sd_card_size)
274  return 0;
275  if (is_vhd)
276  WARNING_WINDOW("SD-card image \"%s\" is promoted for extension but it seems to be a VHD file.\nIf you allow extension it WON'T BE USED AS VHD ANY MORE BY OTHER SOFTWARE!", sdimg_path);
277  INFO_WINDOW("SD-card image file \"%s\" is about to be extended with %d bytes (the next valid SD-card size), new size is: " PRINTF_LLD, sdimg_path, (int)(new_size - sd_card_size), (long long)new_size);
278  if (!QUESTION_WINDOW("Not allowed|Allowed (DANGEROUS)", "Do you allow this extension? NOTE: it's a test feature, do not allow it, if you are unsure!")) {
279  INFO_WINDOW("You didn't allow the extension. You can continue, but some EP128 software may fail (ie: fdisk)!");
280  return 0;
281  }
282  if (lseek(sdfd, new_size - 1, SEEK_SET) != new_size - 1) {
283  ERROR_WINDOW("SD card image file \"%s\" cannot be extended (seek error: %s).\nYou can continue but some EP128 software may fail (ie: fdisk)!", sdimg_path, strerror(errno));
284  return 0;
285  }
286  if (write(sdfd, sd_rom_ext, 1) != 1) { // sd_rom_ext is just used to write some *RANDOM* byte, the content is not so important here :-P It will create a file "with hole" btw.
287  ERROR_WINDOW("SD card image file \"%s\" cannot be extended (write error: %s).\nYou can continue but some EP128 software may fail (ie: fdisk)!", sdimg_path, strerror(errno));
288  return 0;
289  }
290  sd_card_size = new_size;
291  INFO_WINDOW("Great, image file is successfully extended to valid SD-card size! :-)\nNext time you can enjoy the lack of these info message, as you have valid file size now :-)");
292  return 0;
293 }
294 
295 
296 
297 /* SDEXT emulation currently excepts the cartridge area (segments 4-7) to be filled
298  * with the FLASH ROM content. Even segment 7, which will be copied to the second 64K "hidden"
299  * and pagable flash area of the SD cartridge. Currently, there is no support for the full
300  * sized SDEXT flash image */
301 void sdext_init ( const char *sdimg_filename, const char *sdrom_filename )
302 {
303  sdext_enabled = 0;
304  // try to load our ROM ...
305  if (xemu_load_file(sdrom_filename, sd_rom_ext, SDCARD_ROM_SIZE, SDCARD_ROM_SIZE, "Cannot load SD-card cartridge ROM, SD emulation has been disabled!") < 0) {
306  SD_DEBUG("SDEXT: init: REFUSE: no SD-card cartridge ROM code found in loaded ROM set." NL);
307  goto error;
308  }
309  SD_DEBUG("SDEXT: init: cool, SD-card cartridge ROM code seems to be found in loaded ROM set, enabling SD card hardware emulation ..." NL);
310  // try to open SD card image. If not found, and it's the DEFAULT config option we provide user to install an empty one (and later to download a populated one)
311 //try_to_open_image:
312  //sdf = open_emu_file(emucfg_get_str("sdimg"), "rb", sdimg_path); // open in read-only mode, to get the path
313  sd_is_ro = O_RDONLY;
314  sdfd = xemu_open_file(sdimg_filename, O_RDWR, &sd_is_ro, sdimg_path);
315  sd_is_ro = (sd_is_ro != XEMU_OPEN_FILE_FIRST_MODE_USED);
316  if (sdfd < 0) {
317  WARNING_WINDOW("SD card image file \"%s\" cannot be open: %s. You can use the emulator but SD card access won't work!", sdimg_path, strerror(errno));
318  goto error;
319  } else {
320  if (sd_is_ro)
321  DEBUGPRINT("SDEXT: SD image cannot be open in read-write mode, using read-only access (fd=%d)." NL, sdfd);
322  else
323  DEBUGPRINT("SDEXT: SD image file is open in read/write mode, good (fd=%d)" NL, sdfd);
324  }
325  // size, etc
326  sd_card_size = lseek(sdfd, 0, SEEK_END);
327  if (sdext_check_and_set_size()) {
328  close(sdfd);
329  goto error;
330  } else
331  DEBUG("SDEXT: SD card size is: " PRINTF_LLD " bytes" NL, (long long)sd_card_size);
332  sdext_clear_ram();
333  sdext_enabled = 1; // turn emulation on
334  rom_page_ofs = 0;
335  is_hs_read = 0;
336  cmd_index = 0;
337  ans_size = 0;
338  delay_answer = 0;
339  ans_index = 0;
340  ans_callback = NULL;
341  status = 0;
342  _read_b = 0;
343  _write_b = 0xFF;
344  _spi_last_w = 0xFF;
345  writing = -2;
346  SD_DEBUG("SDEXT: init end" NL);
347  return;
348 error:
349  *sdimg_path = 0;
350  sdfd = -1;
351  sdext_enabled = 0;
352 }
353 
354 
355 static int blocks;
356 
357 
358 // FIXME: error handling of read() !!!!
359 // FIXME: check excess of card size (during multiple block read) !!!!
360 static void _block_read ( void )
361 {
362  int ret;
363  z80ex_w_states(40); // TODO: fake some wait states here, actully this is the WRONG method, as not the Z80 should wait but the SD card's answer ...
364  blocks++;
365  _buffer[0] = 0xFF; // wait a bit
366  _buffer[1] = 0xFE; // data token
367  //ret = fread(_buffer + 2, 1, 512, sdf);
368  ret = read(sdfd, _buffer + 2, 512);
369  SD_DEBUG("SDEXT: REGIO: fread retval = %d" NL, ret);
370  (void)ret;
371  _buffer[512 + 2] = 0; // CRC
372  _buffer[512 + 3] = 0; // CRC
373  ans_p = _buffer;
374  ans_index = 0;
375  ans_size = 512 + 4;
376 }
377 
378 
379 
380 /* SPI is a read/write in once stuff. We have only a single function ...
381  * _write_b is the data value to put on MOSI
382  * _read_b is the data read from MISO without spending _ANY_ SPI time to do shifting!
383  * This is not a real thing, but easier to code this way.
384  * The implementation of the real behaviour is up to the caller of this function.
385  */
386 static void _spi_shifting_with_sd_card ( void )
387 {
388  if (!cs0) { // Currently, we only emulate one SD card, and it must be selected for any answer
389  _read_b = 0xFF;
390  return;
391  }
392  /* begin of write support */
393  if (delay_answer) {
394  delay_answer = 0;
395  return;
396  }
397  if (writing > -2) {
398  _read_b = 0xFF;
399  SD_DEBUG("SDEXT: write byte #%d as %02Xh for CMD %d" NL, writing, _write_b, cmd[0]);
400  if (writing == -1) {
401  if (_write_b == 0xFD) { // stop token
402  SD_DEBUG("SDEXT: Stop token got" NL);
403  _read_b = 0; // wait a tiny time ...
404  writing = -2; // ... but otherwise, end of write session
405  return;
406  }
407  if (_write_b != 0xFE && _write_b != 0xFC) {
408  SD_DEBUG("SDEXT: Waiting for token ..." NL);
409  return;
410  }
411  SD_DEBUG("SDEXT: token found %02Xh" NL, _write_b);
412  writing = 0;
413  return;
414  }
415  _buffer[writing++] = _write_b; // store written byte
416  if (writing == 512 + 2) { // if one block (+ 2byte CRC) is written by host ...
417  off_t ret, _offset = (cmd[1] << 24) | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
418  _offset += 512UL * blocks;
419  blocks++;
420  if (_offset > sd_card_size - 512UL) {
421  ret = 13;
422  SD_DEBUG("SDEXT: access beyond the card size!" NL);
423  } else {
424  ret = (lseek(sdfd, _offset, SEEK_SET) == _offset) ? 5 : 13;
425  if (ret != 5)
426  SD_DEBUG("SDEXT: seek error: %s" NL, strerror(errno));
427  else {
428  ret = (write(sdfd, _buffer, 512) == 512) ? 5 : 13;
429  if (ret != 5)
430  SD_DEBUG("SDEXT: write error: %s" NL, strerror(errno));
431  }
432  }
433  // space for the actual block write ...
434  if (cmd[0] == 24 || ret != 5) {
435  SD_DEBUG("SDEXT: cmd-%d end blocks=%d" NL, cmd[0], blocks);
436  _read_b = ret; // data accepted?
437  writing = -2; // turn off write mode
438  delay_answer = 1;
439  } else {
440  SD_DEBUG("SDEXT: cmd-25 end blocks=%d" NL, blocks);
441  _read_b = ret; // data accepted?
442  writing = -1; // write mode back to the token waiting phase
443  delay_answer = 1;
444  }
445  }
446  return;
447  }
448  /* end of write support */
449  if (cmd_index == 0 && (_write_b & 0xC0) != 0x40) {
450  if (ans_index < ans_size) {
451  SD_DEBUG("SDEXT: REGIO: streaming answer byte %d of %d-1 value %02X" NL, ans_index, ans_size, ans_p[ans_index]);
452  _read_b = ans_p[ans_index++];
453  } else {
454  if (ans_callback)
455  ans_callback();
456  else {
457  //_read_b = 0xFF;
458  ans_index = 0;
459  ans_size = 0;
460  SD_DEBUG("SDEXT: REGIO: dummy answer 0xFF" NL);
461  }
462  _read_b = 0xFF;
463  }
464  return;
465  }
466  if (cmd_index < 6) {
467  cmd[cmd_index++] = _write_b;
468  _read_b = 0xFF;
469  return;
470  }
471  SD_DEBUG("SDEXT: REGIO: command (CMD%d) received: %02X %02X %02X %02X %02X %02X" NL, cmd[0] & 63, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5]);
472  cmd[0] &= 63;
473  cmd_index = 0;
474  ans_callback = NULL;
475  switch (cmd[0]) {
476  case 0: // CMD 0
477  _read_b = 1; // IDLE state R1 answer
478  break;
479  case 1: // CMD 1 - init
480  _read_b = 0; // non-IDLE now (?) R1 answer
481  break;
482  case 16: // CMD16 - set blocklen (?!) : we only handles that as dummy command oh-oh ...
483  _read_b = 0; // R1 answer
484  break;
485  case 9: // CMD9: read CSD register
486  SD_DEBUG("SDEXT: REGIO: command is read CSD register" NL);
487  ADD_ANS(_read_csd_answer);
488  _read_b = 0; // R1
489  break;
490  case 10: // CMD10: read CID register
491  ADD_ANS(_read_cid_answer);
492  _read_b = 0; // R1
493  break;
494  case 58: // CMD58: read OCR
495  ADD_ANS(_read_ocr_answer);
496  _read_b = 0; // R1 (R3 is sent as data in the emulation without the data token)
497  break;
498  case 12: // CMD12: stop transmission (reading multiple)
499  ADD_ANS(_stop_transmission_answer);
500  _read_b = 0;
501  // actually we don't do too much, as on receiving a new command callback will be deleted before this switch-case block
502  SD_DEBUG("SDEXT: REGIO: block counter before CMD12: %d" NL, blocks);
503  blocks = 0;
504  break;
505  case 17: // CMD17: read a single block, babe
506  case 18: // CMD18: read multiple blocks
507  blocks = 0;
508  if (sdfd < 0)
509  _read_b = 32; // address error, if no SD card image ... [this is bad TODO, better error handling]
510  else {
511  off_t ret, _offset = (cmd[1] << 24) | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
512  SD_DEBUG("SDEXT: REGIO: seek to " PRINTF_LLD " in the image file." NL, (long long)_offset);
513  z80ex_w_states(100); // TODO: fake some wait states here, actully this is the WRONG method, as not the Z80 should wait but the SD card's answer ...
514  if (_offset > sd_card_size - 512UL) {
515  _read_b = 32; // address error, TODO: what is the correct answer here?
516  SD_DEBUG("SDEXT: access beyond the card size!" NL);
517  } else {
518  //fseek(sdf, _offset, SEEK_SET);
519  ret = lseek(sdfd, _offset, SEEK_SET);
520  if (ret != _offset) {
521  _read_b = 32; // address error, TODO: what is the correct answer here?
522  SD_DEBUG("SDEXT: seek error to " PRINTF_LLD " (got: " PRINTF_LLD ")" NL, (long long)_offset, (long long)ret);
523  } else {
524  _block_read();
525  if (cmd[0] == 18)
526  ans_callback = _block_read; // in case of CMD18, continue multiple sectors, register callback for that!
527  _read_b = 0; // R1
528  }
529  }
530  }
531  break;
532  case 24: // CMD24: write block
533  case 25: // CMD25: write multiple blocks
534  blocks = 0;
535  writing = -1; // signal writing (-2 for not-write mode), also the write position into the buffer
536  _read_b = 0; // R1 answer, OK
537  break;
538  default: // unimplemented command, heh!
539  SD_DEBUG("SDEXT: REGIO: unimplemented command %d = %02Xh" NL, cmd[0], cmd[0]);
540  _read_b = 4; // illegal command :-/
541  break;
542  }
543 }
544 
545 
546 
547 
548 Uint8 sdext_read_cart ( int addr )
549 {
550  if (!sdext_enabled)
551  return 0xFF;
552  SD_DEBUG("SDEXT: read cart @ %04X [pc=%04X]" NL, addr, Z80_PC);
553 #if 0
554  if (addr < 0xC000) {
555  Uint8 byte = flash_rd_bus_op(0, addr);
556  SD_DEBUG("SDEXT: reading base ROM, ROM offset = %04X, result = %02X" NL, addr, byte);
557  return byte;
558  }
559 #endif
560  if (addr < 0x2000) {
561  return sd_rom_ext[rom_page_ofs + addr];
562  }
563  if (addr < 0x3C00) {
564  addr -= 0x2000;
565  SD_DEBUG("SDEXT: reading RAM at offset %04X, result = %02X" NL, addr, sd_ram_ext[addr]);
566  return sd_ram_ext[addr];
567  }
568  if (is_hs_read) {
569  // in HS-read (high speed read) mode, all the 0x3C00-0x3FFF acts as data _read_ register (but not for _write_!!!)
570  // also, there is a fundamental difference compared to "normal" read: each reads triggers SPI shifting in HS mode, but not in regular mode, there only write does that!
571  Uint8 old = _read_b; // HS-read initiates an SPI shift, but the result (AFAIK) is the previous state, as shifting needs time!
572  _spi_shifting_with_sd_card();
573  SD_DEBUG("SDEXT: REGIO: R: DATA: SPI data register HIGH SPEED read %02X [future byte %02X] [shited out was: %02X]" NL, old, _read_b, _write_b);
574  return old;
575  } else
576  switch (addr & 3) {
577  case 0:
578  // regular read (not HS) only gives the last shifted-in data, that's all!
579  SD_DEBUG("SDEXT: REGIO: R: DATA: SPI data register regular read %02X" NL, _read_b);
580  return _read_b;
581  case 1: // status reg: bit7=wp1, bit6=insert, bit5=changed (insert/changed=1: some of the cards not inserted or changed)
582  SD_DEBUG("SDEXT: REGIO: R: status" NL);
583  return status;
584  //return 0xFF - 32 + changed;
585  //return changed | 64;
586  case 2: // ROM pager [hmm not readble?!]
587  SD_DEBUG("SDEXT: REGIO: R: rom pager" NL);
588  return 0xFF;
589  return rom_page_ofs >> 8;
590  case 3: // HS read config is not readable?!]
591  SD_DEBUG("SDEXT: REGIO: R: HS config" NL);
592  return 0xFF;
593  return is_hs_read;
594  default:
595  FATAL("SDEXT: FATAL, unhandled (RD) case");
596  break;
597  }
598  FATAL("SDEXT: FATAL, control should not get here");
599  return 0; // make GCC happy :)
600 }
601 
602 
603 void sdext_write_cart ( int addr, Uint8 data )
604 {
605  if (!sdext_enabled)
606  return;
607  //SD_DEBUG("SDEXT: write cart @ %04X with %02X [CPU: seg=%02X, pc=%04X]" NL, addr, data, ports[0xB0 | (Z80_PC >> 14)], Z80_PC);
608  if (addr < 0x2000) { // pageable ROM (8K), currently we don't support re-flashing, etc
609  return;
610  }
611  if (addr < 0x3C00) { // SDEXT's RAM (7K), writable
612  addr -= 0x2000;
613  SD_DEBUG("SDEXT: writing RAM at offset %04X" NL, addr);
614  sd_ram_ext[addr] = data;
615  return;
616  }
617  // rest 1K is the (memory mapped) I/O area
618  switch (addr & 3) {
619  case 0: // data register
620  SD_DEBUG("SDEXT: REGIO: W: DATA: SPI data register to %02X" NL, data);
621  if (!is_hs_read) _write_b = data;
622  _write_specified = data;
623  _spi_shifting_with_sd_card();
624  break;
625  case 1: // control register (bit7=CS0, bit6=CS1, bit5=clear change card signal
626  if (data & 32) // clear change signal
627  status &= 255 - 32;
628  cs0 = data & 128;
629  cs1 = data & 64;
630  SD_DEBUG("SDEXT: REGIO: W: control register to %02X CS0=%d CS1=%d" NL, data, cs0, cs1);
631  break;
632  case 2: // ROM pager register
633  rom_page_ofs = (data & 0xE0) << 8; // only high 3 bits count
634  SD_DEBUG("SDEXT: REGIO: W: paging ROM to %02X, eg %04X offset" NL, data, rom_page_ofs);
635  break;
636  case 3: // HS (high speed) read mode to set: bit7=1
637  is_hs_read = data & 128;
638  _write_b = is_hs_read ? 0xFF : _write_specified;
639  SD_DEBUG("SDEXT: REGIO: W: HS read mode is %s" NL, is_hs_read ? "set" : "reset");
640  break;
641  default:
642  FATAL("SDEXT: FATAL, unhandled (WR) case");
643  break;
644  }
645 }
646 
647 #endif
sdext.h
z80ex_w_states
void z80ex_w_states(unsigned w_states)
Definition: z80ex.c:307
emutools.h
xemu_open_file
int xemu_open_file(const char *filename, int mode, int *mode2, char *filepath_back)
Definition: emutools_files.c:469
WARNING_WINDOW
#define WARNING_WINDOW(...)
Definition: xep128.h:115
INFO_WINDOW
#define INFO_WINDOW(...)
Definition: xep128.h:114
addr
int addr
Definition: dma65.c:81
m65-memcontent-generator.data
data
Definition: m65-memcontent-generator.py:119
Uint32
uint32_t Uint32
Definition: fat32.c:49
Uint8
uint8_t Uint8
Definition: fat32.c:51
emutools_files.h
z80.h
DEBUGPRINT
#define DEBUGPRINT(...)
Definition: emutools_basicdefs.h:171
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
NL
#define NL
Definition: fat32.c:37
compress_sd_image.r
def r
Definition: compress_sd_image.py:76
memory
Uint8 memory[0x100000]
Definition: commodore_65.c:43
xemu_load_file
int xemu_load_file(const char *filename, void *store_to, int min_size, int max_size, const char *cry)
Definition: emutools_files.c:674
PRINTF_LLD
#define PRINTF_LLD
Definition: emutools_basicdefs.h:145
blocks
Uint32 blocks
Definition: fat32.c:73
size
int size
Definition: inject.c:37
Z80_PC
#define Z80_PC
Definition: z80ex.h:121
status
enum @26::@29 status
QUESTION_WINDOW
#define QUESTION_WINDOW(items, msg)
Definition: xep128.h:124
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
FATAL
#define FATAL(...)
Definition: xep128.h:117
XEMU_OPEN_FILE_FIRST_MODE_USED
#define XEMU_OPEN_FILE_FIRST_MODE_USED
Definition: emutools_files.h:45
sdimg_path
char sdimg_path[PATH_MAX+1]