diff options
author | 2021-05-09 19:35:31 -0400 | |
---|---|---|
committer | 2021-05-09 19:35:31 -0400 | |
commit | 488e60b3ab36f2914a2ee206bb10b03933379987 (patch) | |
tree | e2e4438fb52a3af49594ceda0458e8032cdcb01d | |
parent | 2077c7dca05c4ccf01e0535f72518fb0aff206b5 (diff) |
ch376 updates [R. Belmont]
- Ignore non-8.3 compliant filenames when generating the directory since CH376 is super-tied to FAT12 semantics
- Implement CHECK_EXIST command for BBC Micro
- Implement undocumented command 0x16, also for BBC Micro
- Fix status return from SET_USB_MODE
-rw-r--r-- | src/devices/machine/ch376.cpp | 79 |
1 files changed, 55 insertions, 24 deletions
diff --git a/src/devices/machine/ch376.cpp b/src/devices/machine/ch376.cpp index a59bb3787ce..a22005ad9c1 100644 --- a/src/devices/machine/ch376.cpp +++ b/src/devices/machine/ch376.cpp @@ -2,24 +2,25 @@ // copyright-holders:R. Belmont /*************************************************************************** - ch376.h + ch376.cpp - "File manage and control chip CH376" - https://www.mpja.com/download/ch376ds1.pdf + "File manage and control chip CH376" + https://www.mpja.com/download/ch376ds1.pdf + https://github.com/djuseeq/Ch376msc/blob/master/src/CommDef.h - This is a module intended to offload USB and USB mass storage - I/O from a small microcontroller or microprocessor. + This is a module intended to offload USB and USB mass storage + I/O from a small microcontroller or microprocessor. - It has 3 host interfaces: - 1) A regular 8-bit bus with 8 data lines, an address line, - chip select, read enable, and write enable lines - 2) An SPI bus interface (SCS, SCK, MOSI, MISO lines) - 3) An asynchronous serial interface (TxD and RxD lines) + It has 3 host interfaces: + 1) A regular 8-bit bus with 8 data lines, an address line, + chip select, read enable, and write enable lines + 2) An SPI bus interface (SCS, SCK, MOSI, MISO lines) + 3) An asynchronous serial interface (TxD and RxD lines) - And 2 guest interfaces: USB 2.0 and a second 4-wire SPI bus for SD/MMC/TF cards. + And 2 guest interfaces: USB 2.0 and a second 4-wire SPI bus for SD/MMC/TF cards. - The module can give high level directory/open/close/read/write access to - files on a FAT12, FAT16, or FAT32 filesystem. + The module can give high level directory/open/close/read/write access to + files on a FAT12, FAT16, or FAT32 filesystem. ***************************************************************************/ @@ -44,7 +45,11 @@ static constexpr u8 STATUS_USB_INT_DISK_WRITE = 0x1e; static constexpr u8 STATUS_USB_INT_DISK_ERR = 0x1f; static constexpr u8 STATUS_ERR_MISS_FILE = 0x42; +// despite the name, this isn't a command +static constexpr u8 CMD_RET_SUCCESS = 0x51; + static constexpr u8 CMD_GET_IC_VER = 0x01; +static constexpr u8 CMD_CHECK_EXIST = 0x06; static constexpr u8 CMD_GET_FILE_SIZE = 0x0c; static constexpr u8 CMD_SET_USB_MODE = 0x15; static constexpr u8 CMD_GET_STATUS = 0x22; @@ -144,8 +149,18 @@ void ch376_device::write(offs_t offset, u8 data) m_last_command = data; switch (data) { + case 0x16: // not a documented valid command, but apparently used by the BBC Micro software + m_dataBuffer[0] = m_int_status = STATUS_USB_INT_CONNECT; + m_dataPtr = 0; + m_dataLen = 1; + break; + + case CMD_CHECK_EXIST: + m_state = STATE_CHECK_EXIST; + break; + case CMD_GET_IC_VER: - m_dataBuffer[0] = 0x41; // + m_dataBuffer[0] = 0x41; m_dataPtr = 0; m_dataLen = 1; break; @@ -187,13 +202,13 @@ void ch376_device::write(offs_t offset, u8 data) case CMD_FILE_OPEN: /* - CH376 allows paths with a leading / or \ to indicate the root of the SD card. - Directories are chained by an unusual method: start with the root dir (leading path separator), - then open each subdirectory without a leading path separator, and finally open the file without - a leading path separator. + CH376 allows paths with a leading / or \ to indicate the root of the SD card. + Directories are chained by an unusual method: start with the root dir (leading path separator), + then open each subdirectory without a leading path separator, and finally open the file without + a leading path separator. - The BOOTI card ignores directories entirely, so the implmentation here is not tested with that - scenario but it should work. + The BOOTI card ignores directories entirely, so the implmentation here is not tested with that + scenario but it should work. */ if (m_file_name[strlen(m_file_name) - 1] == '*') { @@ -258,7 +273,7 @@ void ch376_device::write(offs_t offset, u8 data) { m_int_status = STATUS_USB_INT_DISK_READ; } - else // end of directory + else // end of directory { m_int_status = STATUS_ERR_MISS_FILE; } @@ -327,8 +342,17 @@ void ch376_device::write(offs_t offset, u8 data) { switch (m_state) { + case STATE_CHECK_EXIST: + m_data = (data ^ 0xff); + m_state = STATE_IDLE; + break; + case STATE_USB_MODE_SET: m_state = STATE_IDLE; + if ((data == 0x6) || (data == 0x7)) + { + m_data = CMD_RET_SUCCESS; + } break; case STATE_SET_FILE_NAME: @@ -426,7 +450,7 @@ bool ch376_device::generateNextDirEntry() if (ourEntry->type == osd::directory::entry::entry_type::DIR) { strncpy(reinterpret_cast<char *>(&m_dataBuffer[1]), ourEntry->name, 8); - m_dataBuffer[0xc] = 0x10; // directory type + m_dataBuffer[0xc] = 0x10; // directory type } else if (ourEntry->type == osd::directory::entry::entry_type::FILE) { @@ -440,6 +464,13 @@ bool ch376_device::generateNextDirEntry() } } + // is this an 8.3 filename? CH376 can only really cope with 8.3, so + // skip this entry and recurse to get the next one. + if (dotIdx > 8) + { + return generateNextDirEntry(); + } + int baseLen = std::min(8, dotIdx); for (int idx = 0; idx < baseLen; idx++) { @@ -465,7 +496,7 @@ bool ch376_device::generateNextDirEntry() } } - m_dataBuffer[0xc] = 0; // no attributes + m_dataBuffer[0xc] = 0; // no attributes if (ourEntry->size >= u64(0x100000000)) { @@ -482,7 +513,7 @@ bool ch376_device::generateNextDirEntry() m_dataBuffer[0x20] = ((ourEntry->size >> 24) & 0xff); } } - else // not a file or directory, recurse and hope the next one's better + else // not a file or directory, recurse and hope the next one's better { return generateNextDirEntry(); } |