Compare commits

...

184 Commits

Author SHA1 Message Date
Eric Helgeson
bf5823468a Add 50pin 1.1 case back, was accidentally removed in 57ff0cd3b4 2024-02-22 07:30:57 -06:00
Eric Helgeson
2baa0155e1
Merge pull request #262 from dotsam/better-logging
Reformatted Logging
2024-02-17 15:59:33 -06:00
Sam Edwards
3a9db99723 Changing indentation on log lines 2024-02-17 11:23:17 -08:00
Sam Edwards
70eda86484 Ensure log output is correct with used IDs 2024-02-17 11:23:17 -08:00
Sam Edwards
9d4207ea14 Only read INI per-device config once in "finalize" function, include filenames in output 2024-02-17 11:23:17 -08:00
Sam Edwards
1d49003fe1 Clean up logging in setup functions 2024-02-17 11:22:27 -08:00
Sam Edwards
0a30396c3b Make better use of macros, functions, and dynamic char array lengths 2024-02-17 11:21:26 -08:00
Sam Edwards
ba06827814 Whitespace/Type cleanup 2024-02-17 11:21:26 -08:00
Eric Helgeson
a45af3edec
Merge pull request #261 from WilliamLeara/fix_typographical_errors
fix typographical mistakes in comments
2024-02-17 12:05:27 -06:00
William Leara
0be37ccde0 fix typographical mistakes in comments
Also, fix up some white-space issues.  No functional change here.
2024-02-14 13:31:35 -06:00
Eric Helgeson
e236b5b054
Merge pull request #252 from dotsam/easy-leds
Easier to change LEDs
2024-02-09 20:11:36 -06:00
Sam Edwards
47179c5fd0
Easier to change LEDs
- For building for boards with different LEDs and configurations
 - Define mode for LED
 - Update GPIO macros for port C
 - Use macros to generate bits for registers
2024-02-09 17:42:07 -08:00
Eric Helgeson
59c858332a dev 2023-11-16 21:39:00 -06:00
Eric Helgeson
dddb7bfc1c v1.1-20231116 2023-11-16 21:38:41 -06:00
Eric Helgeson
8b79df00ba
Merge pull request #257 from erichelgeson/eric/toolbox
BlueSCSI Toolbox
2023-11-16 21:35:26 -06:00
Eric Helgeson
7c9428131b Update commands to match v2 2023-11-16 21:30:15 -06:00
Eric Helgeson
e35bae560c constant for block size 2023-11-16 21:30:15 -06:00
Eric Helgeson
13d7b985b7 Reuse m_buf and allow for 100 files 2023-11-16 21:30:15 -06:00
Eric Helgeson
27b7427301 hide hidden files 2023-11-16 21:30:15 -06:00
Eric Helgeson
98162fcd84 Fix issue with large files MSB being overwritten 2023-11-16 21:30:10 -06:00
Eric Helgeson
2be810e2ca 68k app 2023-10-24 17:17:12 -05:00
Eric Helgeson
4f7c0fe2c2
Merge pull request #253 from dotsam/compiler-warnings
Fix some compiler warnings
2023-08-13 10:22:33 -05:00
Sam Edwards
458617a827
Fix some compiler warnings
- Fix syntax of a cast to a uint32
 - Remove defines that are already made by the base platform
2023-08-11 11:47:34 -07:00
Eric Helgeson
810eae9be3
Merge pull request #251 from dotsam/fix-debug
Ensure allocLength is defined when needed in onReadBuffer
2023-08-10 20:37:08 -05:00
Sam Edwards
d67fa80cf0
Ensure allocLength is defined when needed in onReadBuffer 2023-08-10 16:57:06 -07:00
Eric Helgeson
9e746ba145 Back to snapshot 2023-07-08 12:06:50 -05:00
Eric Helgeson
e0d115f33c v1.1-20230708 2023-07-08 11:53:38 -05:00
Eric Helgeson
27d13192b0 Ignore kicad backup dir 2023-07-08 11:45:08 -05:00
Eric Helgeson
43335afbdb Use fork of SdFat that supports gpt partitions so users do not have to format their cards with mbr. Thanks @PetteriAimonen for the patch. 2023-04-01 11:24:11 -05:00
Troy
ad4737f384 INQUIRY supports small transfer sizes now
this fixes some Apple II SCSI cards like RAMFast and CMS
2023-04-01 11:23:53 -05:00
Eric Helgeson
927f8101fa Allow optical files that are set to RO on the SD card to be used 2023-04-01 11:20:19 -05:00
Eric Helgeson
142117c83a Merge remote-tracking branch 'jokker/troy/inifile' 2023-04-01 11:13:05 -05:00
Troy
c5eff4f5fd megastemode renamed to maplunstoids in inifile 2022-12-28 22:16:54 -05:00
Troy
c901efb929 fixed up CI/CD to work with ext libs better 2022-12-28 15:16:21 -05:00
Troy
2d0b466296 remove miniIni from PIO lib_deps 2022-12-28 11:30:07 -05:00
Eric Helgeson
075e21d981
Merge pull request #208 from erichelgeson/eric/clarifyType
Clarify the bluepill must be the C8T6 and not a C6T6
2022-12-27 16:38:11 -06:00
Eric Helgeson
71b1d3ca31 Clarify the bluepill must be the C8T6 and not a C6T6 2022-12-27 15:37:05 -06:00
Troy
5bad53008a bluescsi.ini support enabled for some features
MegaSTE Mode
Per SCSI device Product/Vendor/Revision

