diff --git a/lib/SCSI2SD/include/scsi2sd.h b/lib/SCSI2SD/include/scsi2sd.h index 0c886b986..4f24eeb9e 100755 --- a/lib/SCSI2SD/include/scsi2sd.h +++ b/lib/SCSI2SD/include/scsi2sd.h @@ -76,6 +76,7 @@ typedef enum S2S_CFG_SEQUENTIAL, S2S_CFG_NETWORK, S2S_CFG_ZIP100, + S2S_CFG_AMIGAWIFI, } S2S_CFG_TYPE; typedef enum diff --git a/lib/SCSI2SD/src/firmware/AmigaWIFI/AmigaWIFI.c b/lib/SCSI2SD/src/firmware/AmigaWIFI/AmigaWIFI.c new file mode 100644 index 000000000..57be2a1b2 --- /dev/null +++ b/lib/SCSI2SD/src/firmware/AmigaWIFI/AmigaWIFI.c @@ -0,0 +1,479 @@ +/* + * AmigaWIFI Module, based on the work by joshua stein Copyright (c) 2023 + * Copyright (C) 2026 RobSmithDev + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef BLUESCSI_NETWORK +#include + +#include "scsi.h" +#include "scsi2sd_time.h" +#include "scsiPhy.h" +#include "config.h" +#include "network.h" +#include "AmigaWIFI.h" + +// Share with the original network code +extern bool scsiNetworkEnabled; +extern struct scsiNetworkPacketQueue scsiNetworkInboundQueue; + +#define AMIGASCSI_PATCH_24BYTE_BLOCKSIZE 0xA8 // In this mode, data written is rounded up to the nearest 24-byte boundary +#define AMIGASCSI_PATCH_SINGLEWRITE_ONLY 0xA9 // In this mode, data written is always ONLY as one single write command +#define AMIGASCSI_BATCHMODE 0x40 // Enable batch mode + +#define SCSI_CMD_READ 0x08 +#define SCSI_CMD_WRITE 0x0A +#define SCSI_CMD_ADDMULTOCAST 0x0D +#define SCSI_CMD_TOGGLEINTERFACE 0x0E +#define SCSI_CMD_MODESENSE 0x1A +#define SCSI_CMD_WIFI 0x1C +#define SCSI_NETWORK_WIFI_CMD_SCAN 0x01 // cdb[2] +#define SCSI_NETWORK_WIFI_CMD_COMPLETE 0x02 +#define SCSI_NETWORK_WIFI_CMD_SCAN_RESULTS 0x03 +#define SCSI_NETWORK_WIFI_CMD_INFO 0x04 +#define SCSI_NETWORK_WIFI_CMD_JOIN 0x05 +#define SCSI_NETWORK_WIFI_CMD_ALTREAD 0x08 +#define SCSI_NETWORK_WIFI_CMD_GETMACADDRESS 0x09 +#define SCSI_NETWORK_WIFI_CMD_ALTWRITE 0x0A +#define SCSI_NETWORK_WIFI_CMD_AMIGANET_INFO 0x0B + +// Special command to fetch info about the config + +int amigaWifiCommand() +{ + int handled = 1; + int parityError = 0; + long psize; + uint32_t size; + uint8_t command = scsiDev.cdb[0]; + + // Rather than duplicating code, this just diverts a 'fake' read request to make the gvpscsi.device happy on the Amiga + if ((scsiDev.cdb[0] == SCSI_CMD_WIFI) && (scsiDev.cdb[1] == SCSI_NETWORK_WIFI_CMD_ALTREAD)) { + // Redirect the command as a READ. + command = 0x08; + } + + /*// Rather than duplicating code, this just diverts a 'fake' read/write request to make the gvpscsi.device happy on the Amiga + if (scsiDev.cdb[0] == SCSI_CMD_WIFI) + switch (scsiDev.cdb[1]) { + case SCSI_NETWORK_WIFI_CMD_ALTREAD: command = SCSI_CMD_READ; break; + case SCSI_NETWORK_WIFI_CMD_ALTWRITE: command = SCSI_CMD_WRITE; break; + } +*/ + DBGMSG_F("------ in amigaWifiCommand with command 0x%02x", command); + + switch (command) { + case SCSI_CMD_READ: { + size = scsiDev.cdb[4] + (scsiDev.cdb[3] << 8); + + if (unlikely(size < NETWORK_PACKET_MAX_SIZE)) { + DBGMSG_F("%s: SCSI_CMD_READ Data too small %ld", __func__, size); + scsiDev.target->sense.code = ILLEGAL_REQUEST; + scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB; + scsiDev.status = CHECK_CONDITION; + scsiDev.phase = STATUS; + break; + } + + if (scsiDev.cdb[2] & AMIGASCSI_BATCHMODE) { + if (scsiNetworkInboundQueue.readIndex == scsiNetworkInboundQueue.writeIndex) { + // No data + memset(scsiDev.data, 0, 4); + scsiDev.dataLen = 4; + } else { + uint16_t packets = 0; + uint8_t* dataPos = scsiDev.data; + uint32_t bufferUsed = 4; dataPos += 4; // skip header + psize = scsiNetworkInboundQueue.sizes[scsiNetworkInboundQueue.readIndex]; + if (psize>4) psize-=4; // remove checksum + + while (size-bufferUsed>psize+2) { + bufferUsed += psize + 2; + dataPos[0] = psize >> 8; + dataPos[1] = psize & 0xff; + memcpy(&dataPos[2], scsiNetworkInboundQueue.packets[scsiNetworkInboundQueue.readIndex], psize); + + dataPos += psize+2; + packets++; + + // Next packet + if (scsiNetworkInboundQueue.readIndex == NETWORK_PACKET_QUEUE_SIZE - 1) + scsiNetworkInboundQueue.readIndex = 0; + else scsiNetworkInboundQueue.readIndex++; + if (scsiNetworkInboundQueue.readIndex == scsiNetworkInboundQueue.writeIndex) break; + psize = scsiNetworkInboundQueue.sizes[scsiNetworkInboundQueue.readIndex]; + if (psize>4) psize-=4; // remove checksum + } + + // Encode the header + scsiDev.data[0] = packets >> 8; + scsiDev.data[1] = packets & 0xFF; + scsiDev.data[2] = (scsiNetworkInboundQueue.readIndex == scsiNetworkInboundQueue.writeIndex) ? 0 : 1; + scsiDev.data[3] = 0; + + scsiDev.dataLen = bufferUsed; + //DBGMSG_BUF(scsiDev.data, scsiDev.dataLen); + } + } else { + if (scsiNetworkInboundQueue.readIndex == scsiNetworkInboundQueue.writeIndex) { + memset(scsiDev.data, 0, 6); + scsiDev.dataLen = 6; + } else { + psize = scsiNetworkInboundQueue.sizes[scsiNetworkInboundQueue.readIndex]; + if (psize < 64) psize = 64; + else if (psize + 6 > size) { + log_f("%s: packet size too big (%d)", __func__, psize); + psize = size - 6; + } + DBGMSG_F("%s: sending packet[%d] to host of size %zu + 6", __func__, scsiNetworkInboundQueue.readIndex, psize); + scsiDev.dataLen = psize + 6; // 2-byte length + 4-byte flag + packet + memcpy(scsiDev.data + 6, scsiNetworkInboundQueue.packets[scsiNetworkInboundQueue.readIndex], psize); + scsiDev.data[0] = (psize >> 8) & 0xff; + scsiDev.data[1] = psize & 0xff; + if (scsiNetworkInboundQueue.readIndex == NETWORK_PACKET_QUEUE_SIZE - 1) + scsiNetworkInboundQueue.readIndex = 0; + else scsiNetworkInboundQueue.readIndex++; + scsiDev.data[2] = 0; scsiDev.data[3] = 0; scsiDev.data[4] = 0; + // more data to read? + scsiDev.data[5] = (scsiNetworkInboundQueue.readIndex == scsiNetworkInboundQueue.writeIndex ? 0 : 0x10); + DBGMSG_BUF(scsiDev.data, scsiDev.dataLen); + } + } + + // Patches around the weirdness on the Amiga SCSI devices + if ((scsiDev.cdb[0] == SCSI_CMD_WIFI) && (scsiDev.cdb[1] == SCSI_NETWORK_WIFI_CMD_ALTREAD)) { + //scsiDev.data[2] = scsiDev.cdb[2]; // for me really + int extra = 0; + if ( (scsiDev.cdb[2]&0xBF) == AMIGASCSI_PATCH_24BYTE_BLOCKSIZE) { + if (scsiDev.dataLen<90) scsiDev.dataLen = 90; + int missing = (scsiDev.dataLen-90) % 24; + if (missing) { + scsiDev.dataLen += 24 - missing; + // TODO! + if (scsiDev.dataLen>size) { + extra = scsiDev.dataLen - size; + scsiDev.dataLen = size; + } + } + scsiEnterPhase(DATA_IN); + scsiWrite(scsiDev.data, scsiDev.dataLen); + while (!scsiIsWriteFinished(NULL)) platform_poll(); + scsiFinishWrite(); + } else { + extra = scsiDev.dataLen; // F9 means send in ONE transaction + if (extra) scsiEnterPhase(DATA_IN); + } + + if (extra) { + // Just write the extra data to make the padding work for such a large packet + scsiWrite(scsiDev.data, extra); + while (!scsiIsWriteFinished(NULL)) platform_poll(); + scsiFinishWrite(); + } + } else { + // DaynaPort driver needs a delay between reading the initial packet size and the data so manually do two transfers + scsiEnterPhase(DATA_IN); + scsiWrite(scsiDev.data, 6); + while (!scsiIsWriteFinished(NULL)) + { + platform_poll(); + } + scsiFinishWrite(); + + if (scsiDev.dataLen > 6) + { + s2s_delay_us(80); + + scsiWrite(scsiDev.data + 6, scsiDev.dataLen - 6); + while (!scsiIsWriteFinished(NULL)) + { + platform_poll(); + } + scsiFinishWrite(); + } + } + + scsiDev.status = GOOD; + scsiDev.phase = STATUS; + break; + } + + case SCSI_CMD_WRITE: + size = scsiDev.cdb[4] + (scsiDev.cdb[3] << 8); + if (scsiDev.cdb[2] & AMIGASCSI_BATCHMODE) { + if (unlikely(size < 4)) { + DBGMSG_F("%s: SCSI_CMD_WRITE Data too small %ld", __func__, size); + scsiDev.target->sense.code = ILLEGAL_REQUEST; + scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB; + scsiDev.status = CHECK_CONDITION; + scsiDev.phase = STATUS; + break; + } + + // Send multiple packets to the WIFI + scsiEnterPhase(DATA_OUT); + parityError = 0; + scsiRead(scsiDev.data, size, &parityError); + if (parityError) { + DBGMSG_F("%s: read packets block from host of size %zu (parity error %d)", __func__, size, parityError); + } + else { + DBGMSG_F("------ %s: read packets block from host of size %zu", __func__, size); + } + + // How many packets? + uint8_t* bufferPosition = scsiDev.data; + const uint16_t numPackets = (scsiDev.data[0] << 8) | scsiDev.data[1]; + bufferPosition+=2; + + for (uint16_t packet=0; packetsense.code = ILLEGAL_REQUEST; + scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB; + scsiDev.status = CHECK_CONDITION; + scsiDev.phase = STATUS; + break; + } + + if (unlikely(size < 2)) + { + scsiDev.target->sense.code = ILLEGAL_REQUEST; + scsiDev.target->sense.asc = INVALID_FIELD_IN_CDB; + scsiDev.status = CHECK_CONDITION; + scsiDev.phase = STATUS; + break; + } + + int nets = 0; + for (int i = 0; i < WIFI_NETWORK_LIST_ENTRY_COUNT; i++) + { + if (wifi_network_list[i].ssid[0] == '\0') + break; + nets++; + } + + if (nets) { + unsigned int netsize = sizeof(struct wifi_network_entry) * nets; + if (netsize + 2 > sizeof(scsiDev.data)) + { + log_f("WARNING: wifi_network_list is bigger than scsiDev.data, truncating"); + netsize = sizeof(scsiDev.data) - 2; + netsize -= (netsize % (sizeof(struct wifi_network_entry))); + } + if (netsize + 2 > size) + { + log_f("WARNING: wifi_network_list is bigger than requested dataLen, truncating"); + netsize = size - 2; + netsize -= (netsize % (sizeof(struct wifi_network_entry))); + } + scsiDev.data[0] = (netsize >> 8) & 0xff; + scsiDev.data[1] = netsize & 0xff; + memcpy(scsiDev.data + 2, wifi_network_list, netsize); + scsiDev.dataLen = netsize + 2; + } + else + { + scsiDev.data[0] = 0; + scsiDev.data[1] = 0; + scsiDev.dataLen = 2; + } + + scsiDev.phase = DATA_IN; + break; + + case SCSI_NETWORK_WIFI_CMD_INFO: { + // return current wi-fi information + struct wifi_network_entry wifi_cur = { 0 }; + int size = sizeof(wifi_cur); + char *ssid = platform_network_wifi_ssid(); + if (ssid != NULL) + strlcpy(wifi_cur.ssid, ssid, sizeof(wifi_cur.ssid)); + + char *bssid = platform_network_wifi_bssid(); + if (bssid != NULL) + memcpy(wifi_cur.bssid, bssid, sizeof(wifi_cur.bssid)); + + wifi_cur.rssi = platform_network_wifi_rssi(); + wifi_cur.channel = platform_network_wifi_channel(); + scsiDev.data[0] = (size >> 8) & 0xff; + scsiDev.data[1] = size & 0xff; + memcpy(scsiDev.data + 2, (char *)&wifi_cur, size); + scsiDev.dataLen = size + 2; + scsiDev.phase = DATA_IN; + break; + } + + case SCSI_NETWORK_WIFI_CMD_JOIN: { + // set current wi-fi network + struct wifi_join_request req = { 0 }; + + if (size != sizeof(req)) { + log_f("wifi_join_request bad size (%zu != %zu), ignoring", size, sizeof(req)); + scsiDev.status = CHECK_CONDITION; + scsiDev.phase = STATUS; + break; + } + + scsiEnterPhase(DATA_OUT); + parityError = 0; + scsiRead((uint8_t *)&req, sizeof(req), &parityError); + + DBGMSG_F("%s: read join request from host:", __func__); + DBGMSG_BUF(scsiDev.data, size); + + platform_network_wifi_join(req.ssid, req.key); + + scsiDev.status = GOOD; + scsiDev.phase = STATUS; + break; + } + + case SCSI_NETWORK_WIFI_CMD_GETMACADDRESS: + // Update for the gvpscsi.device on the Amiga as it doesn't like 0x09 command being called! - NOTE this only sends 6 bytes back + memcpy(scsiDev.data, scsiDev.boardCfg.wifiMACAddress, sizeof(scsiDev.boardCfg.wifiMACAddress)); + memset(scsiDev.data + sizeof(scsiDev.boardCfg.wifiMACAddress), 0, sizeof(scsiDev.data) - sizeof(scsiDev.boardCfg.wifiMACAddress)); + + scsiDev.dataLen = 6; + scsiDev.phase = DATA_IN; + break; + + // Fetches some info, and the MAC address + case SCSI_NETWORK_WIFI_CMD_AMIGANET_INFO: { + uint32_t maxData = sizeof(scsiDev.data); + if (maxData>0xFFFC) maxData = 0xFFFC; // Even number that fits into two bytes and is a multiple of 4 bytes + const uint32_t maxPackets = NETWORK_PACKET_QUEUE_SIZE-4; // Wanna leave some space + scsiDev.data[0] = (uint8_t)((maxData>>8) & 0xFF); // maximum buffer size that can be received + scsiDev.data[1] = (uint8_t)(maxData & 0xFF); + scsiDev.data[2] = (uint8_t)(maxPackets >> 8); // maximum packets in one go + scsiDev.data[3] = (uint8_t)(maxPackets & 0xFF); + scsiDev.data[4] = 0; // RFU + scsiDev.data[5] = 0; // RFU + memcpy(&scsiDev.data[6], scsiDev.boardCfg.wifiMACAddress, sizeof(scsiDev.boardCfg.wifiMACAddress)); + scsiDev.dataLen = 12; + scsiDev.phase = DATA_IN; + break; + } + } + } + break; + + default: + handled = 0; + break; + } + + + return handled; +} + + +#endif diff --git a/lib/SCSI2SD/src/firmware/AmigaWIFI/AmigaWIFI.h b/lib/SCSI2SD/src/firmware/AmigaWIFI/AmigaWIFI.h new file mode 100644 index 000000000..a9593b472 --- /dev/null +++ b/lib/SCSI2SD/src/firmware/AmigaWIFI/AmigaWIFI.h @@ -0,0 +1,33 @@ +/* + * AmigaWIFI Module, based on the work by joshua stein Copyright (c) 2023 + * Copyright (C) 2026 RobSmithDev + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef AMIGAWIFI_H +#define AMIGAWIFI_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int amigaWifiCommand(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/SCSI2SD/src/firmware/inquiry.c b/lib/SCSI2SD/src/firmware/inquiry.c index 7fdf466aa..6148d2357 100755 --- a/lib/SCSI2SD/src/firmware/inquiry.c +++ b/lib/SCSI2SD/src/firmware/inquiry.c @@ -215,6 +215,7 @@ void s2s_scsiInquiry() break; case S2S_CFG_NETWORK: + case S2S_CFG_AMIGAWIFI: scsiDev.data[2] = 0x01; // Page code. break; @@ -299,6 +300,7 @@ uint8_t getDeviceTypeQualifier() break; case S2S_CFG_NETWORK: + case S2S_CFG_AMIGAWIFI: // processor device return 0x03; break; diff --git a/lib/SCSI2SD/src/firmware/network.c b/lib/SCSI2SD/src/firmware/network.c index e1ba9a9f0..c2d934e4d 100644 --- a/lib/SCSI2SD/src/firmware/network.c +++ b/lib/SCSI2SD/src/firmware/network.c @@ -22,16 +22,27 @@ #include "config.h" #include "network.h" -static bool scsiNetworkEnabled = false; -struct scsiNetworkPacketQueue { - uint8_t packets[NETWORK_PACKET_QUEUE_SIZE][NETWORK_PACKET_MAX_SIZE]; - uint16_t sizes[NETWORK_PACKET_QUEUE_SIZE]; - uint8_t writeIndex; - uint8_t readIndex; -}; +#define SCSI_NETWORK_WIFI_CMD 0x1c // cdb opcode +#define SCSI_NETWORK_WIFI_CMD_SCAN 0x01 // cdb[2] +#define SCSI_NETWORK_WIFI_CMD_COMPLETE 0x02 +#define SCSI_NETWORK_WIFI_CMD_SCAN_RESULTS 0x03 +#define SCSI_NETWORK_WIFI_CMD_INFO 0x04 +#define SCSI_NETWORK_WIFI_CMD_JOIN 0x05 + +// Patches to make the DaynaPORT (or whats left of it) work on the Amiga - RobSmithDev +#define SCSI_NETWORK_WIFI_CMD_ALTREAD 0x08 // gvpscsi.device on AMIGA doesnt like the standard version +#define SCSI_NETWORK_WIFI_CMD_GETMACADDRESS 0x09 // gvpscsi.device on AMIGA doesnt like the standard version + +#define AMIGASCSI_PATCH_24BYTE_BLOCKSIZE 0xA8 // In this mode, data written is rounded up to the nearest 24-byte boundary +#define AMIGASCSI_PATCH_SINGLEWRITE_ONLY 0xA9 // In this mode, data written is always ONLY as one single write command + + +// No longer static so they can be shared with AmigaWIFI +bool scsiNetworkEnabled = false; +struct scsiNetworkPacketQueue scsiNetworkInboundQueue; -static struct scsiNetworkPacketQueue scsiNetworkInboundQueue, scsiNetworkOutboundQueue; +static struct scsiNetworkPacketQueue scsiNetworkOutboundQueue; struct __attribute__((packed)) wifi_network_entry wifi_network_list[WIFI_NETWORK_LIST_ENTRY_COUNT] = { 0 }; diff --git a/lib/SCSI2SD/src/firmware/network.h b/lib/SCSI2SD/src/firmware/network.h index 30e87567d..0a361fb61 100644 --- a/lib/SCSI2SD/src/firmware/network.h +++ b/lib/SCSI2SD/src/firmware/network.h @@ -18,28 +18,23 @@ #define NETWORK_H #include +#include "AmigaWIFI/AmigaWIFI.h" #ifdef __cplusplus extern "C" { #endif -#define SCSI_NETWORK_WIFI_CMD 0x1c // cdb opcode -#define SCSI_NETWORK_WIFI_CMD_SCAN 0x01 // cdb[2] -#define SCSI_NETWORK_WIFI_CMD_COMPLETE 0x02 -#define SCSI_NETWORK_WIFI_CMD_SCAN_RESULTS 0x03 -#define SCSI_NETWORK_WIFI_CMD_INFO 0x04 -#define SCSI_NETWORK_WIFI_CMD_JOIN 0x05 - -// Patches to make the DaynaPORT (or whats left of it) work on the Amiga - RobSmithDev -#define SCSI_NETWORK_WIFI_CMD_ALTREAD 0x08 // gvpscsi.device on AMIGA doesnt like the standard version -#define SCSI_NETWORK_WIFI_CMD_GETMACADDRESS 0x09 // gvpscsi.device on AMIGA doesnt like the standard version - -#define AMIGASCSI_PATCH_24BYTE_BLOCKSIZE 0xA8 // In this mode, data written is rounded up to the nearest 24-byte boundary -#define AMIGASCSI_PATCH_SINGLEWRITE_ONLY 0xA9 // In this mode, data written is always ONLY as one single write command - #define NETWORK_PACKET_QUEUE_SIZE 20 // must be <= 255 #define NETWORK_PACKET_MAX_SIZE 1520 +// Shared with the +struct scsiNetworkPacketQueue { + uint8_t packets[NETWORK_PACKET_QUEUE_SIZE][NETWORK_PACKET_MAX_SIZE]; + uint16_t sizes[NETWORK_PACKET_QUEUE_SIZE]; + uint8_t writeIndex; + uint8_t readIndex; +}; + struct __attribute__((packed)) wifi_network_entry { char ssid[64]; char bssid[6]; diff --git a/lib/SCSI2SD/src/firmware/scsi.c b/lib/SCSI2SD/src/firmware/scsi.c index 9ed23aa8c..e2cd454f2 100755 --- a/lib/SCSI2SD/src/firmware/scsi.c +++ b/lib/SCSI2SD/src/firmware/scsi.c @@ -624,8 +624,9 @@ static void process_Command() else if (((cfg->deviceType == S2S_CFG_OPTICAL) && scsiCDRomCommand()) || ((cfg->deviceType == S2S_CFG_SEQUENTIAL) && scsiTapeCommand()) || ((cfg->deviceType == S2S_CFG_MO) && scsiMOCommand()) -#ifdef BLUESCSI_NETWORK - || ((cfg->deviceType == S2S_CFG_NETWORK && scsiNetworkCommand())) +#ifdef BLUESCSI_NETWORK + || ((cfg->deviceType == S2S_CFG_AMIGAWIFI && amigaWifiCommand())) + || ((cfg->deviceType == S2S_CFG_NETWORK && scsiNetworkCommand())) #endif ) diff --git a/src/BlueSCSI.cpp b/src/BlueSCSI.cpp index 2722ec0e6..8c256c15d 100644 --- a/src/BlueSCSI.cpp +++ b/src/BlueSCSI.cpp @@ -188,6 +188,7 @@ const char * typeToChar(int deviceType) case S2S_CFG_MO: return "MO"; case S2S_CFG_NETWORK: + case S2S_CFG_AMIGAWIFI: return "Network"; case S2S_CFG_SEQUENTIAL: return "Tape"; @@ -287,6 +288,7 @@ bool findHDDImages() bool is_re = (tolower(name[0]) == 'r' && tolower(name[1]) == 'e'); bool is_tp = (tolower(name[0]) == 't' && tolower(name[1]) == 'p'); bool is_zp = (tolower(name[0]) == 'z' && tolower(name[1]) == 'p'); + bool is_am = (tolower(name[0]) == 'a' && tolower(name[1]) == 'm'); if(strcasecmp(name, "CLEAR_ROM") == 0) { @@ -294,7 +296,7 @@ bool findHDDImages() continue; } - if (is_hd || is_cd || is_fd || is_mo || is_ne || is_re || is_tp || is_zp) + if (is_hd || is_cd || is_fd || is_mo || is_ne || is_re || is_tp || is_zp || is_am) { // Check if the image should be loaded to microcontroller flash ROM drive bool is_romdrive = false; @@ -359,7 +361,7 @@ bool findHDDImages() continue; } - if (is_ne && !platform_network_supported()) + if ((is_ne || is_am) && !platform_network_supported()) { log("-- Ignoring ", fullname, ", networking is not supported on this hardware"); continue; @@ -372,6 +374,7 @@ bool findHDDImages() if (is_fd) type = S2S_CFG_FLOPPY_14MB; if (is_mo) type = S2S_CFG_MO; if (is_ne) type = S2S_CFG_NETWORK; + if (is_am) type = S2S_CFG_AMIGAWIFI; if (is_re) type = S2S_CFG_REMOVEABLE; if (is_tp) type = S2S_CFG_SEQUENTIAL; if (is_zp) type = S2S_CFG_ZIP100; @@ -428,7 +431,7 @@ bool findHDDImages() { int capacity_kB = ((uint64_t)cfg->scsiSectors * cfg->bytesPerSector) / 1024; - if (cfg->deviceType == S2S_CFG_NETWORK) + if (cfg->deviceType == S2S_CFG_NETWORK || cfg->deviceType == S2S_CFG_AMIGAWIFI) { log("* ID: ", (int)(cfg->scsiId & S2S_CFG_TARGET_ID_BITS), ", Type: ", typeToChar((int)cfg->deviceType), diff --git a/src/BlueSCSI_config.h b/src/BlueSCSI_config.h index 8505acb6a..455e0632d 100644 --- a/src/BlueSCSI_config.h +++ b/src/BlueSCSI_config.h @@ -59,6 +59,7 @@ #define DRIVEINFO_MAGOPT {"BlueSCSI", "MO_DRIVE", PLATFORM_REVISION, ""} #define DRIVEINFO_NETWORK {"Dayna", "SCSI/Link", "2.0f", ""} #define DRIVEINFO_TAPE {"BlueSCSI", "TAPE", PLATFORM_REVISION, ""} +#define DRIVEINFO_AMIGAWIFI {"AmigaNET", "SCSI/Link", "1.0f", ""} // Default SCSI drive information when Apple quirks are enabled #define APPLE_DRIVEINFO_FIXED {"QUANTUM", "BlueSCSI Pico", "1.0", ""} diff --git a/src/BlueSCSI_disk.cpp b/src/BlueSCSI_disk.cpp index 8d8e1e364..04b15a913 100644 --- a/src/BlueSCSI_disk.cpp +++ b/src/BlueSCSI_disk.cpp @@ -268,13 +268,14 @@ static void setDefaultDriveInfo(int target_idx) static const char *driveinfo_magopt[4] = DRIVEINFO_MAGOPT; static const char *driveinfo_network[4] = DRIVEINFO_NETWORK; static const char *driveinfo_tape[4] = DRIVEINFO_TAPE; + static const char *driveinfo_amigawifi[4] = DRIVEINFO_AMIGAWIFI; static const char *apl_driveinfo_fixed[4] = APPLE_DRIVEINFO_FIXED; static const char *apl_driveinfo_removable[4] = APPLE_DRIVEINFO_REMOVABLE; static const char *apl_driveinfo_optical[4] = APPLE_DRIVEINFO_OPTICAL; static const char *apl_driveinfo_floppy[4] = APPLE_DRIVEINFO_FLOPPY; static const char *apl_driveinfo_magopt[4] = APPLE_DRIVEINFO_MAGOPT; - static const char *apl_driveinfo_network[4] = APPLE_DRIVEINFO_NETWORK; + static const char *apl_driveinfo_network[4] = APPLE_DRIVEINFO_NETWORK; static const char *apl_driveinfo_tape[4] = APPLE_DRIVEINFO_TAPE; static const char *iomega_driveinfo_removeable[4] = IOMEGA_DRIVEINFO_ZIP100; @@ -291,9 +292,10 @@ static void setDefaultDriveInfo(int target_idx) case S2S_CFG_OPTICAL: driveinfo = apl_driveinfo_optical; break; case S2S_CFG_FLOPPY_14MB: driveinfo = apl_driveinfo_floppy; break; case S2S_CFG_MO: driveinfo = apl_driveinfo_magopt; break; - case S2S_CFG_NETWORK: driveinfo = apl_driveinfo_network; break; + case S2S_CFG_NETWORK: driveinfo = apl_driveinfo_network; break; case S2S_CFG_SEQUENTIAL: driveinfo = apl_driveinfo_tape; break; case S2S_CFG_ZIP100: driveinfo = iomega_driveinfo_removeable; break; + case S2S_CFG_AMIGAWIFI: driveinfo = driveinfo_amigawifi; break; // just incase default: driveinfo = apl_driveinfo_fixed; break; } } @@ -308,6 +310,7 @@ static void setDefaultDriveInfo(int target_idx) case S2S_CFG_FLOPPY_14MB: driveinfo = driveinfo_floppy; break; case S2S_CFG_MO: driveinfo = driveinfo_magopt; break; case S2S_CFG_NETWORK: driveinfo = driveinfo_network; break; + case S2S_CFG_AMIGAWIFI: driveinfo = driveinfo_amigawifi; break; case S2S_CFG_SEQUENTIAL: driveinfo = driveinfo_tape; break; case S2S_CFG_ZIP100: driveinfo = iomega_driveinfo_removeable; break; default: driveinfo = driveinfo_fixed; break; @@ -381,7 +384,7 @@ bool scsiDiskOpenHDDImage(const char *filename, int scsi_id, int scsi_lun, int b img.scsiId = scsi_id | S2S_CFG_TARGET_ENABLED; img.sdSectorStart = 0; - if (type != S2S_CFG_NETWORK) + if ((type != S2S_CFG_NETWORK) && (type != S2S_CFG_AMIGAWIFI)) { if (img.scsiSectors == 0) { @@ -427,6 +430,17 @@ bool scsiDiskOpenHDDImage(const char *filename, int scsi_id, int scsi_lun, int b log("---- Configuring as network based on image name"); img.deviceType = S2S_CFG_NETWORK; } + else if (type == S2S_CFG_AMIGAWIFI) + { + if (!platform_network_supported()) + { + log("---- Error: network not supported on this device, ignoring ", filename); + img.file.close(); + return false; + } + log("---- Configuring as network based on image name"); + img.deviceType = S2S_CFG_AMIGAWIFI; + } else if (type == S2S_CFG_REMOVEABLE) { log("---- Configuring as removable drive based on image name"); @@ -1013,7 +1027,7 @@ bool scsiDiskCheckAnyNetworkDevicesConfigured() { for (int i = 0; i < S2S_MAX_TARGETS; i++) { - if (g_DiskImages[i].file.isOpen() && (g_DiskImages[i].scsiId & S2S_CFG_TARGET_ENABLED) && g_DiskImages[i].deviceType == S2S_CFG_NETWORK) + if (g_DiskImages[i].file.isOpen() && (g_DiskImages[i].scsiId & S2S_CFG_TARGET_ENABLED) && (g_DiskImages[i].deviceType == S2S_CFG_NETWORK || g_DiskImages[i].deviceType == S2S_CFG_AMIGAWIFI)) { return true; } @@ -1316,7 +1330,7 @@ static void doReadCapacity() uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector; uint32_t capacity; - if (unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_NETWORK)) + if (unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_NETWORK) || unlikely(scsiDev.target->cfg->deviceType == S2S_CFG_AMIGAWIFI)) { capacity = 1; }