MBR/partition detection, SDSC/SDHC/SDXC auto-addressing, LBA range guard, BPB/FAT32 validation, FAT mirroring, free-cluster search with FSInfo hint, LFN support, RTC-based real date/time stamping, and multi-cluster streaming read/write.
81 lines
5.3 KiB
Markdown
81 lines
5.3 KiB
Markdown
# zc_sd_driver
|
||
|
||
Открытый SD/FAT32-драйвер для ZiFi, замена закрытого `WDFCVBI2.COD`.
|
||
Реализует ту же CORE-таблицу (`CORE equ #2002` в `zifi.asm`), что и
|
||
оригинальный драйвер, но с открытыми исходниками.
|
||
|
||
## Файлы
|
||
|
||
- `zc_sd_driver.asm` — резидентная часть: таблица переходов CORE,
|
||
di/ei-обёртки над каждой точкой входа, распаковщик тела.
|
||
- `zc_sd_driver_body.asm` — основная логика: SPI/SD-протокол, DMA,
|
||
разбор FAT32 (BPB, цепочки кластеров, FAT), поиск по имени с LFN,
|
||
создание/удаление файлов и каталогов. Хранится в сжатом виде и
|
||
распаковывается в резидентную часть во время выполнения `DOS_SWP`.
|
||
- `body_syms.inc` — адреса функций/переменных тела, сгенерированные
|
||
из символьной таблицы сборки `zc_sd_driver_body.asm`, подключаются
|
||
в `zc_sd_driver.asm` как константы.
|
||
|
||
## Реализованные функции CORE
|
||
|
||
`DEV_INI`, `HDD`, `LOAD512`, `SAVE512`, `DOS_SWP`, `MKFILE`, `MKDIR`,
|
||
`DELFL`, `RENAME`, `FENTRY`, `LOADNON`, `NXTETY`, `SETDIR`, `SETROOT`,
|
||
`SEEK0`. Остальные точки входа таблицы — заглушки (не используются
|
||
ZiFi).
|
||
|
||
## Что реализовано сверх голого CORE ABI
|
||
|
||
- **MBR/раздел**: автоматически определяет, есть ли на карте
|
||
партиция (тип `0x0B`/`0x0C`), или BPB лежит прямо в LBA0; смещение
|
||
партиции (`ADDTOP`) прибавляется ко всем последующим LBA.
|
||
- **SDSC/SDHC/SDXC**: сама определяет байтовую или блочную адресацию
|
||
по биту CCS из CMD8/ACMD41/CMD58, а не считает её заранее известной.
|
||
- **Защита от выхода за границу LBA**: перед любым чтением сверяет
|
||
номер сектора с реальным размером тома (посчитанным из BPB) —
|
||
ошибка в арифметике не уйдёт в CMD17/25 как заведомо неверный адрес.
|
||
- **Проверка BPB/FAT32**: сигнатура `55 AA`, `BytesPerSector==512`,
|
||
`FATSz16==0`, `RootEntryCount==0`, `SectorsPerCluster` — степень
|
||
двойки, прежде чем доверять остальным полям.
|
||
- **Зеркалирование FAT**: запись FAT-записи дублируется во все копии
|
||
(`NumFATs`), не только в первую.
|
||
- **Поиск свободного кластера**: сессионный кэш "куда искать дальше"
|
||
плюс чтение/запись `FSInfo`-подсказки (`FSI_Nxt_Free`) — не
|
||
пересканирует FAT с кластера 2 при каждой аллокации на разделах с
|
||
большим количеством уже занятых кластеров.
|
||
- **Длинные имена (LFN)**: генерация уникального короткого имени 8.3
|
||
с суффиксом `~N` при коллизии, полноценные LFN-записи для
|
||
MKFILE/MKDIR.
|
||
- **Дата/время создания**: читает реальные RTC (DS1685-совместимые,
|
||
порты `#EFF7`/`#DFF7`/`#BFF7`) и проставляет их в создаваемые
|
||
записи каталога вместо фиксированной заглушки.
|
||
- **Многокластерные файлы/каталоги**: потоковое чтение и запись
|
||
(`stream_open`/`stream_read_sector`/`stream_write_sector`) следует
|
||
цепочке FAT и доращивает её по мере необходимости — не ограничено
|
||
одним кластером.
|
||
|
||
## Адресация
|
||
|
||
Драйвер загружается в физическую страницу `#0F`, отображается в CPU
|
||
слот 0 (`#0000-#3FFF`). `CORE` (`#2002`) — фиксированный адрес внутри
|
||
этого слота. Резидентная часть собирается с `ORG #2000`; тело
|
||
распаковывается в адреса `#0000..body_end` той же страницы —
|
||
`body_end` обязан оставаться в пределах `#2002` (граница проверяется
|
||
на этапе сборки).
|
||
|
||
`LOAD512`/`SAVE512` используют прямой DMA между SD-картой и указанной
|
||
вызывающим физической страницей/смещением, не затрагивая пейджинг
|
||
CPU.
|
||
|
||
## Сборка
|
||
|
||
```
|
||
cd _sd
|
||
sjasmplus.exe zc_sd_driver_body.asm --sym=body_syms_new.txt
|
||
# упаковать zc_sd_driver_body.bin -> zc_sd_driver_body.pb (PackBits)
|
||
# обновить body_syms.inc из body_syms_new.txt (без DATA/CONF)
|
||
sjasmplus.exe zc_sd_driver.asm
|
||
```
|
||
|
||
Результат (`zc_sd_driver.bin`) копируется в `_spg/` и подключается
|
||
через `_spg/spgbld.ini` (`Block = #e000, #0f, zc_sd_driver.bin`).
|