bunch of text refactoring for brievity and byteshaving
some reorg of the SD card info printed in the log
other little bits here and there
2022-12-22 17:45:20 -05:00
Troy
c2c4b83925 miniIni lib added 2022-12-22 11:19:59 -05:00
Eric Helgeson
5506a90042 Back to snapshot 2022-12-22 08:55:46 -06:00
Eric Helgeson
b117ebb39d v1.1-20221203 2022-12-03 16:14:13 -06:00
Eric Helgeson
139a510ee7
Merge pull request #201 from erichelgeson/eric/fragmented
Warn user if file is fragmented
2022-12-03 16:04:45 -06:00
Eric Helgeson
7ee2c44c6a Warn user if file is fragmented
See: https://github.com/greiman/SdFat/issues/256#issuecomment-778795554
- performance can be impacted if the file is fragmented on the SD card.
2022-12-03 15:22:07 -06:00
Eric Helgeson
f4d7cdfa92
Merge pull request #196 from mynameistroy/troy/megaste_mode
MegaSTE mode added for using IDs as LUNs
2022-12-01 14:28:58 -06:00
Eric Helgeson
a8903d42f2
Merge pull request #194 from mynameistroy/troy/cdb_length_fix
added a full lookup table for cdb length
2022-12-01 14:28:50 -06:00
Troy
0ae77a7b48 cleaned things up and added a log message 2022-11-30 21:42:38 -05:00
Eric Helgeson
726d72c09b
Merge pull request #186 from erichelgeson/eric/spiTake3
Revert "We only need to test 50 and 25 as the rest are just divided and rounded to full and half."
2022-11-22 16:51:21 -06:00
Eric Helgeson
dc0bce859c Revert "We only need to test 50 and 25 as the rest are just divided and rounded to full and half."
This reverts commit 1cfaf00594.
2022-11-22 16:50:07 -06:00
Troy
dba1860856 MegaSTE mode added for using IDs as LUNs 2022-11-13 18:08:41 -05:00
Troy
6ec75300c4 added a full lookup table for cdb length
this fixes the issue of 16 byte cdb commands
from causing problems by not being detected correctly
2022-11-06 12:20:30 -05:00
Eric Helgeson
5bb2dee71f
Merge pull request #187 from erichelgeson/eric/renameSTL
Rename file to be more clear
2022-10-14 16:20:32 -05:00
Eric Helgeson
bb4b688cad Rename file to be more clear 2022-10-14 16:20:04 -05:00
Eric Helgeson
44b6270ef8
Merge pull request #172 from lausvi/main
external-db25 3D-printed case remix
2022-10-14 16:08:32 -05:00
Eric Helgeson
30cf64ff83
Merge pull request #185 from command-tab/patch-1
Fix typo in README.adoc
2022-10-14 16:06:35 -05:00
Collin Allen
d3ef149aa3
Fix typo in README.adoc
Gerbers was misspelled as Grebers
2022-10-14 12:18:09 -07:00
Eric Helgeson
e930ecfcde
Merge pull request #183 from mynameistroy/troy/myst_fix
Fix for incorrect response to READ_DVD_STRUCTURE
2022-10-13 14:53:50 -05:00
Troy
847456203f Cleaned up SDfs logging 2022-10-12 21:15:18 -04:00
Troy
fb3a266c86 Report error for READ_DVD_STRUCTURE
fixes issues with drivers getting confused about the optical image file
2022-10-12 21:08:47 -04:00
Ville Laustela
330c3edd91 external-3D-printed-case-remix 2022-09-20 19:11:43 +03:00
Ville Laustela
57ff0cd3b4 external-3D-printed-case-remix 2022-09-20 19:07:56 +03:00
Eric Helgeson
452930940c Back to snapshot 2022-09-18 15:30:42 -05:00
Eric Helgeson
7c6f9aef75 v1.1-20220917 2022-09-17 09:53:00 -05:00
Mike
a7af02057f Add apostrophe to log message 2022-09-17 09:53:00 -05:00
Eric Helgeson
19f6b428a1
Merge pull request #151 from erichelgeson/eric/longFileNames
Allow for file names to be up to 64 chars
2022-09-17 09:42:04 -05:00
Eric Helgeson
b0a47bc376 Allow for file names to be up to 64 chars 2022-09-17 09:37:32 -05:00
Eric Helgeson
dc9552410f
Merge pull request #130 from mynameistroy/troy/optical
CD/DVD emulation
2022-09-13 20:46:54 -05:00
Troy
67d3909dd9 Cleaned up MODE_SELECT blocksize request
OnReadBuffer uses generic buffer and only transfers actual length
2022-09-11 18:32:29 -04:00
Troy
3f279230d9 cleanup Apple Mode Page handling 2022-09-08 22:02:55 -04:00
Troy
331cd96ac5 minor logging cleanup 2022-09-06 22:46:38 -04:00
Troy
3952181d4f Clean up some remaining pinMode => gpio_mode 2022-09-06 22:45:26 -04:00
Eric Helgeson
c12aa478d5
Merge pull request #161 from erichelgeson/eric/kay_stl
Add Kay's STL
2022-08-25 18:50:12 -05:00
Eric Helgeson
9831c38237 Add Kay's STL 2022-08-25 18:47:59 -05:00
Troy
94a5e711e3 MODE SELECT supports CDROM 512/2048 sector toggle
CDROM devices return a DBD properly
CDROM Error Mode Page has a default retry of 1
More streamlining of debug logging
2022-08-17 21:15:15 -04:00
Eric Helgeson
6b2152d1f7
Merge pull request #152 from erichelgeson/eric/SDFat2.2.0
Upgrade SdFat from 2.0.6 to 2.2.0
2022-08-03 09:07:23 -05:00
Eric Helgeson
a06e840e39 Upgrade SdFat from 2.0.6 to 2.2.0
No change in perf
2022-07-26 18:28:19 -05:00
Troy
32453b9886 added missing set of raw sector size 2022-07-24 23:11:15 -04:00
Troy
3a3d68cf99 alternative sector size supported
this let's .BIN files get used at the very least, maybe more depending
on how some of the other optical formats look
reverted a small SCSI phase change that causes problems
2022-07-22 20:38:59 -04:00
Troy
30b794e03d merged in latest HEAD, cleaned up some warnings 2022-07-17 11:49:08 -04:00
Troy
2611ec885b out of phase error fixed, SGI Indy works now
basic determination of arbitration
2022-07-17 11:26:07 -04:00
Troy
953309be30 ISO-9660 raw image support for CD/DVD emulation 2022-07-17 11:26:05 -04:00
Troy
b00dac7339 more code shuffling 2022-07-17 11:20:58 -04:00
Troy
b53524e6c7 code layout adjustments 2022-07-17 11:20:55 -04:00
Eric Helgeson
16c0cfd57a
Merge pull request #144 from erichelgeson/eric/minorFixes
Minor Updates and Fixes
2022-07-16 15:05:34 -05:00
Eric Helgeson
40e4590686 Product back to BLUESCSI F1 2022-07-16 15:02:19 -05:00
Eric Helgeson
d4f86ddaed LED on/off is around all commands, no need to have it here. 2022-07-16 15:02:19 -05:00
Eric Helgeson
ff8990e5c5 Test unit ready is a nop and not defined 2022-07-16 15:02:19 -05:00
Eric Helgeson
173cc6126a Turn warnings on 2022-07-16 15:02:19 -05:00
Eric Helgeson
2a95bc35ff
Merge pull request #142 from mynameistroy/troy/phase_fix
SCSI Phase handling improved for SCSI-2
2022-07-16 15:02:02 -05:00
Eric Helgeson
219e3d0f23
Merge pull request #141 from mynameistroy/troy/lun_fix
stop invalid LUNs from reading unallocated structs
2022-07-16 15:01:55 -05:00
Eric Helgeson
2bd79bb487
Merge pull request #140 from mynameistroy/troy/icd
Support for Atari ST ICD commands
2022-07-16 15:01:42 -05:00
Eric Helgeson
53ad02384d
Merge branch 'main' into troy/icd 2022-07-16 15:01:35 -05:00
Eric Helgeson
e26e41dcbd
Merge pull request #143 from erichelgeson/eric/pinSDFat
Pin SdFat to 2.0.6
2022-07-16 13:40:32 -05:00
Eric Helgeson
2f8dd8a3fe Pin SdFat to 2.0.6 to allow CI to run 2022-07-16 13:13:34 -05:00
Troy
5d80b8adbf added proper define for ICD command 2022-07-13 17:58:59 -04:00
Troy
e5d78139de SCSI Phase handling improved for SCSI-2 2022-07-03 22:13:25 -04:00
Troy
0895f00094 stop invalid LUNs from reading unallocated structs 2022-07-03 15:39:17 -04:00
Troy
58e880a9e1 Support for Atari ST ICD commands 2022-06-29 21:36:33 -04:00
Eric Helgeson
54500e18b8 Back to snapshot 2022-06-26 10:57:03 -05:00
Eric Helgeson
ca9089b405 v1.1-20220626 2022-06-26 09:35:44 -05:00
Eric Helgeson
f8cd61fbf9
Merge pull request #138 from erichelgeson/eric/vdrName
Change product so vendor specific Quantum commands are not issued
2022-06-26 09:31:50 -05:00
Eric Helgeson
a2a2d82d4b
Merge pull request #137 from erichelgeson/eric/senseCache0x08
Add Sense page for caching 0x08
2022-06-26 07:14:02 -05:00
Eric Helgeson
b74eecfa7a Add Sense page for caching 0x08 2022-06-26 07:03:09 -05:00
Eric Helgeson
63a1fe9c41 Change product so vendor specific Quantum commands are not issued, but still compatible with Apple formatting utils 2022-06-26 07:02:46 -05:00
Eric Helgeson
423b054f5a
Merge pull request #135 from mynameistroy/troy/minorfixes
minor fixes
2022-06-26 06:51:06 -05:00
Troy
d97ea88d17 minor fixes
cleaned up onReadCapacity last lba calculation
cleaned up Flexible Geometry Mode Page values
2022-06-25 15:42:36 -04:00
Eric Helgeson
45524964d6
Merge pull request #134 from erichelgeson/eric/bugfixes
Fix onReadCapacity calculation & Sense offset for Flexable Geometry
2022-06-24 16:21:44 -05:00
Eric Helgeson
28078212f5 Fix length offset for Flexable Geometry sense 2022-06-24 16:13:15 -05:00
Eric Helgeson
52a0936fbc Fix onReadCapacity calculation 2022-06-24 16:13:15 -05:00
Eric Helgeson
4dbba493d7
Merge pull request #133 from mactcp/main
Fix handling of dbd bit in onModeSense(), cleanup some stray command table definitions.
2022-06-24 16:09:42 -05:00
Glenn Anderson
f29da7c88c Cleanup some stray command table definitions.
Fix handling of dbd bit in onModeSense()
2022-06-24 13:21:05 -07:00
Eric Helgeson
ad87d86b7a Remove copy/paste error in -USB firmware 2022-06-23 08:21:31 -05:00
Eric Helgeson
d26bf0a15a Back to snapshot 2022-06-22 07:43:35 -05:00
Eric Helgeson
f7075df6d8 v1.1-20220620 2022-06-20 07:45:35 -05:00
Eric Helgeson
3b7aa0d160 Renamed build to dist 2022-06-20 07:45:18 -05:00
Eric Helgeson
8e4b4ee512 v1.1-SNAPSHOT-20220617 2022-06-17 10:23:51 -05:00
Eric Helgeson
557f34e5da
Merge pull request #122 from erichelgeson/eric/spi
We only need to test full and half speed spi
2022-06-17 10:08:28 -05:00
Eric Helgeson
11901d6a0d
Merge pull request #126 from ryandesign/patch-1
Fix typos
2022-06-17 10:05:25 -05:00
Eric Helgeson
1cfaf00594 We only need to test 50 and 25 as the rest are just divided and rounded to full and half. 2022-06-17 10:04:04 -05:00
Eric Helgeson
07961108c7
Merge pull request #115 from mynameistroy/troy/function_table
Switched to function table for SCSI commands
2022-06-17 10:03:05 -05:00
Eric Helgeson
b01c2ffd7c
Merge pull request #127 from ryandesign/patch-2
Fix typos
2022-06-17 09:36:10 -05:00
Ryan Schmidt
d5405ab5f0
Fix typos 2022-06-17 06:52:11 -05:00
Ryan Schmidt
bfa59a1fa4
Fix typos 2022-06-17 06:32:24 -05:00
Troy
f69cff42e4 LED2 blinks once again 2022-06-16 17:13:35 -04:00
Troy
9b2b3f689f accidentally left DEBUG = 1 2022-06-10 23:05:42 -04:00
Troy
eeacf3e746 dev->m_file actually gets the right pointer now 2022-06-10 22:57:06 -04:00
Troy
e52957315e Switched to function table for SCSI commands
moved defines/macros/etc to BlueSCSI.h
SCSI device state is now per device instead of global
Missing INQUIRY init added
SCSI-2 LUN handling (Fixes excess LUN's on SCSI-2)
Only allocate File obj for active SCSI ID's
2022-06-10 22:23:14 -04:00
Eric Helgeson
2641e80fac
Merge pull request #120 from erichelgeson/eric/readDefectData
Implement Read Defect Data 0x37
2022-06-08 15:51:18 -05:00
Eric Helgeson
437b2531ca
Merge pull request #118 from mactcp/main
XCVR code cleanup
2022-06-08 10:00:14 -05:00
Glenn Anderson
dcbb7df80d Alignment adjustment to make XCVR perform the same as non-XCVR 2022-06-04 23:33:19 -07:00
Glenn Anderson
1aecf323e1 Remove unnecessary SCSI_DB_INPUT() and TRANSCEIVER_IO_SET(vTR_DBP,TR_INPUT) 2022-06-03 16:11:53 -07:00
Eric Helgeson
d6ff7017c9 Implement Read Defect Data 0x37 2022-06-02 21:49:27 -05:00
Glenn Anderson
8167ddea6c Move TRANSCEIVER_IO_SET out of writeDataLoop.
Add matching TRANSCEIVER_IO_SET(vTR_DBP,TR_INPUT) to writeDataPhase() and writeDataPhaseSD()
2022-06-01 12:44:05 -07:00
Eric Helgeson
2338d8f153
Merge pull request #117 from erichelgeson/eric/reordercmds
Move read/write command earlier, few kb/sec faster read/write
2022-05-30 16:16:33 +00:00
Eric Helgeson
b16dc558dc Add a few more noops 2022-05-30 11:13:06 -05:00
Eric Helgeson
a5c6edadc3 Move read/write command earlier, few kb/sec faster read/write 2022-05-30 11:13:06 -05:00
Eric Helgeson
79d5b12110
Merge pull request #116 from erichelgeson/eric/noopCmds
Add cmds that are ok to respond GOOD and not do anything.
2022-05-30 14:50:33 +00:00
Eric Helgeson
d6fb46d387 Add cmds that are ok to respond GOOD and not do anything. 2022-05-26 10:01:03 -05:00
Eric Helgeson
c2c3397b72
Merge pull request #114 from erichelgeson/eric/newCmds
Four new commands & some Sense
2022-05-25 02:38:02 +00:00
Eric Helgeson
906b8be9aa Implement Send Diagnostic 2022-05-24 16:49:23 -05:00
Eric Helgeson
3c258451fa Add SCSI_SENSE_MODE_FLEXABLE_GEOMETRY 2022-05-24 13:38:21 -05:00
Eric Helgeson
7cdddf7371 Fix header handling in scsi buffer 2022-05-24 13:37:17 -05:00
Eric Helgeson
20cb5d8552 Prepend the header to the buffer data 2022-05-23 17:13:09 -05:00
Eric Helgeson
5c0724703b Fix build for USB 2022-05-22 12:53:57 -05:00
Eric Helgeson
61ae8a59db Add constants for SCSI mode page codes 2022-05-21 17:32:07 -05:00
Eric Helgeson
19cc9ad169 Implement 3 commands:
SCSI Read Buffer (Thanks @marcelv-3!)
SCSI Write Buffer (Thanks @marcelv-3!)
ReZero Unit
2022-05-21 15:51:42 -05:00
Eric Helgeson
14321e3ba6
Merge pull request #113 from erichelgeson/eric/minorFixes2
Minor fixes
2022-05-21 15:51:33 -05:00
Eric Helgeson
b0799bc327 Remove tabs 2022-05-21 13:21:21 -05:00
Eric Helgeson
2127b14863 Fix default env name 2022-05-21 13:20:53 -05:00
Eric Helgeson
3ef2474ae8
Merge pull request #112 from erichelgeson/eric/versions
Build and tag all versions, collect & rename bin fines
2022-05-21 09:30:58 -05:00
Eric Helgeson
9d1b58cdb6
Merge pull request #111 from erichelgeson/eric/fewMinorFixes
Few minor fixes
2022-05-21 09:30:31 -05:00
Eric Helgeson
1f03996977 Build and tag all versions, collect & rename bin fines 2022-05-20 20:47:11 -05:00
Eric Helgeson
73fc0ed2bf Fix issue where log file would close when logging was enabled.
Thanks @marcelv-3
https://github.com/erichelgeson/BlueSCSI/discussions/103#discussioncomment-2779471
2022-05-20 19:36:06 -05:00
Eric Helgeson
94a22bb45e Add sd card volume format to log.txt 2022-05-20 19:34:19 -05:00
Eric Helgeson
c8d47218b1 Remove the usage of String, saves quite a bit of flash 2022-05-20 19:34:19 -05:00
Eric Helgeson
853956e441
Merge pull request #110 from erichelgeson/eric/APM32F103C8-support
Add support for the APM32F103C8T6 chip, a clone of the STM32F103
2022-05-20 19:34:01 -05:00
Eric Helgeson
69e69cad3a add support for the APM32F103C8T6 chip, a clone of the STM32F103 2022-05-18 19:43:56 -05:00
Eric Helgeson
bbd91936fb
Fix typo 2022-04-24 14:41:09 -05:00
Eric Helgeson
c04027c8ca
Merge pull request #97 from erichelgeson/eric/minor_cleanup
Implement Test Unit Ready & minor cleanup
2022-04-23 16:12:57 -05:00
Eric Helgeson
b898d9684f Remove comment 2022-04-23 16:09:44 -05:00
Eric Helgeson
38904285d4 Make the STM32F103C8 the default env 2022-04-23 16:08:30 -05:00
Eric Helgeson
8a27bcc585 Remove unused settings as we always use the OPTIMISEd ones 2022-04-23 16:08:30 -05:00
Eric Helgeson
c5447a4098 Add back LUN filename parsing 2022-04-23 16:08:30 -05:00
Eric Helgeson
408e155a63 Implement Test Unit Ready command 2022-04-23 16:08:30 -05:00
Eric Helgeson
f7799fb225 Replace magic numbers with constants - thanks Jokker 2022-04-23 16:08:30 -05:00
Eric Helgeson
845954edeb Remove unused SCSI_SELECT - upstream has moved to a different approch to
support PC98/etc
2022-04-23 16:08:30 -05:00
Eric Helgeson
7b7f19413c
Merge pull request #98 from mactcp/main
Support for image files larger than 4GB
2022-04-22 07:48:52 -05:00
Glenn Anderson
961ae0b8b7 Support for images larger than 4GB 2022-04-19 10:14:23 -07:00
Eric Helgeson
aa751dc3b8
Merge pull request #92 from erichelgeson/XCVR
Code for Transceiver Hardware
2022-04-18 21:19:08 -05:00
androda
fff520959e Merge branch 'main' into XCVR 2022-04-18 16:57:57 -06:00
androda
2f08b9fa73 Swap to #ifdef 2022-04-18 16:57:19 -06:00
Eric Helgeson
24e1612fc7 Add build env for xcvr 2022-04-17 16:39:59 -05:00
Eric Helgeson
a566c9bbb0
Merge pull request #94 from mactcp/Write-speed-tune
Write speed tuning
2022-04-17 14:51:46 -05:00
Eric Helgeson
9a4e3dc886
Merge pull request #96 from erichelgeson/eric/moveAssembly
Point assembly to wiki
2022-04-17 11:04:10 -05:00
Eric Helgeson
27c424d2f9
Update assembly.md 2022-04-17 11:01:44 -05:00
androda
3158391c86 Merge branch 'main' into XCVR 2022-04-15 06:29:02 -06:00
androda
ceb6da764b Boot tested
Tested to boot beige G3 and Q700, both with XCVR mode on and off on appropriate hardware
2022-04-15 06:14:59 -06:00
androda
b4b0ce711f Cleaning up changes 2022-04-15 05:34:47 -06:00
androda
77698d0a68 Disable by default
Since this is new hardware, disable it by default
2022-04-15 05:21:44 -06:00
androda
d593c0817c Seems to boot 2022-04-14 06:44:19 -06:00
Glenn Anderson
adca34aeb8 Write speed tuning 2022-04-13 16:47:48 -07:00
Eric Helgeson
693ab2a5c0
Merge pull request #88 from mactcp/Bus-settle-delay-cleanup
Cleanup of SCSI phase change code, and adjustment of bus settle delays.
2022-04-13 08:28:02 -05:00
androda
4d3ee87c56 Work in progress 2022-04-12 06:22:28 -06:00
Glenn Anderson
ba1b3df680 Cleanup of SCSI phase change code, and adjustment of bus settle delays. 2022-04-08 11:10:07 -07:00
Eric Helgeson
22eb2c8d3e Back to snapshot 2022-04-07 16:29:06 -05:00
25 changed files with 3555 additions and 1209 deletions

View File

@ -27,8 +27,5 @@ jobs:
python -m pip install --upgrade pip
pip install --upgrade platformio
- name: Install library dependencies
run: pio lib -g install 1
- name: Run PlatformIO
run: pio ci --project-conf platformio.ini .
run: pio run -e STM32F1 -e STM32F1-USB -e STM32F1-XCVR -e STM32F1-USB-96MHz -e STM32F1-USB-128MHz

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
.DS_Store
.vscode/
workspace.code-workspace
dist/
hw/*/*-backups/

View File

@ -1,6 +1,6 @@
# Mounts
## Desktop
## Desktop
Provides mouting holes for the BlueSCSI along with side and bottom holes for common mounting in computers.
@ -10,6 +10,8 @@ Please pre-tap any screw holes before mounting.
Print with supports for front overhangs. Tight fit to hold everything together.
Remix = a slightly modified version with light-pipes for the LEDs and some geometry fixes.
# License
BlueSCSI 3D files © 2021 by Eric Helgeson is licensed under Attribution-NonCommercial 4.0 International

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

View File

@ -10,7 +10,7 @@ BlueSCSI & ArdSCSino are hardware that reproduces SCSI devices (hard disks) with
* Enable/Disable Passive SCSI termination
* An alternative power source if not able to be powered by the SCSI bus
* Documentation
* Open Hardware (KiCad & Grebers)
* Open Hardware (KiCad & Gerbers)
`ArdSCSino-stm32` created by https://github.com/ztto/ArdSCSino-stm32[ztto] is the STM32 version of `ArdSCSino`
@ -63,7 +63,7 @@ https://github.com/erichelgeson/BlueSCSI/wiki/Troubleshooting
#### 1.1-a Desktop
* Binky! There are now resistors and pin outs for Power and Activity LED's
* Blinky! There are now resistors and pin outs for Power and Activity LED's
* Resistor nets flipped all the same way
* 50 pin allows for right angle connector
* SD Card facing out the back - gives some better options for mounting and access

14
dist.sh Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
set -e
set -x
DATE=$(date +%Y%m%d)
VERSION="v1.1-$DATE"
mkdir -p dist
rm -f dist/*.bin
for f in $(ls .pio/build/*/firmware.bin); do
NAME="BlueSCSI-$VERSION-$(echo $f | cut -d\/ -f3).bin"
cp $f dist/$NAME
done

