6.3 KiB
zc_sd_driver
Открытый SD/FAT32-драйвер для ZiFi, замена закрытого WDFCVBI2.COD.
Реализует ту же CORE-таблицу (CORE equ #2002 в zifi.asm), что и
оригинальный драйвер, но с открытыми исходниками.
Файлы
zc_sd_driver.asm— резидентная часть: таблица переходов CORE, сохранение IX в точках входа и распаковщик тела. Длинные рабочие операции оставляют растровые прерывания включёнными; конфликтующие задачи ZiFi блокируются снаружи черезinit_sd_card/sd_exit.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
# зачем: --sym выгружает адреса ВСЕХ меток тела (включая DATA/CONF --
# служебные метки портов ввода-вывода), а zc_sd_driver.asm уже сам
# объявляет DATA/CONF как константы -- если подключить дамп как есть,
# получим "Duplicate label: DATA"/"Duplicate label: CONF". Поэтому
# перед тем как класть файл в body_syms.inc, эти две строки убираются:
grep -v -E "^(DATA|CONF): EQU" body_syms_new.txt > body_syms.inc
# упаковать zc_sd_driver_body.bin -> zc_sd_driver_body.pb (PackBits;
# любым PackBits-кодировщиком с раунд-трип проверкой -- контрольный
# байт C: C=128 конец, C<128 литерал C+1 байт, C>128 повтор (257-C) раз)
sjasmplus.exe zc_sd_driver.asm
Результат (zc_sd_driver.bin) копируется в _spg/ и подключается
через _spg/spgbld.ini (Block = #e000, #0f, zc_sd_driver.bin).