View File

@ -3,25 +3,25 @@
## Introduction
1.0-c was a small change to fix an issue with machines that provide low or no `TERMPOWER` over the SCSI bus. If you recived a Fully Assembled BlueSCSI after April 1st, 2021 then this was done for you. If you have a kit labled 1.0-b you can make these modifications to become a 1.0-c.
1.0-c was a small change to fix an issue with machines that provide low or no `TERMPOWER` over the SCSI bus. If you received a fully-assembled BlueSCSI after April 1st, 2021 then this was done for you. If you have a kit labeled 1.0-b you can make these modifications to become a 1.0-c.
## Steps
### Disconnect `TERMPOWER` from 220 Pull Up Jupmer
### Disconnect `TERMPOWER` from 220 Pull Up Jumper
Use a cutting tool to cut the small trace between the `TERMPOWR` and 220 Pull Up Jumper pictured below.
Make sure continiutiy from `TERMPOWER` to the diode still flows correctly but is disconnected from the jumper.
Make sure continuity from `TERMPOWER` to the diode still flows correctly but is disconnected from the jumper.
image::images/1.0-b-bodge-1.jpg[]
### Connect 5V to 220 Pull Up Jupmer
### Connect 5V to 220 Pull Up Jumper
Now we will provide pull up from the 5v provided by the BluePill.
Now we will provide pull up from the 5V provided by the BluePill.
image::images/1.0-b-bodge-2.png[]
### Complete!
Thats it! 5v to the Pull Up resistors will now work when powered externally.
Thats it! 5V to the Pull Up resistors will now work when powered externally.

View File

@ -1,66 +1,5 @@
# Assembly
## Before you start
Instructions have moved to the wiki
Read through all instructions before starting.
## Videos
The community has created a few assembly videos:
* [Stephen Arsenault - BlueSCSI Kit Assembly](https://www.youtube.com/watch?v=G6lwCfLQwd8) 2:52
* [Joe's Computer Museum - A New Challenger - BlueSCSI - #MARCHintosh Review](https://www.youtube.com/watch?v=d_8VVmvvlNI) 26:52
* [Geeky Bit - Tutorial - BlueSCSI Assembly](https://www.youtube.com/watch?v=-nF9FYFgVHM) 20:35
## Building
1. Solder on the surface mount SD Card holder. Use the [Drag Solder](https://youtu.be/Z_KL4fWOMug) technique.
- Once on, check continuity of all connections. Fixing this after the BluePill is on will be difficult.
- Ensure the SD card fits and you dont have too much solder on the sides or contacts
2. Solder the diodes to the **bottom** of the board. Be sure they are flush as possible to the bottom.
![Diode Orientation](images/diodes.png)
3. Solder the header pins on to the BluePill. Then BluePill pill to the BlueSCSI PCB.
- Correct orientation is having the USB connector of the BluePill should be over the SD Card holder.
- **NOTE**: Consider adding headers to the board if you would like to have the BluePill removable.
4. Solder on the resistor nets. Pin one is marked on the board and the resistors.
- 220 RNETS (`RN1` & `RN3`) are closest to the BluePill
- **NOTE** PIN one on each - they are opposite of eachtoher. See photo.
- 330 RNETS (`RN2` & `RN4`) are furthest from the BluePill
- **NOTE** PIN one on each - they are opposite of eachtoher. See photo.
![Orientation RNETs and BluePill](images/orientation.png)
5. Solder on the Termination Jumpers & place the jumpers on to enable Termiation
6. Solder the 50 Pin headers on.
1. Note Pin 1 and Box header on the silk screen.
7. Optional - Solder on the berg connector. Only needed if your machine does not supply enough power via the SCSI bus.
8. Optional - Solder on the debug headers near the SD card. Only nessissarry if re-programming.
### Fully Assembled
![Fully Assembled](images/assembled.png)
### Version 1.0-b & 1.0-c BOM
#### Mouser Cart
https://www.mouser.com/ProjectManager/ProjectDetail.aspx?AccessID=c5cc83feff
#### Parts
STM32F103C8T6 (U1) aka BluePill board. Beware of fake/scams. Look for reviews. Amazon, ebay, etc.
* 2x 330 (RN2, RN4) Resistor nets https://www.mouser.com/ProductDetail/652-4610X-1LF-330
* 2x 220 (RN1, RN3) Resistor nets https://www.mouser.com/ProductDetail/652-4610X-1LF-220
* 2x Diodes https://www.mouser.com/ProductDetail/583-1N5818-T
* SD Card Holder (J1) https://www.mouser.com/ProductDetail/538-104031-0811
* Headers https://www.mouser.com/ProductDetail/872-920-0011-01
* 50 PIN SCSI header https://www.mouser.com/ProductDetail/517-30350-6002/
- May substitute with 2 rows of headers from above.
- **Note on Right angle connectors** - it appears Right angle headers are notched differently then the pin out. Be sure to note PIN 1/red stripe on the cable match up.
### Optional
Floppy/Berg Power header https://www.mouser.com/ProductDetail/571-1718254
- Required if your machine does not supply power via TERM POWER. For example a Mac Plus or Mac with a Analog/PSU board that has not been recapped.
https://github.com/erichelgeson/BlueSCSI/wiki/Assembly

View File

@ -1,7 +1,7 @@
# Build Your Own
These instructions will guide you thorugh purchasing all of the parts needed to assemble kits for yourselves and for friends! Please note the hardware is licensed non-comercial.
These instructions will guide you through purchasing all of the parts needed to assemble kits for yourselves and for friends! Please note the hardware is licensed non-commercial.
If you'd like to buy the kits pre-packaged/pre-flashed or fully assembled we have a network of makers here to help you out at https://scsi.blue
@ -11,11 +11,11 @@ Updated for 1.0-c.
### PCB's
Grab the latest Gerbers. Gerber files tell the PCB manufactuer how to create the BlueSCSI boards.
Grab the latest Gerbers. Gerber files tell the PCB manufacturer how to create the BlueSCSI boards.
https://github.com/erichelgeson/BlueSCSI/tree/main/hw/
Order the boards from https://jlcpcb.com/ or your manufactuer of choice.
Order the boards from https://jlcpcb.com/ or your manufacturer of choice.
### Components
@ -27,6 +27,8 @@ https://www.mouser.com/ProjectManager/ProjectDetail.aspx?AccessID=c5cc83feff
Buy from a place where returns are easy. Ensure the photo in the listing shows a chip that says STM32 on it.
The BluePill must be a STM32F103**C8T6** - a C6T6 will not work. Check the listings closely.
https://www.amazon.com/s?k=stm32f103c8t6
https://www.ebay.com/sch/i.html?_nkw=stm32f103c8t6
@ -55,6 +57,6 @@ https://github.com/erichelgeson/BlueSCSI#flashing
## Usage
Be sure to follow the usage instructions for getting your drive images setup:
Be sure to follow the usage instructions for getting your drive images set up:
https://github.com/erichelgeson/BlueSCSI#usage

15
lib/minIni/minGlue.h Normal file
View File

@ -0,0 +1,15 @@
/* Glue functions for the minIni library to SdFat library */
#include <SdFat.h>
extern SdFs SD;
#define INI_READONLY 1
#define INI_FILETYPE FsFile
#define ini_openread(filename,file) ((file)->open(SD.vol(), filename, O_RDONLY))
#define ini_close(file) ((file)->close())
#define ini_read(buffer,size,file) ((file)->fgets((buffer),(size)) > 0)
#define INI_FILEPOS fspos_t
#define ini_tell(file,pos) ((file)->fgetpos(pos))
#define ini_seek(file,pos) ((file)->fsetpos(pos))

952
lib/minIni/minIni.cpp Normal file
View File

@ -0,0 +1,952 @@
/* minIni - Multi-Platform INI file parser, suitable for embedded systems
*
* These routines are in part based on the article "Multiplatform .INI Files"
* by Joseph J. Graf in the March 1994 issue of Dr. Dobb's Journal.
*
* Copyright (c) CompuPhase, 2008-2021
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Version: $Id: minIni.c 53 2015-01-18 13:35:11Z thiadmer.riemersma@gmail.com $
*/
#if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined INI_ANSIONLY
# if !defined UNICODE /* for Windows */
# define UNICODE
# endif
# if !defined _UNICODE /* for C library */
# define _UNICODE
# endif
#endif
#define MININI_IMPLEMENTATION
#include "minIni.h"
#if defined NDEBUG
#define assert(e)
#else
#include <assert.h>
#endif
#if !defined __T || defined INI_ANSIONLY
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define TCHAR char
#define __T(s) s
#define _tcscat strcat
#define _tcschr strchr
#define _tcscmp strcmp
#define _tcscpy strcpy
#define _tcsicmp stricmp
#define _tcslen strlen
#define _tcsncmp strncmp
#define _tcsnicmp strnicmp
#define _tcsrchr strrchr
#define _tcstol strtol
#define _tcstod strtod
#define _totupper toupper
#define _stprintf sprintf
#define _tfgets fgets
#define _tfputs fputs
#define _tfopen fopen
#define _tremove remove
#define _trename rename
#endif
#if defined __linux || defined __linux__
#define __LINUX__
#elif defined FREEBSD && !defined __FreeBSD__
#define __FreeBSD__
#elif defined(_MSC_VER)
#pragma warning(disable: 4996) /* for Microsoft Visual C/C++ */
#endif
#if !defined strnicmp && !defined PORTABLE_STRNICMP
#if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ || defined __NetBSD__ || defined __DragonFly__ || defined __GNUC__
#define strnicmp strncasecmp
#endif
#endif
#if !defined _totupper
#define _totupper toupper
#endif
#if !defined INI_LINETERM
#if defined __LINUX__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ || defined __NetBSD__ || defined __DragonFly__
#define INI_LINETERM __T("\n")
#else
#define INI_LINETERM __T("\r\n")
#endif
#endif
#if !defined INI_FILETYPE
#error Missing definition for INI_FILETYPE.
#endif
#if !defined sizearray
#define sizearray(a) (sizeof(a) / sizeof((a)[0]))
#endif
enum quote_option {
QUOTE_NONE,
QUOTE_ENQUOTE,
QUOTE_DEQUOTE,
};
#if defined PORTABLE_STRNICMP
int strnicmp(const TCHAR *s1, const TCHAR *s2, size_t n)
{
while (n-- != 0 && (*s1 || *s2)) {
register int c1, c2;
c1 = *s1++;
if ('a' <= c1 && c1 <= 'z')
c1 += ('A' - 'a');
c2 = *s2++;
if ('a' <= c2 && c2 <= 'z')
c2 += ('A' - 'a');
if (c1 != c2)
return c1 - c2;
}
return 0;
}
#endif /* PORTABLE_STRNICMP */
static TCHAR *skipleading(const TCHAR *str)
{
assert(str != NULL);
while ('\0' < *str && *str <= ' ')
str++;
return (TCHAR *)str;
}
static TCHAR *skiptrailing(const TCHAR *str, const TCHAR *base)
{
assert(str != NULL);
assert(base != NULL);
while (str > base && '\0' < *(str-1) && *(str-1) <= ' ')
str--;
return (TCHAR *)str;
}
static TCHAR *striptrailing(TCHAR *str)
{
TCHAR *ptr = skiptrailing(_tcschr(str, '\0'), str);
assert(ptr != NULL);
*ptr = '\0';
return str;
}
static TCHAR *ini_strncpy(TCHAR *dest, const TCHAR *source, size_t maxlen, enum quote_option option)
{
size_t d, s;
assert(maxlen>0);
assert(source != NULL && dest != NULL);
assert((dest < source || (dest == source && option != QUOTE_ENQUOTE)) || dest > source + strlen(source));
if (option == QUOTE_ENQUOTE && maxlen < 3)
option = QUOTE_NONE; /* cannot store two quotes and a terminating zero in less than 3 characters */
switch (option) {
case QUOTE_NONE:
for (d = 0; d < maxlen - 1 && source[d] != '\0'; d++)
dest[d] = source[d];
assert(d < maxlen);
dest[d] = '\0';
break;
case QUOTE_ENQUOTE:
d = 0;
dest[d++] = '"';
for (s = 0; source[s] != '\0' && d < maxlen - 2; s++, d++) {
if (source[s] == '"') {
if (d >= maxlen - 3)
break; /* no space to store the escape character plus the one that follows it */
dest[d++] = '\\';
}
dest[d] = source[s];
}
dest[d++] = '"';
dest[d] = '\0';
break;
case QUOTE_DEQUOTE:
for (d = s = 0; source[s] != '\0' && d < maxlen - 1; s++, d++) {
if ((source[s] == '"' || source[s] == '\\') && source[s + 1] == '"')
s++;
dest[d] = source[s];
}
dest[d] = '\0';
break;
default:
assert(0);
}
return dest;
}
static TCHAR *cleanstring(TCHAR *string, enum quote_option *quotes)
{
int isstring;
TCHAR *ep;
assert(string != NULL);
assert(quotes != NULL);
/* Remove a trailing comment */
isstring = 0;
for (ep = string; *ep != '\0' && ((*ep != ';' && *ep != '#') || isstring); ep++) {
if (*ep == '"') {
if (*(ep + 1) == '"')
ep++; /* skip "" (both quotes) */
else
isstring = !isstring; /* single quote, toggle isstring */
} else if (*ep == '\\' && *(ep + 1) == '"') {
ep++; /* skip \" (both quotes */
}
}
assert(ep != NULL && (*ep == '\0' || *ep == ';' || *ep == '#'));
*ep = '\0'; /* terminate at a comment */
striptrailing(string);
/* Remove double quotes surrounding a value */
*quotes = QUOTE_NONE;
if (*string == '"' && (ep = _tcschr(string, '\0')) != NULL && *(ep - 1) == '"') {
string++;
*--ep = '\0';
*quotes = QUOTE_DEQUOTE; /* this is a string, so remove escaped characters */
}
return string;
}
static int getkeystring(INI_FILETYPE *fp, const TCHAR *Section, const TCHAR *Key,
int idxSection, int idxKey, TCHAR *Buffer, int BufferSize,
INI_FILEPOS *mark)
{
TCHAR *sp, *ep;
int len, idx;
enum quote_option quotes;
TCHAR LocalBuffer[INI_BUFFERSIZE];
assert(fp != NULL);
/* Move through file 1 line at a time until a section is matched or EOF. If
* parameter Section is NULL, only look at keys above the first section. If
* idxSection is positive, copy the relevant section name.
*/
len = (Section != NULL) ? (int)_tcslen(Section) : 0;
if (len > 0 || idxSection >= 0) {
assert(idxSection >= 0 || Section != NULL);
idx = -1;
do {
do {
if (!ini_read(LocalBuffer, INI_BUFFERSIZE, fp))
return 0;
sp = skipleading(LocalBuffer);
ep = _tcsrchr(sp, ']');
} while (*sp != '[' || ep == NULL);
/* When arrived here, a section was found; now optionally skip leading and
* trailing whitespace.
*/
assert(sp != NULL && *sp == '[');
sp = skipleading(sp + 1);
assert(ep != NULL && *ep == ']');
ep = skiptrailing(ep, sp);
} while ((((int)(ep-sp) != len || Section == NULL || _tcsnicmp(sp, Section, len) != 0) && ++idx != idxSection));
if (idxSection >= 0) {
if (idx == idxSection) {
assert(ep != NULL);
*ep = '\0'; /* the end of the section name was found earlier */
ini_strncpy(Buffer, sp, BufferSize, QUOTE_NONE);
return 1;
}
return 0; /* no more section found */
}
}
/* Now that the section has been found, find the entry.
* Stop searching upon leaving the section's area.
*/
assert(Key != NULL || idxKey >= 0);
len = (Key != NULL) ? (int)_tcslen(Key) : 0;
idx = -1;
do {
if (mark != NULL)
ini_tell(fp, mark); /* optionally keep the mark to the start of the line */
if (!ini_read(LocalBuffer,INI_BUFFERSIZE,fp) || *(sp = skipleading(LocalBuffer)) == '[')
return 0;
sp = skipleading(LocalBuffer);
ep = _tcschr(sp, '='); /* Parse out the equal sign */
if (ep == NULL)
ep = _tcschr(sp, ':');
} while (*sp == ';' || *sp == '#' || ep == NULL
|| ((len == 0 || (int)(skiptrailing(ep,sp)-sp) != len || _tcsnicmp(sp,Key,len) != 0) && ++idx != idxKey));
if (idxKey >= 0) {
if (idx == idxKey) {
assert(ep != NULL);
assert(*ep == '=' || *ep == ':');
*ep = '\0';
striptrailing(sp);
ini_strncpy(Buffer, sp, BufferSize, QUOTE_NONE);
return 1;
}
return 0; /* no more key found (in this section) */
}
/* Copy up to BufferSize chars to buffer */
assert(ep != NULL);
assert(*ep == '=' || *ep == ':');
sp = skipleading(ep + 1);
sp = cleanstring(sp, &quotes); /* Remove a trailing comment */
ini_strncpy(Buffer, sp, BufferSize, quotes);
return 1;
}
/** ini_gets()
* \param Section the name of the section to search for
* \param Key the name of the entry to find the value of
* \param DefValue default string in the event of a failed read
* \param Buffer a pointer to the buffer to copy into
* \param BufferSize the maximum number of characters to copy
* \param Filename the name and full path of the .ini file to read from
*
* \return the number of characters copied into the supplied buffer
*/
int ini_gets(const TCHAR *Section, const TCHAR *Key, const TCHAR *DefValue,
TCHAR *Buffer, int BufferSize, const TCHAR *Filename)
{
INI_FILETYPE fp;
int ok = 0;
if (Buffer == NULL || BufferSize <= 0 || Key == NULL)
return 0;
if (ini_openread(Filename, &fp)) {
ok = getkeystring(&fp, Section, Key, -1, -1, Buffer, BufferSize, NULL);
(void)ini_close(&fp);
}
if (!ok)
ini_strncpy(Buffer, (DefValue != NULL) ? DefValue : __T(""), BufferSize, QUOTE_NONE);
return (int)_tcslen(Buffer);
}
/** ini_getl()
* \param Section the name of the section to search for
* \param Key the name of the entry to find the value of
* \param DefValue the default value in the event of a failed read
* \param Filename the name of the .ini file to read from
*
* \return the value located at Key
*/
long ini_getl(const TCHAR *Section, const TCHAR *Key, long DefValue, const TCHAR *Filename)
{
TCHAR LocalBuffer[64];
int len = ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename);
return (len == 0) ? DefValue
: ((len >= 2 && _totupper((int)LocalBuffer[1]) == 'X') ? _tcstol(LocalBuffer, NULL, 16)
: _tcstol(LocalBuffer, NULL, 10));
}
#if defined INI_REAL
/** ini_getf()
* \param Section the name of the section to search for
* \param Key the name of the entry to find the value of
* \param DefValue the default value in the event of a failed read
* \param Filename the name of the .ini file to read from
*
* \return the value located at Key
*/
INI_REAL ini_getf(const TCHAR *Section, const TCHAR *Key, INI_REAL DefValue, const TCHAR *Filename)
{
TCHAR LocalBuffer[64];
int len = ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename);
return (len == 0) ? DefValue : ini_atof(LocalBuffer);
}
#endif
/** ini_getbool()
* \param Section the name of the section to search for
* \param Key the name of the entry to find the value of
* \param DefValue default value in the event of a failed read; it should
* zero (0) or one (1).
* \param Filename the name and full path of the .ini file to read from
*
* A true boolean is found if one of the following is matched:
* - A string starting with 'y' or 'Y'
* - A string starting with 't' or 'T'
* - A string starting with '1'
*
* A false boolean is found if one of the following is matched:
* - A string starting with 'n' or 'N'
* - A string starting with 'f' or 'F'
* - A string starting with '0'
*
* \return the true/false flag as interpreted at Key
*/
int ini_getbool(const TCHAR *Section, const TCHAR *Key, int DefValue, const TCHAR *Filename)
{
TCHAR LocalBuffer[2] = __T("");
int ret;
ini_gets(Section, Key, __T(""), LocalBuffer, sizearray(LocalBuffer), Filename);
LocalBuffer[0] = (TCHAR)_totupper((int)LocalBuffer[0]);
if (LocalBuffer[0] == 'Y' || LocalBuffer[0] == '1' || LocalBuffer[0] == 'T')
ret = 1;
else if (LocalBuffer[0] == 'N' || LocalBuffer[0] == '0' || LocalBuffer[0] == 'F')
ret = 0;
else
ret = DefValue;
return(ret);
}
/** ini_getsection()
* \param idx the zero-based sequence number of the section to return
* \param Buffer a pointer to the buffer to copy into
* \param BufferSize the maximum number of characters to copy
* \param Filename the name and full path of the .ini file to read from
*
* \return the number of characters copied into the supplied buffer
*/
int ini_getsection(int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename)
{
INI_FILETYPE fp;
int ok = 0;
if (Buffer == NULL || BufferSize <= 0 || idx < 0)
return 0;
if (ini_openread(Filename, &fp)) {
ok = getkeystring(&fp, NULL, NULL, idx, -1, Buffer, BufferSize, NULL);
(void)ini_close(&fp);
}
if (!ok)
*Buffer = '\0';
return (int)_tcslen(Buffer);
}
/** ini_getkey()
* \param Section the name of the section to browse through, or NULL to
* browse through the keys outside any section
* \param idx the zero-based sequence number of the key to return
* \param Buffer a pointer to the buffer to copy into
* \param BufferSize the maximum number of characters to copy
* \param Filename the name and full path of the .ini file to read from
*
* \return the number of characters copied into the supplied buffer
*/
int ini_getkey(const TCHAR *Section, int idx, TCHAR *Buffer, int BufferSize, const TCHAR *Filename)
{
INI_FILETYPE fp;
int ok = 0;
if (Buffer == NULL || BufferSize <= 0 || idx < 0)
return 0;
if (ini_openread(Filename, &fp)) {
ok = getkeystring(&fp, Section, NULL, -1, idx, Buffer, BufferSize, NULL);
(void)ini_close(&fp);
}
if (!ok)
*Buffer = '\0';
return (int)_tcslen(Buffer);
}
/** ini_hassection()
* \param Section the name of the section to search for
* \param Filename the name of the .ini file to read from
*
* \return 1 if the section is found, 0 if not found
*/
int ini_hassection(const mTCHAR *Section, const mTCHAR *Filename)
{
TCHAR LocalBuffer[32]; /* dummy buffer */
INI_FILETYPE fp;
int ok = 0;
if (ini_openread(Filename, &fp)) {
ok = getkeystring(&fp, Section, NULL, -1, 0, LocalBuffer, sizearray(LocalBuffer), NULL);
(void)ini_close(&fp);
}
return ok;
}
/** ini_haskey()
* \param Section the name of the section to search for
* \param Key the name of the entry to find the value of
* \param Filename the name of the .ini file to read from
*
* \return 1 if the key is found, 0 if not found
*/
int ini_haskey(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Filename)
{
TCHAR LocalBuffer[32]; /* dummy buffer */
INI_FILETYPE fp;
int ok = 0;
if (ini_openread(Filename, &fp)) {
ok = getkeystring(&fp, Section, Key, -1, -1, LocalBuffer, sizearray(LocalBuffer), NULL);
(void)ini_close(&fp);
}
return ok;
}
#if !defined INI_NOBROWSE
/** ini_browse()
* \param Callback a pointer to a function that will be called for every
* setting in the INI file.
* \param UserData arbitrary data, which the function passes on the
* \c Callback function
* \param Filename the name and full path of the .ini file to read from
*
* \return 1 on success, 0 on failure (INI file not found)
*
* \note The \c Callback function must return 1 to continue
* browsing through the INI file, or 0 to stop. Even when the
* callback stops the browsing, this function will return 1
* (for success).
*/
int ini_browse(INI_CALLBACK Callback, void *UserData, const TCHAR *Filename)
{
TCHAR LocalBuffer[INI_BUFFERSIZE];
int lenSec, lenKey;
enum quote_option quotes;
INI_FILETYPE fp;
if (Callback == NULL)
return 0;
if (!ini_openread(Filename, &fp))
return 0;
LocalBuffer[0] = '\0'; /* copy an empty section in the buffer */
lenSec = (int)_tcslen(LocalBuffer) + 1;
for ( ;; ) {
TCHAR *sp, *ep;
if (!ini_read(LocalBuffer + lenSec, INI_BUFFERSIZE - lenSec, &fp))
break;
sp = skipleading(LocalBuffer + lenSec);
/* ignore empty strings and comments */
if (*sp == '\0' || *sp == ';' || *sp == '#')
continue;
/* see whether we reached a new section */
ep = _tcsrchr(sp, ']');
if (*sp == '[' && ep != NULL) {
sp = skipleading(sp + 1);
ep = skiptrailing(ep, sp);
*ep = '\0';
ini_strncpy(LocalBuffer, sp, INI_BUFFERSIZE, QUOTE_NONE);
lenSec = (int)_tcslen(LocalBuffer) + 1;
continue;
}
/* not a new section, test for a key/value pair */
ep = _tcschr(sp, '='); /* test for the equal sign or colon */
if (ep == NULL)
ep = _tcschr(sp, ':');
if (ep == NULL)
continue; /* invalid line, ignore */
*ep++ = '\0'; /* split the key from the value */
striptrailing(sp);
ini_strncpy(LocalBuffer + lenSec, sp, INI_BUFFERSIZE - lenSec, QUOTE_NONE);
lenKey = (int)_tcslen(LocalBuffer + lenSec) + 1;
/* clean up the value */
sp = skipleading(ep);
sp = cleanstring(sp, &quotes); /* Remove a trailing comment */
ini_strncpy(LocalBuffer + lenSec + lenKey, sp, INI_BUFFERSIZE - lenSec - lenKey, quotes);
/* call the callback */
if (!Callback(LocalBuffer, LocalBuffer + lenSec, LocalBuffer + lenSec + lenKey, UserData))
break;
}
(void)ini_close(&fp);
return 1;
}
#endif /* INI_NOBROWSE */
#if ! defined INI_READONLY
static void ini_tempname(TCHAR *dest, const TCHAR *source, int maxlength)
{
TCHAR *p;
ini_strncpy(dest, source, maxlength, QUOTE_NONE);
p = _tcschr(dest, '\0');
assert(p != NULL);
*(p - 1) = '~';
}
static enum quote_option check_enquote(const TCHAR *Value)
{
const TCHAR *p;
/* run through the value, if it has trailing spaces, or '"', ';' or '#'
* characters, enquote it
*/
assert(Value != NULL);
for (p = Value; *p != '\0' && *p != '"' && *p != ';' && *p != '#'; p++)
/* nothing */;
return (*p != '\0' || (p > Value && *(p - 1) == ' ')) ? QUOTE_ENQUOTE : QUOTE_NONE;
}
static void writesection(TCHAR *LocalBuffer, const TCHAR *Section, INI_FILETYPE *fp)
{
if (Section != NULL && _tcslen(Section) > 0) {
TCHAR *p;
LocalBuffer[0] = '[';
ini_strncpy(LocalBuffer + 1, Section, INI_BUFFERSIZE - 4, QUOTE_NONE); /* -1 for '[', -1 for ']', -2 for '\r\n' */
p = _tcschr(LocalBuffer, '\0');
assert(p != NULL);
*p++ = ']';
_tcscpy(p, INI_LINETERM); /* copy line terminator (typically "\n") */
if (fp != NULL)
(void)ini_write(LocalBuffer, fp);
}
}
static void writekey(TCHAR *LocalBuffer, const TCHAR *Key, const TCHAR *Value, INI_FILETYPE *fp)
{
TCHAR *p;
enum quote_option option = check_enquote(Value);
ini_strncpy(LocalBuffer, Key, INI_BUFFERSIZE - 3, QUOTE_NONE); /* -1 for '=', -2 for '\r\n' */
p = _tcschr(LocalBuffer, '\0');
assert(p != NULL);
*p++ = '=';
ini_strncpy(p, Value, INI_BUFFERSIZE - (p - LocalBuffer) - 2, option); /* -2 for '\r\n' */
p = _tcschr(LocalBuffer, '\0');
assert(p != NULL);
_tcscpy(p, INI_LINETERM); /* copy line terminator (typically "\n") */
if (fp != NULL)
(void)ini_write(LocalBuffer, fp);
}
static int cache_accum(const TCHAR *string, int *size, int max)
{
int len = (int)_tcslen(string);
if (*size + len >= max)
return 0;
*size += len;
return 1;
}
static int cache_flush(TCHAR *buffer, int *size,
INI_FILETYPE *rfp, INI_FILETYPE *wfp, INI_FILEPOS *mark)
{
int terminator_len = (int)_tcslen(INI_LINETERM);
int pos = 0, pos_prev = -1;
(void)ini_seek(rfp, mark);
assert(buffer != NULL);
buffer[0] = '\0';
assert(size != NULL);
assert(*size <= INI_BUFFERSIZE);
while (pos < *size && pos != pos_prev) {
pos_prev = pos; /* to guard against zero bytes in the INI file */
(void)ini_read(buffer + pos, INI_BUFFERSIZE - pos, rfp);
while (pos < *size && buffer[pos] != '\0')
pos++; /* cannot use _tcslen() because buffer may not be zero-terminated */
}
if (buffer[0] != '\0') {
assert(pos > 0 && pos <= INI_BUFFERSIZE);
if (pos == INI_BUFFERSIZE)
pos--;
buffer[pos] = '\0'; /* force zero-termination (may be left unterminated in the above while loop) */
(void)ini_write(buffer, wfp);
}
ini_tell(rfp, mark); /* update mark */
*size = 0;
/* return whether the buffer ended with a line termination */
return (pos > terminator_len) && (_tcscmp(buffer + pos - terminator_len, INI_LINETERM) == 0);
}
static int close_rename(INI_FILETYPE *rfp, INI_FILETYPE *wfp, const TCHAR *filename, TCHAR *buffer)
{
(void)ini_close(rfp);
(void)ini_close(wfp);
(void)ini_tempname(buffer, filename, INI_BUFFERSIZE);
#if defined ini_remove || defined INI_REMOVE
(void)ini_remove(filename);
#endif
(void)ini_rename(buffer, filename);
return 1;
}
/** ini_puts()
* \param Section the name of the section to write the string in
* \param Key the name of the entry to write, or NULL to erase all keys in the section
* \param Value a pointer to the buffer the string, or NULL to erase the key
* \param Filename the name and full path of the .ini file to write to
*
* \return 1 if successful, otherwise 0
*/
int ini_puts(const TCHAR *Section, const TCHAR *Key, const TCHAR *Value, const TCHAR *Filename)
{
INI_FILETYPE rfp;
INI_FILETYPE wfp;
INI_FILEPOS mark;
INI_FILEPOS head, tail;
TCHAR *sp, *ep;
TCHAR LocalBuffer[INI_BUFFERSIZE];
int len, match, flag, cachelen;
assert(Filename != NULL);
if (!ini_openread(Filename, &rfp)) {
/* If the .ini file doesn't exist, make a new file */
if (Key != NULL && Value != NULL) {
if (!ini_openwrite(Filename, &wfp))
return 0;
writesection(LocalBuffer, Section, &wfp);
writekey(LocalBuffer, Key, Value, &wfp);
(void)ini_close(&wfp);
}
return 1;
}
/* If parameters Key and Value are valid (so this is not an "erase" request)
* and the setting already exists, there are two short-cuts to avoid rewriting
* the INI file.
*/
if (Key != NULL && Value != NULL) {
match = getkeystring(&rfp, Section, Key, -1, -1, LocalBuffer, sizearray(LocalBuffer), &head);
if (match) {
/* if the current setting is identical to the one to write, there is
* nothing to do.
*/
if (_tcscmp(LocalBuffer,Value) == 0) {
(void)ini_close(&rfp);
return 1;
}
/* if the new setting has the same length as the current setting, and the
* glue file permits file read/write access, we can modify in place.
*/
#if defined ini_openrewrite || defined INI_OPENREWRITE
/* we already have the start of the (raw) line, get the end too */
ini_tell(&rfp, &tail);
/* create new buffer (without writing it to file) */
writekey(LocalBuffer, Key, Value, NULL);
if (_tcslen(LocalBuffer) == (size_t)(tail - head)) {
/* length matches, close the file & re-open for read/write, then
* write at the correct position
*/
(void)ini_close(&rfp);
if (!ini_openrewrite(Filename, &wfp))
return 0;
(void)ini_seek(&wfp, &head);
(void)ini_write(LocalBuffer, &wfp);
(void)ini_close(&wfp);
return 1;
}
#endif
}
/* key not found, or different value & length -> proceed */
} else if (Key != NULL && Value == NULL) {
/* Conversely, for a request to delete a setting; if that setting isn't
present, just return */
match = getkeystring(&rfp, Section, Key, -1, -1, LocalBuffer, sizearray(LocalBuffer), NULL);
if (!match) {
(void)ini_close(&rfp);
return 1;
}
/* key found -> proceed to delete it */
}
/* Get a temporary file name to copy to. Use the existing name, but with
* the last character set to a '~'.
*/
(void)ini_close(&rfp);
ini_tempname(LocalBuffer, Filename, INI_BUFFERSIZE);
if (!ini_openwrite(LocalBuffer, &wfp))
return 0;
/* In the case of (advisory) file locks, ini_openwrite() may have been blocked
* on the open, and after the block is lifted, the original file may have been
* renamed, which is why the original file was closed and is now reopened */
if (!ini_openread(Filename, &rfp)) {
/* If the .ini file doesn't exist any more, make a new file */
assert(Key != NULL && Value != NULL);
writesection(LocalBuffer, Section, &wfp);
writekey(LocalBuffer, Key, Value, &wfp);
(void)ini_close(&wfp);
return 1;
}
(void)ini_tell(&rfp, &mark);
cachelen = 0;
/* Move through the file one line at a time until a section is
* matched or until EOF. Copy to temp file as it is read.
*/
len = (Section != NULL) ? (int)_tcslen(Section) : 0;
if (len > 0) {
do {
if (!ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) {
/* Failed to find section, so add one to the end */
flag = cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
if (Key!=NULL && Value!=NULL) {
if (!flag)
(void)ini_write(INI_LINETERM, &wfp); /* force a new line behind the last line of the INI file */
writesection(LocalBuffer, Section, &wfp);
writekey(LocalBuffer, Key, Value, &wfp);
}
return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */
}
/* Check whether this line is a section */
sp = skipleading(LocalBuffer);
ep = _tcsrchr(sp, ']');
match = (*sp == '[' && ep != NULL);
if (match) {
/* A section was found, skip leading and trailing whitespace */
assert(sp != NULL && *sp == '[');
sp = skipleading(sp + 1);
assert(ep != NULL && *ep == ']');
ep = skiptrailing(ep, sp);
match = ((int)(ep-sp) == len && _tcsnicmp(sp, Section, len) == 0);
}
/* Copy the line from source to dest, but not if this is the section that
* we are looking for and this section must be removed
*/
if (!match || Key != NULL) {
if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) {
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE);
}
}
} while (!match);
}
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
/* when deleting a section, the section head that was just found has not been
* copied to the output file, but because this line was not "accumulated" in
* the cache, the position in the input file was reset to the point just
* before the section; this must now be skipped (again)
*/
if (Key == NULL) {
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
(void)ini_tell(&rfp, &mark);
}
/* Now that the section has been found, find the entry. Stop searching
* upon leaving the section's area. Copy the file as it is read
* and create an entry if one is not found.
*/
len = (Key != NULL) ? (int)_tcslen(Key) : 0;
for( ;; ) {
if (!ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) {
/* EOF without an entry so make one */
flag = cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
if (Key!=NULL && Value!=NULL) {
if (!flag)
(void)ini_write(INI_LINETERM, &wfp); /* force a new line behind the last line of the INI file */
writekey(LocalBuffer, Key, Value, &wfp);
}
return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */
}
sp = skipleading(LocalBuffer);
ep = _tcschr(sp, '='); /* Parse out the equal sign */
if (ep == NULL)
ep = _tcschr(sp, ':');
match = (ep != NULL && len > 0 && (int)(skiptrailing(ep,sp)-sp) == len && _tcsnicmp(sp,Key,len) == 0);
if ((Key != NULL && match) || *sp == '[')
break; /* found the key, or found a new section */
/* copy other keys in the section */
if (Key == NULL) {
(void)ini_tell(&rfp, &mark); /* we are deleting the entire section, so update the read position */
} else {
if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) {
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE);
}
}
}
/* the key was found, or we just dropped on the next section (meaning that it
* wasn't found); in both cases we need to write the key, but in the latter
* case, we also need to write the line starting the new section after writing
* the key
*/
flag = (*sp == '[');
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
if (Key != NULL && Value != NULL)
writekey(LocalBuffer, Key, Value, &wfp);
/* cache_flush() reset the "read pointer" to the start of the line with the
* previous key or the new section; read it again (because writekey() destroyed
* the buffer)
*/
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
if (flag) {
/* the new section heading needs to be copied to the output file */
cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE);
} else {
/* forget the old key line */
(void)ini_tell(&rfp, &mark);
}
/* Copy the rest of the INI file */
while (ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp)) {
if (!cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE)) {
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
(void)ini_read(LocalBuffer, INI_BUFFERSIZE, &rfp);
cache_accum(LocalBuffer, &cachelen, INI_BUFFERSIZE);
}
}
cache_flush(LocalBuffer, &cachelen, &rfp, &wfp, &mark);
return close_rename(&rfp, &wfp, Filename, LocalBuffer); /* clean up and rename */
}
/* Ansi C "itoa" based on Kernighan & Ritchie's "Ansi C" book. */
#define ABS(v) ((v) < 0 ? -(v) : (v))
static void strreverse(TCHAR *str)
{
int i, j;
for (i = 0, j = (int)_tcslen(str) - 1; i < j; i++, j--) {
TCHAR t = str[i];
str[i] = str[j];
str[j] = t;
}
}
static void long2str(long value, TCHAR *str)
{
int i = 0;
long sign = value;
/* generate digits in reverse order */
do {
int n = (int)(value % 10); /* get next lowest digit */
str[i++] = (TCHAR)(ABS(n) + '0'); /* handle case of negative digit */
} while (value /= 10); /* delete the lowest digit */
if (sign < 0)
str[i++] = '-';
str[i] = '\0';
strreverse(str);
}
/** ini_putl()
* \param Section the name of the section to write the value in
* \param Key the name of the entry to write
* \param Value the value to write
* \param Filename the name and full path of the .ini file to write to
*
* \return 1 if successful, otherwise 0
*/
int ini_putl(const TCHAR *Section, const TCHAR *Key, long Value, const TCHAR *Filename)
{
TCHAR LocalBuffer[32];
long2str(Value, LocalBuffer);
return ini_puts(Section, Key, LocalBuffer, Filename);
}
#if defined INI_REAL
/** ini_putf()
* \param Section the name of the section to write the value in
* \param Key the name of the entry to write
* \param Value the value to write
* \param Filename the name and full path of the .ini file to write to
*
* \return 1 if successful, otherwise 0
*/
int ini_putf(const TCHAR *Section, const TCHAR *Key, INI_REAL Value, const TCHAR *Filename)
{
TCHAR LocalBuffer[64];
ini_ftoa(LocalBuffer, Value);
return ini_puts(Section, Key, LocalBuffer, Filename);
}
#endif /* INI_REAL */
#endif /* !INI_READONLY */

166
lib/minIni/minIni.h Normal file
View File

@ -0,0 +1,166 @@
/* minIni - Multi-Platform INI file parser, suitable for embedded systems
*
* Copyright (c) CompuPhase, 2008-2021
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Version: $Id: minIni.h 53 2015-01-18 13:35:11Z thiadmer.riemersma@gmail.com $
*/
#ifndef MININI_H
#define MININI_H
#include "minGlue.h"
#if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined INI_ANSIONLY
#include <tchar.h>
#define mTCHAR TCHAR
#else
/* force TCHAR to be "char", but only for minIni */
#define mTCHAR char
#endif
#if !defined INI_BUFFERSIZE
#define INI_BUFFERSIZE 512
#endif
#if defined __cplusplus
extern "C" {
#endif
int ini_getbool(const mTCHAR *Section, const mTCHAR *Key, int DefValue, const mTCHAR *Filename);
long ini_getl(const mTCHAR *Section, const mTCHAR *Key, long DefValue, const mTCHAR *Filename);
int ini_gets(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *DefValue, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
int ini_getsection(int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
int ini_getkey(const mTCHAR *Section, int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
int ini_hassection(const mTCHAR *Section, const mTCHAR *Filename);
int ini_haskey(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Filename);
#if defined INI_REAL
INI_REAL ini_getf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL DefValue, const mTCHAR *Filename);
#endif
#if !defined INI_READONLY
int ini_putl(const mTCHAR *Section, const mTCHAR *Key, long Value, const mTCHAR *Filename);
int ini_puts(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const mTCHAR *Filename);
#if defined INI_REAL
int ini_putf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL Value, const mTCHAR *Filename);
#endif
#endif /* INI_READONLY */
#if !defined INI_NOBROWSE
typedef int (*INI_CALLBACK)(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData);
int ini_browse(INI_CALLBACK Callback, void *UserData, const mTCHAR *Filename);
#endif /* INI_NOBROWSE */
#if defined __cplusplus
}
#endif
#if defined __cplusplus
#if defined __WXWINDOWS__
#include "wxMinIni.h"
#else
#include <string>
/* The C++ class in minIni.h was contributed by Steven Van Ingelgem. */
class minIni
{
public:
minIni(const std::string& filename) : iniFilename(filename)
{ }
bool getbool(const std::string& Section, const std::string& Key, bool DefValue=false) const
{ return ini_getbool(Section.c_str(), Key.c_str(), int(DefValue), iniFilename.c_str()) != 0; }
long getl(const std::string& Section, const std::string& Key, long DefValue=0) const
{ return ini_getl(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); }
int geti(const std::string& Section, const std::string& Key, int DefValue=0) const
{ return static_cast<int>(this->getl(Section, Key, long(DefValue))); }
std::string gets(const std::string& Section, const std::string& Key, const std::string& DefValue="") const
{
char buffer[INI_BUFFERSIZE];
ini_gets(Section.c_str(), Key.c_str(), DefValue.c_str(), buffer, INI_BUFFERSIZE, iniFilename.c_str());
return buffer;
}
std::string getsection(int idx) const
{
char buffer[INI_BUFFERSIZE];
ini_getsection(idx, buffer, INI_BUFFERSIZE, iniFilename.c_str());
return buffer;
}
std::string getkey(const std::string& Section, int idx) const
{
char buffer[INI_BUFFERSIZE];
ini_getkey(Section.c_str(), idx, buffer, INI_BUFFERSIZE, iniFilename.c_str());
return buffer;
}
bool hassection(const std::string& Section) const
{ return ini_hassection(Section.c_str(), iniFilename.c_str()) != 0; }
bool haskey(const std::string& Section, const std::string& Key) const
{ return ini_haskey(Section.c_str(), Key.c_str(), iniFilename.c_str()) != 0; }
#if defined INI_REAL
INI_REAL getf(const std::string& Section, const std::string& Key, INI_REAL DefValue=0) const
{ return ini_getf(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); }
#endif
#if ! defined INI_READONLY
bool put(const std::string& Section, const std::string& Key, long Value)
{ return ini_putl(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; }
bool put(const std::string& Section, const std::string& Key, int Value)
{ return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; }
bool put(const std::string& Section, const std::string& Key, bool Value)
{ return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; }
bool put(const std::string& Section, const std::string& Key, const std::string& Value)
{ return ini_puts(Section.c_str(), Key.c_str(), Value.c_str(), iniFilename.c_str()) != 0; }
bool put(const std::string& Section, const std::string& Key, const char* Value)
{ return ini_puts(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; }
#if defined INI_REAL
bool put(const std::string& Section, const std::string& Key, INI_REAL Value)
{ return ini_putf(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; }
#endif
bool del(const std::string& Section, const std::string& Key)
{ return ini_puts(Section.c_str(), Key.c_str(), 0, iniFilename.c_str()) != 0; }
bool del(const std::string& Section)
{ return ini_puts(Section.c_str(), 0, 0, iniFilename.c_str()) != 0; }
#endif
#if !defined INI_NOBROWSE
bool browse(INI_CALLBACK Callback, void *UserData) const
{ return ini_browse(Callback, UserData, iniFilename.c_str()) != 0; }
#endif
private:
std::string iniFilename;
};
#endif /* __WXWINDOWS__ */
#endif /* __cplusplus */
#endif /* MININI_H */

View File

@ -1,31 +1,88 @@
; PlatformIO Project Configuration File https://docs.platformio.org/page/projectconf.html
[env:genericSTM32F103C8]
[platformio]
default_envs = STM32F1
[env]
framework = arduino
lib_deps =
SdFat=https://github.com/BlueSCSI/SdFat#2.2.0-gpt
upload_protocol = stlink
; Different gcc versions produce much different binaries in terms of speed.
platform_packages = platformio/toolchain-gccarmnoneeabi@1.90301.200702
build_flags =
-DARDUINO_LIB_DISCOVERY_PHASE
-DARDUINO_ARCH_STM32
-DDEBUG_LEVEL=DEBUG_NONE
-O2
-D BUILD_TAGS="\"\""
build_unflags =
-Os
-DARDUINO_ARCH_STM32F1
upload_flags = -c set CPUTAPID 0
[env:STM32F1]
platform = ststm32
board = genericSTM32F103C8
board_build.mcu = stm32f103c8t6
board_build.core = maple
[env:STM32F1-XCVR]
extends = env:STM32F1
build_flags = ${env.build_flags}
-DXCVR
-D BUILD_TAGS="\"-XCVR\""
[env:STM32F1-USB-128MHz]
# Max overclock for STM32
# Can use for APM32F1 as well.
extends = env:STM32F1-USB
board_build.f_cpu = 128000000L
build_flags = ${env.build_flags}
-D BUILD_TAGS="\"-USB-128MHz\""
[env:STM32F1-USB-96MHz]
# Slight overclock for STM32
# Use for APM32F1's - it's default clock is 96MHz and runs unstable at 72MHz(STM32F1's default)
extends = env:STM32F1-USB
# Explicilty define the multiplier as maple only handles a few cases.
build_flags = ${env.build_flags}
-D BUILD_TAGS="\"-USB-96MHz\""
-D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
-D USBCON
-D USBD_VID=0x0483
-D USB_MANUFACTURER="Unknown"
-D USB_PRODUCT="\"BLUEPILL_F103C8\""
-D HAL_PCD_MODULE_ENABLED
-DBOARD_RCC_PLLMUL=RCC_PLLMUL_12 #96000000L
# TODO: Find out why USB build flags get trampled when extending an extended env.
[env:STM32F1-USB]
platform = ststm32
board = genericSTM32F103C8
board_build.mcu = stm32f103c8t6
board_build.core = maple
framework = arduino
lib_deps =
greiman/SdFat @ ^2.0.6
upload_protocol = stlink
greiman/SdFat @ 2.2.0
upload_protocol = dfu
; Different gcc versions produce much different binaries in terms of speed.
platform_packages = platformio/toolchain-gccarmnoneeabi@1.90301.200702
build_unflags =
-Os
-DARDUINO_ARCH_STM32F1
build_flags =
-w
-DARDUINO_GENERIC_STM32F103C
build_flags =
-D BUILD_TAGS="\"-USB\""
-D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
-D USBCON
-D USBD_VID=0x0483
-D USB_MANUFACTURER="Unknown"
-D USB_PRODUCT="\"BLUEPILL_F103C8\""
-D HAL_PCD_MODULE_ENABLED
-DARDUINO_LIB_DISCOVERY_PHASE
-DARDUINO=10813
-DARDUINO_ARCH_STM32
-DDEBUG_LEVEL=DEBUG_NONE
-O2
; Work around for clones.
; https://community.platformio.org/t/cannot-upload-to-stm32-bluepill-board-over-stlink-v2/3492/25
build_unflags =
-Os
-DARDUINO_ARCH_STM32F1
upload_flags = -c set CPUTAPID 0
; [env:debug]

File diff suppressed because it is too large Load Diff

371
src/BlueSCSI.h Normal file
View File

@ -0,0 +1,371 @@
#ifndef __BLUESCSI_H__
#define __BLUESCSI_H__
#include <Arduino.h> // For Platform.IO
#include <SdFat.h>
// SCSI config
#define MAX_SCSIID 7 // Maximum number of supported SCSI-IDs (The minimum is 0)
#define MAX_SCSILUN 8 // Maximum number of LUNs supported (The minimum is 0)
#define NUM_SCSIID MAX_SCSIID // Number of enabled SCSI IDs
#define NUM_SCSILUN 1 // Number of enabled LUNs
#define READ_PARITY_CHECK 0 // Perform read parity check (unverified)
#define DEFAULT_SCSI_ID 1
#define DEFAULT_SCSI_LUN 0
#define SCSI_BUF_SIZE 512 // Size of the SCSI Buffer
#define HDD_BLOCK_SIZE 512
#define OPTICAL_BLOCK_SIZE 2048
#define BLUESCSI_INI "bluescsi.ini"
#define SCSI_VENDOR_LENGTH 8
#define SCSI_PRODUCT_LENGTH 16
#define SCSI_REVISION_LENGTH 4
// HDD format
#define MAX_BLOCKSIZE 4096 // Maximum BLOCK size
// SDFAT
#define SD1_CONFIG SdSpiConfig(PA4, DEDICATED_SPI, SD_SCK_MHZ(SPI_FULL_SPEED), &SPI)
// LED ERRORS
#define ERROR_FALSE_INIT 3
#define ERROR_NO_SDCARD 5
enum SCSI_DEVICE_TYPE
{
SCSI_DEVICE_HDD,
SCSI_DEVICE_OPTICAL,
};
#define SCSI_DEVICE_FLAG_OPTICAL_MODE2 0x1
#define SCSI_DEVICE_FLAG_OPTICAL_RAW 0x2
#define SET_DEVICE_FLAG(var, flag) (var |= flag)
#define UNSET_DEVICE_FLAG(var, flag) (var &= ~flag)
#define IS_DEVICE_FLAG_SET(var, flag) ((var & flag) == flag)
#define IS_RAW(var) IS_DEVICE_FLAG_SET(var, SCSI_DEVICE_FLAG_OPTICAL_RAW)
#define IS_MODE2(var) IS_DEVICE_FLAG_SET(var, SCSI_DEVICE_FLAG_OPTICAL_MODE2)
#define INT_TO_CHAR(var) var+'0'
#define CHAR_TO_INT(var) var-'0'
#define CDROM_RAW_SECTORSIZE 2352
#define CDROM_COMMON_SECTORSIZE 2048
#define MAX_SCSI_COMMAND 0xff
#define SCSI_COMMAND_HANDLER(x) static byte x(SCSI_DEVICE *dev, const byte *cdb)
#if DEBUG
#define LOG(XX) Serial.print(XX)
#define LOGHEX(XX) Serial.print(XX, HEX)
#define LOGN(XX) Serial.println(XX)
#define LOGHEXN(XX) Serial.println(XX, HEX)
#else
#define LOG(XX) //Serial.print(XX)
#define LOGHEX(XX) //Serial.print(XX, HEX)
#define LOGN(XX) //Serial.println(XX)
#define LOGHEXN(XX) //Serial.println(XX, HEX)
#endif
#define active 1
#define inactive 0
#define high 0
#define low 1
#define isHigh(XX) ((XX) == high)
#define isLow(XX) ((XX) != high)
#define gpio_mode(pin,val) gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val);
#define gpio_write(pin,val) gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val)
#define gpio_read(pin) gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit)
//#define DB0 PB8 // SCSI:DB0
//#define DB1 PB9 // SCSI:DB1
//#define DB2 PB10 // SCSI:DB2
//#define DB3 PB11 // SCSI:DB3
//#define DB4 PB12 // SCSI:DB4
//#define DB5 PB13 // SCSI:DB5
//#define DB6 PB14 // SCSI:DB6
//#define DB7 PB15 // SCSI:DB7
//#define DBP PB0 // SCSI:DBP
#define ATN PA8 // SCSI:ATN
#define BSY PA9 // SCSI:BSY
#define ACK PA10 // SCSI:ACK
#define RST PA15 // SCSI:RST
#define MSG PB3 // SCSI:MSG
#define SEL PB4 // SCSI:SEL
#define CD PB5 // SCSI:C/D
#define REQ PB6 // SCSI:REQ
#define IO PB7 // SCSI:I/O
#define SD_CS PA4 // SDCARD:CS
// Image Set Selector
#ifdef XCVR
#define IMAGE_SELECT1 PC14
#define IMAGE_SELECT2 PC15
#else
#define IMAGE_SELECT1 PA1
#define IMAGE_SELECT2 PB1
#endif
// GPIO register port
#define PAREG GPIOA->regs
#define PBREG GPIOB->regs
#define PCREG GPIOC->regs
// Virtual pin (Arduio compatibility is slow, so make it MCU-dependent)
#define PA(BIT) (BIT)
#define PB(BIT) (BIT+16)
#define PC(BIT) (BIT+32)
// Virtual pin decoding
#define GPIOREG(VPIN) ((VPIN)>=16?((VPIN)>=32?PCREG:PBREG):PAREG)
#define BITMASK(VPIN) (1<<((VPIN)&15))
// Built-in LED
#define LED PC13
#define vLED PC(13)
#define LED_MODE GPIO_OUTPUT_OD
// External LED
#define LED2 PA0
#define vLED2 PA(0)
#define LED2_MODE GPIO_OUTPUT_PP
// LED control
#define LED_ON() GPIOREG(vLED)->BSRR = BITMASK(vLED) << (LED_MODE == GPIO_OUTPUT_PP ? 0 : 16); GPIOREG(vLED2)->BSRR = BITMASK(vLED2) << (LED2_MODE == GPIO_OUTPUT_PP ? 0 : 16);
#define LED_OFF() GPIOREG(vLED)->BSRR = BITMASK(vLED) << (LED_MODE == GPIO_OUTPUT_PP ? 16 : 0); GPIOREG(vLED2)->BSRR = BITMASK(vLED2) << (LED2_MODE == GPIO_OUTPUT_PP ? 16 : 0);
#define vATN PA(8) // SCSI:ATN
#define vBSY PA(9) // SCSI:BSY
#define vACK PA(10) // SCSI:ACK
#define vRST PA(15) // SCSI:RST
#define vMSG PB(3) // SCSI:MSG
#define vSEL PB(4) // SCSI:SEL
#define vCD PB(5) // SCSI:C/D
#define vREQ PB(6) // SCSI:REQ
#define vIO PB(7) // SCSI:I/O
#define vSD_CS PA(4) // SDCARD:CS
// SCSI output pin control: opendrain active LOW (direct pin drive)
#define SCSI_OUT(VPIN,ACTIVE) { GPIOREG(VPIN)->BSRR = BITMASK(VPIN)<<((ACTIVE)?16:0); }
// SCSI input pin check (inactive=0,active=1)
#define SCSI_IN(VPIN) ((~GPIOREG(VPIN)->IDR>>(VPIN&15))&1)
#define NOP(x) for(unsigned _nopcount = x; _nopcount; _nopcount--) { asm("NOP"); }
/* SCSI Timing delays */
// Due to limitations in timing granularity all of these are "very" rough estimates
#define SCSI_BUS_SETTLE() NOP(30); // spec 400ns ours ~420us
#define SCSI_DATA_RELEASE() NOP(30); // spec 400ns ours ~420us
#define SCSI_HOLD_TIME() asm("NOP"); asm("NOP"); asm("NOP"); // spec 45ns ours ~42ns
#define SCSI_DESKEW() // asm("NOP"); asm("NOP"); asm("NOP"); // spec 45ns ours ~42ns
#define SCSI_CABLE_SKEW() // asm("NOP"); // spec 10ns ours ~14ns
#define SCSI_RESET_HOLD() asm("NOP"); asm("NOP"); // spec 25ns ours ~28ns
#define SCSI_DISCONNECTION_DELAY() NOP(15); // spec 200ns ours ~210ns
/* SCSI phases
+=============-===============-==================================-============+
| Signal | Phase name | Direction of transfer | Comment |
|-------------| | | |
| MSG|C/D|I/O | | | |
|----+---+----+---------------+----------------------------------+------------|
| 0 | 0 | 0 | DATA OUT | Initiator to target \ | Data |
| 0 | 0 | 1 | DATA IN | Initiator from target / | phase |
| 0 | 1 | 0 | COMMAND | Initiator to target | |
| 0 | 1 | 1 | STATUS | Initiator from target | |
| 1 | 0 | 0 | * | | |
| 1 | 0 | 1 | * | | |
| 1 | 1 | 0 | MESSAGE OUT | Initiator to target \ | Message |
| 1 | 1 | 1 | MESSAGE IN | Initiator from target / | phase |
|-----------------------------------------------------------------------------|
| Key: 0 = False, 1 = True, * = Reserved for future standardization |
+=============================================================================+
*/
// SCSI phase change as single write to port B
#define SCSIPHASEMASK(MSGACTIVE, CDACTIVE, IOACTIVE) ((BITMASK(vMSG)<<((MSGACTIVE)?16:0)) | (BITMASK(vCD)<<((CDACTIVE)?16:0)) | (BITMASK(vIO)<<((IOACTIVE)?16:0)))
#define SCSI_PHASE_DATAOUT SCSIPHASEMASK(inactive, inactive, inactive)
#define SCSI_PHASE_DATAIN SCSIPHASEMASK(inactive, inactive, active)
#define SCSI_PHASE_COMMAND SCSIPHASEMASK(inactive, active, inactive)
#define SCSI_PHASE_STATUS SCSIPHASEMASK(inactive, active, active)
#define SCSI_PHASE_MESSAGEOUT SCSIPHASEMASK(active, active, inactive)
#define SCSI_PHASE_MESSAGEIN SCSIPHASEMASK(active, active, active)
#define SCSI_PHASE_CHANGE(MASK) { PBREG->BSRR = (MASK); }
#ifdef XCVR
#define TR_TARGET PA1 // Target Transceiver Control Pin
#define TR_DBP PA2 // Data Pins Transceiver Control Pin
#define TR_INITIATOR PA3 // Initiator Transciever Control Pin
#define vTR_TARGET PA(1) // Target Transceiver Control Pin
#define vTR_DBP PA(2) // Data Pins Transceiver Control Pin
#define vTR_INITIATOR PA(3) // Initiator Transciever Control Pin
#define TR_INPUT 1
#define TR_OUTPUT 0
// Transceiver control definitions
#define TRANSCEIVER_IO_SET(VPIN,TR_INPUT) { GPIOREG(VPIN)->BSRR = BITMASK(VPIN) << ((TR_INPUT) ? 16 : 0); }
// Turn on the output only for BSY
#define SCSI_BSY_ACTIVE() { gpio_mode(BSY, GPIO_OUTPUT_PP); SCSI_OUT(vBSY, active) }
#define SCSI_TARGET_ACTIVE() { gpio_mode(REQ, GPIO_OUTPUT_PP); gpio_mode(MSG, GPIO_OUTPUT_PP); gpio_mode(CD, GPIO_OUTPUT_PP); gpio_mode(IO, GPIO_OUTPUT_PP); gpio_mode(BSY, GPIO_OUTPUT_PP); TRANSCEIVER_IO_SET(vTR_TARGET,TR_OUTPUT);}
// BSY,REQ,MSG,CD,IO Turn off output, BSY is the last input
#define SCSI_TARGET_INACTIVE() { gpio_mode(REQ, GPIO_INPUT_FLOATING); gpio_mode(MSG, GPIO_INPUT_FLOATING); gpio_mode(CD, GPIO_INPUT_FLOATING); gpio_mode(IO, GPIO_INPUT_FLOATING); gpio_mode(BSY, GPIO_INPUT_FLOATING); TRANSCEIVER_IO_SET(vTR_TARGET,TR_INPUT); }
#define DB_MODE_OUT 1 // push-pull mode
#define DB_MODE_IN 4 // floating inputs
#else
// GPIO mode
// IN , FLOAT : 4
// IN , PU/PD : 8
// OUT, PUSH/PULL : 3
// OUT, OD : 1
#define DB_MODE_OUT 3
//#define DB_MODE_OUT 7
#define DB_MODE_IN 8
// Turn on the output only for BSY
#define SCSI_BSY_ACTIVE() { gpio_mode(BSY, GPIO_OUTPUT_OD); SCSI_OUT(vBSY, active) }
// BSY,REQ,MSG,CD,IO Turn on the output (no change required for OD)
#define SCSI_TARGET_ACTIVE() { if (DB_MODE_OUT != 7) gpio_mode(REQ, GPIO_OUTPUT_PP); }
// BSY,REQ,MSG,CD,IO Turn off output, BSY is the last input
#define SCSI_TARGET_INACTIVE() { if (DB_MODE_OUT == 7) SCSI_OUT(vREQ,inactive) else { if (DB_MODE_IN == 8) gpio_mode(REQ, GPIO_INPUT_PU) else gpio_mode(REQ, GPIO_INPUT_FLOATING)} PBREG->BSRR = 0b000000000000000011101000; SCSI_OUT(vBSY,inactive); gpio_mode(BSY, GPIO_INPUT_PU); }
#endif
// Put DB and DP in output mode
#define SCSI_DB_OUTPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_OUT; PBREG->CRH = 0x11111111*DB_MODE_OUT; }
// Put DB and DP in input mode
#define SCSI_DB_INPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_IN ; PBREG->CRH = (uint32_t)0x11111111*DB_MODE_IN; }
// HDDiamge file
#define HDIMG_ID_POS 2 // Position to embed ID number
#define HDIMG_LUN_POS 3 // Position to embed LUN numbers
#define HDIMG_BLK_POS 5 // Position to embed block size numbers
#define MAX_FILE_PATH 64 // Maximum file name length
#define MAX_MAC_PATH 32 // Maximum file name length on vintage macs
#define MAC_BLK_SIZE 4096
/*
* Data byte to BSRR register setting value and parity table
*/
// Parity bit generation
//#define PTY(V) (1^((V)^((V)>>1)^((V)>>2)^((V)>>3)^((V)>>4)^((V)>>5)^((V)>>6)^((V)>>7))&1)
#define PTY(n) ((1 ^ (n) ^ ((n)>>1) ^ ((n)>>2) ^ ((n)>>3) ^ ((n)>>4) ^ ((n)>>5) ^ ((n)>>6) ^ ((n)>>7)) & 1)
// Data byte to BSRR register setting value conversion table
// BSRR[31:24] = DB[7:0]
// BSRR[ 16] = PTY(DB)
// BSRR[15: 8] = ~DB[7:0]
// BSRR[ 0] = ~PTY(DB)
// Set DBP, set REQ = inactive
#define DBP(D) ((((((uint32_t)(D)<<8)|PTY(D))*0x00010001)^0x0000ff01)|BITMASK(vREQ))
//#define DBP(D) ((((((uint32_t)(D)<<8)|PTY(D))*0x00010001)^0x0000ff01))
//#define DBP8(D) DBP(D),DBP(D+1),DBP(D+2),DBP(D+3),DBP(D+4),DBP(D+5),DBP(D+6),DBP(D+7)
//#define DBP32(D) DBP8(D),DBP8(D+8),DBP8(D+16),DBP8(D+24)
// BSRR register control value that simultaneously performs DB set, DP set, and REQ = H (inactrive)
uint32_t db_bsrr[256];
// Parity bit acquisition
#define PARITY(DB) (db_bsrr[DB]&1)
// Macro cleaning
//#undef DBP32
//#undef DBP8
//#undef DBP
//#undef PTY
// #define GET_CDB6_LBA(x) ((x[2] & 01f) << 16) | (x[3] << 8) | x[4]
#define READ_DATA_BUS() (byte)((~(uint32_t)GPIOB->regs->IDR)>>8)
typedef struct _SCSI_INQUIRY_DATA
{
union
{
struct {
// bitfields are in REVERSE order for ARM
// byte 0
byte peripheral_device_type:5;
byte peripheral_qualifier:3;
// byte 1
byte reserved_byte2:7;
byte rmb:1;
// byte 2
byte ansi_version:3;
byte always_zero_byte3:5;
// byte 3
byte response_format:4;
byte reserved_byte4:2;
byte tiop:1;
byte always_zero_byte4:1;
// byte 4
byte additional_length;
// byte 5-6
byte reserved_byte5;
byte reserved_byte6;
// byte 7
byte sync:1;
byte always_zero_byte7_more:4;
byte always_zero_byte7:3;
// byte 8-15
char vendor[8];
// byte 16-31
char product[16];
// byte 32-35
char revision[4];
// byte 36
byte release;
// 37-46
char revision_date[10];
};
// raw bytes
byte raw[64];
};
} SCSI_INQUIRY_DATA;
// HDD image
typedef __attribute__((aligned(4))) struct _SCSI_DEVICE
{
FsFile m_file; // File object
uint64_t m_fileSize; // File size
uint16_t m_blocksize; // SCSI BLOCK size
uint16_t m_rawblocksize; // OPTICAL raw sector size
uint8_t m_type; // SCSI device type
uint32_t m_blockcount; // blockcount
SCSI_INQUIRY_DATA inquiry_block; // SCSI information
uint8_t m_senseKey; // Sense key
uint16_t m_additional_sense_code; // ASC/ASCQ
uint8_t m_sector_offset; // optical sector offset for missing sync header
uint8_t flags; // various device flags
} SCSI_DEVICE;
static byte cdb_len_lookup[] = {
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
16,16,16,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,10,10,10,10,10
};
#endif

93
src/scsi_cmds.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef __SCSI_CMDS_H__
#define __SCSI_CMDS_H__
// defines for SCSI commands
#define SCSI_TEST_UNIT_READY 0
#define SCSI_REZERO_UNIT 0x1
#define SCSI_REQUEST_SENSE 0x3
#define SCSI_FORMAT_UNIT4 0x4
#define SCSI_FORMAT_UNIT6 0x6
#define SCSI_REASSIGN_BLOCKS 0x7
#define SCSI_READ6 0x8
#define SCSI_WRITE6 0xA
#define SCSI_SEEK6 0xB
#define SCSI_INQUIRY 0x12
#define SCSI_MODE_SELECT6 0x15
#define SCSI_RESERVE 0x16
#define SCSI_RELEASE 0x17
#define SCSI_COPY 0x18
#define SCSI_MODE_SENSE6 0x1A
#define SCSI_START_STOP_UNIT 0x1B
#define SCSI_RECV_DIAG_RESULTS 0x1C
#define SCSI_SEND_DIAG 0x1D
#define SCSI_PREVENT_ALLOW_REMOVAL 0x1E
#define SCSI_ICD_EXTENDED_CMD 0x1F
#define SCSI_READ_CAPACITY 0x25
#define SCSI_READ10 0x28
#define SCSI_WRITE10 0x2A
#define SCSI_SEEK10 0x2B
#define SCSI_WRITE_AND_VERIFY 0x2E
#define SCSI_VERIFY10 0x2F
#define SCSI_SEARCH_DATA_HIGH 0x30
#define SCSI_SEARCH_DATA_EQUAL 0x31
#define SCSI_SEARCH_DATA_LOW 0x32
#define SCSI_SET_LIMITS 0x33
#define SCSI_PREFETCH 0x34
#define SCSI_SYNCHRONIZE_CACHE 0x35
#define SCSI_LOCK_UNLOCK_CACHE 0x36
#define SCSI_READ_DEFECT_DATA 0x37
#define SCSI_COMPARE 0x39
#define SCSI_COPY_AND_VERIFY 0x3A
#define SCSI_WRITE_BUFFER 0x3B
#define SCSI_READ_BUFFER 0x3C
#define SCSI_READ_LONG 0x3E
#define SCSI_WRITE_LONG 0x3F
#define SCSI_CHANGE_DEFINITION 0x40
#define SCSI_WRITE_SAME 0x41
#define SCSI_LOG_SELECT 0x4C
#define SCSI_LOG_SENSE 0x4D
#define SCSI_MODE_SELECT10 0x55
#define SCSI_MODE_SENSE10 0x5A
#define SCSI_READ12 0xA8
#define SCSI_VERIFY12 0xAF
#define BLUESCSI_LIST_FILES 0xD0
#define BLUESCSI_GET_FILE 0xD1
#define BLUESCSI_COUNT_FILES 0xD2
#define BLUESCSI_SEND_PREP 0xD3
#define BLUESCSI_SEND 0xD4
#define BLUESCSI_SEND_END 0xD5
#define SCSI_TOC_LENGTH 20 // length for default CDROM TOC
// SCSI CDROM commands
#define SCSI_AUDIO_SCAN1 0xBA
#define SCSI_AUDIO_SCAN2 0xCD
#define SCSI_PAUSE_RESUME 0x4B
#define SCSI_PLAY_AUDIO10 0x45
#define SCSI_PLAY_AUDIO12 0xA5
#define SCSI_PLAY_AUDIO_MSF 0x47
#define SCSI_PLAY_AUDIO_TRACK_IDX 0x48
#define SCSI_PLAY_TRACK_RELATIVE10 0x49
#define SCSI_PLAY_TRACK_RELATIVE12 0xA9
#define SCSI_READ_CD 0xBE
#define SCSI_READ_CD_DD 0xD8
#define SCSI_READ_CD_MSF 0xB9
#define SCSI_READ_CDDA_MSF 0xD9
#define SCSI_READ_CDXA 0xDB
#define SCSI_READ_ALL_SUBCODE 0xDF
#define SCSI_READ_HEADER 0x44
#define SCSI_READ_SUBCHANNEL 0x42
#define SCSI_READ_TOC 0x43
#define SCSI_READ_DISC_INFORMATION 0x51
#define SCSI_READ_DVD_STRUCTURE 0xAD
#define SCSI_SET_CDROM_SPEED1 0xBB
#define SCSI_SET_CDROM_SPEED2 0xDA
#define SCSI_STOP_PLAY_SCAN 0x4E
#define SCSI_READ_CDP 0xE4
#define SCSI_READ_DRIVE_STATUS 0xE0
#define SCSI_WRITE_CDP 0xE3
#endif // __SCSI_CMDS_H__

9
src/scsi_mode.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef __SCSI_MODE_H__
#define __SCSI_MODE_H__
#define MODE_COMBINED_HEADER_DATA 0x00
#define MODE_NOT_SUPPORTED 0x01
#define MODE_DATA 0x02
#define MODE_DESCRIPTOR 0x03
#endif

55
src/scsi_sense.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef __SCSI_SENSE_H__
#define __SCSI_SENSE_H__
#define SCSI_SENSE_NO_SENSE 0
#define SCSI_SENSE_RECOVERED_ERROR 0x1
#define SCSI_SENSE_NOT_READY 0x2
#define SCSI_SENSE_MEDUIM_ERROR 0x3
#define SCSI_SENSE_HARDWARE_ERROR 0x4
#define SCSI_SENSE_ILLEGAL_REQUEST 0x5
#define SCSI_SENSE_UNIT_ATTENTION 0x6
#define SCSI_SENSE_DATA_PROTECT 0x7
#define SCSI_SENSE_BLANK_CHECK 0x8
#define SCSI_SENSE_VENDOR_SPECIFIC 0x9
#define SCSI_SENSE_COPY_ABORTED 0xa
#define SCSI_SENSE_ABORTED_COMMAND 0xb
#define SCSI_SENSE_EQUAL 0xc
#define SCSI_SENSE_VOLUME_OVERFLOW 0xd
#define SCSI_SENSE_MISCOMPARE 0xe
#define SCSI_SENSE_RESERVED 0xf
#define SCSI_ASC_INVALID_OPERATION_CODE 0x2000
#define SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x2100
#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x2400
#define SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED 0x2500
#define SCSI_ASC_INVALID_FIELD_PARAMETER_LIST 0x2600
#define SCSI_ASC_WRITE_PROTECTED 0x2700
#define SCSI_ASC_CANNOT_READ_MEDIUM_UNKNOWN_FORMAT 0x3001
#define SCSI_ASC_CANNOT_READ_MEDIUM_INCOMPATIBLE_FORMAT 0x3002
#define SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x3900
#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A00
#define SCSI_ASC_LUN_NOT_READY_MANUAL_INTERVENTION_REQUIRED 0x0403
// OpenRetroSCSI Vendor Sense
#define OPEN_RETRO_SCSI_TOO_MANY_FILES 0x0001
// SCSI mode page codes
#define SCSI_SENSE_MODE_VENDOR 0x00
#define SCSI_SENSE_MODE_READ_WRITE_ERROR_RECOVERY 0x01
#define SCSI_SENSE_MODE_DISCONNECT_RECONNECT 0x02
#define SCSI_SENSE_MODE_FORMAT_DEVICE 0x03
#define SCSI_SENSE_MODE_DISK_GEOMETRY 0x04
#define SCSI_SENSE_MODE_FLEXABLE_GEOMETRY 0x05
#define SCSI_SENSE_MODE_CACHING 0x08
#define SCSI_SENSE_MODE_CDROM 0x0D
#define SCSI_SENSE_MODE_CDROM_AUDIO_CONTROL 0x0E
#define SCSI_SENSE_MODE_VENDOR_APPLE 0x30
#define SCSI_SENSE_MODE_VENDOR_BLUESCSI 0x31 // Lookup range for vndr
#define SCSI_SENSE_MODE_ALL 0x3F
#endif

14
src/scsi_status.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef __SCSI_STATUS_H__
#define __SCSI_STATUS_H__
#define SCSI_STATUS_GOOD 0
#define SCSI_STATUS_CHECK_CONDITION 0x2
#define SCSI_STATUS_CONDITION_MET 0x4
#define SCSI_STATUS_BUSY 0x8
#define SCSI_STATUS_INTERMEDIATE 0x16
#define SCSI_STATUS_INTERMEDIATE_CONDITION_MET 0x20
#define SCSI_STATUS_RESERVATION_CONFLICT 0x24
#define SCSI_STATUS_COMMAND_TERMINATED 0x34
#define SCSI_STATUS_QUEUE_FULL 0x40
#endif