| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730 |
- /*
- * SCSI-HDデバイスエミュレータ
- */
- #include <SPI.h>
- #include "SdFat.h"
- //ENABLE_EXTENDED_TRANSFER_CLASSを1に設定する
- //libraries/SdFat/SdFatConfig.h
- SPIClass SPI_2(2);
- SdFatEX SD(&SPI_2);
- //#define SPI_SPEED SD_SCK_MHZ(18)
-
- #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)
- #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 PA0 // SCSI:DB0
- //#define DB1 PA1 // SCSI:DB1
- //#define DB2 PA2 // SCSI:DB2
- //#define DB3 PA3 // SCSI:DB3
- //#define DB4 PA4 // SCSI:DB4
- //#define DB5 PA5 // SCSI:DB5
- //#define DB6 PA6 // SCSI:DB6
- //#define DB7 PA7 // SCSI:DB7
- //#define DBP PA8 // SCSI:DBP
- #define ATN PB0 // SCSI:ATN
- #define BSY PB1 // SCSI:BSY
- #define ACK PB10 // SCSI:ACK
- #define RST PB11 // SCSI:RST
- #define MSG PB5 // SCSI:MSG
- #define SEL PB6 // SCSI:SEL
- #define CD PB7 // SCSI:C/D
- #define REQ PB8 // SCSI:REQ
- #define IO PB9 // SCSI:I/O
- #define SD_CS PB12 // SDCARD:CS
- #define LED PC13 // LED
- #define SCSIID 0 // SCSI-ID
- #define BLOCKSIZE 512 // 1BLOCKサイズ
- uint8_t m_senseKey = 0; //センスキー
- volatile bool m_isBusReset = false; //バスリセット
- #define HDIMG_FILE "HD.HDS" // HDイメージファイル名
- File m_file; // ファイルオブジェクト
- uint32_t m_fileSize; // ファイルサイズ
- byte m_buf[BLOCKSIZE]; // 汎用バッファ
- int m_msc;
- bool m_msb[256];
- /*
- * IO読み込み.
- */
- inline byte readIO(void)
- {
- //GPIO(SCSI BUS)初期化
- //ポート設定レジスタ(下位
- GPIOA->regs->CRL = 0x88888888; // Configure GPIOA[7:0]
- uint32 ret = GPIOA->regs->IDR;
- byte bret = 0x00;
- bret |= ((!bitRead(ret,7)) << 7);
- bret |= ((!bitRead(ret,6)) << 6);
- bret |= ((!bitRead(ret,5)) << 5);
- bret |= ((!bitRead(ret,4)) << 4);
- bret |= ((!bitRead(ret,3)) << 3);
- bret |= ((!bitRead(ret,2)) << 2);
- bret |= ((!bitRead(ret,1)) << 1);
- bret |= ((!bitRead(ret,0)) << 0);
- return bret;
- }
- /*
- * IO書き込み.
- */
- inline void writeIO(byte v)
- {
- //GPIO(SCSI BUS)初期化
- //ポート設定レジスタ(下位)
- // GPIOA->regs->CRL = 0x11111111; // Configure GPIOA PP[7:0]10MHz
- GPIOA->regs->CRL = 0x33333333; // Configure GPIOA PP[7:0]50MHz
- //ポート設定レジスタ(上位)
- GPIOA->regs->CRH = 0x00000003; // Configure GPIOA PP[16:8]50MHz
- uint32 retL = 0x00;
- uint32 retH = 0x00;
- if(!parity(v)) {
- bitWrite(retL, 8, 1);
- } else {
- bitWrite(retH, 8, 1);
- }
- if(v & ( 1 << 7 )) {
- bitWrite(retL, 7, 1);
- } else {
- bitWrite(retH, 7, 1);
- }
- if(v & ( 1 << 6 )) {
- bitWrite(retL, 6, 1);
- } else {
- bitWrite(retH, 6, 1);
- }
- if(v & ( 1 << 5 )) {
- bitWrite(retL, 5, 1);
- } else {
- bitWrite(retH, 5, 1);
- }
- if(v & ( 1 << 4 )) {
- bitWrite(retL, 4, 1);
- } else {
- bitWrite(retH, 4, 1);
- }
- if(v & ( 1 << 3 )) {
- bitWrite(retL, 3, 1);
- } else {
- bitWrite(retH, 3, 1);
- }
- if(v & ( 1 << 2 )) {
- bitWrite(retL, 2, 1);
- } else {
- bitWrite(retH, 2, 1);
- }
- if(v & ( 1 << 1 )) {
- bitWrite(retL, 1, 1);
- } else {
- bitWrite(retH, 1, 1);
- }
- if(v & ( 1 << 0 )) {
- bitWrite(retL, 0, 1);
- } else {
- bitWrite(retH, 0, 1);
- }
- //ビットがLOWに設定される
- GPIOA->regs->BRR = retL ;
- // ビットがHIGHに設定される
- GPIOA->regs->BSRR = retH ;
- }
- /*
- * 初期化.
- * パリティチェック
- */
- inline int parity(byte val) {
- val ^= val >> 16;
- val ^= val >> 8;
- val ^= val >> 4;
- val ^= val >> 2;
- val ^= val >> 1;
- return val & 0x00000001;
- }
- /*
- * 初期化.
- * バスの初期化、PINの向きの設定を行う
- */
- void setup()
- {
- // PA15 / PB3 / PB4 が使えない
- // JTAG デバッグ用に使われているからです。
- disableDebugPorts();
- //シリアル初期化
- //Serial.begin(9600);
- //while (!Serial);
- //PINの初期化
- gpio_mode(LED, GPIO_OUTPUT_OD);
- gpio_write(LED, low);
- //GPIO(SCSI BUS)初期化
- //ポート設定レジスタ(下位)
- GPIOA->regs->CRL = 0x888888888; // Configure GPIOA[8:0]
- gpio_mode(ATN, GPIO_INPUT_PU);
- gpio_mode(BSY, GPIO_INPUT_PU);
- gpio_mode(ACK, GPIO_INPUT_PU);
- gpio_mode(RST, GPIO_INPUT_PU);
- gpio_mode(SEL, GPIO_INPUT_PU);
-
- gpio_mode(MSG, GPIO_OUTPUT_PP);
- gpio_mode(CD, GPIO_OUTPUT_PP);
- gpio_mode(REQ, GPIO_OUTPUT_PP);
- gpio_mode(IO, GPIO_OUTPUT_PP);
- gpio_write(MSG, low);
- gpio_write(CD, low);
- gpio_write(REQ, low);
- gpio_write(IO, low);
- //RSTピンの状態がHIGHからLOWに変わったときに発生
- attachInterrupt(PIN_MAP[RST].gpio_bit, onBusReset, FALLING);
-
- if(!SD.begin(SD_CS,SPI_FULL_SPEED)) {
- Serial.println("SD initialization failed!");
- onFalseInit();
- }
- //HDイメージファイル
- m_file = SD.open(HDIMG_FILE, O_RDWR);
- if(!m_file) {
- Serial.println("Error: open hdimg");
- onFalseInit();
- }
- m_fileSize = m_file.size();
- Serial.println("Found Valid HD Image File.");
- Serial.print(m_fileSize);
- Serial.println("byte");
- Serial.print(m_fileSize / 1024);
- Serial.println("KB");
- Serial.print(m_fileSize / 1024 / 1024);
- Serial.println("MB");
- }
- /*
- * 初期化失敗.
- */
- void onFalseInit(void)
- {
- while(true) {
- gpio_write(LED, high);
- delay(500);
- gpio_write(LED, low);
- delay(500);
- }
- }
- /*
- * バスリセット割り込み.
- */
- void onBusReset(void)
- {
- if(isHigh(gpio_read(RST))) {
- delayMicroseconds(20);
- if(isHigh(gpio_read(RST))) {
- LOGN("BusReset!");
- m_isBusReset = true;
- }
- }
- }
- /*
- * ハンドシェイクで読み込む.
- */
- byte readHandshake(void)
- {
- gpio_write(REQ, high);
- while(isLow(gpio_read(ACK))) {
- if(m_isBusReset) {
- return 0;
- }
- }
- byte r = readIO();
- gpio_write(REQ, low);
- while(isHigh(gpio_read(ACK))) {
- if(m_isBusReset) {
- return 0;
- }
- }
- return r;
- }
- /*
- * ハンドシェイクで書込み.
- */
- void writeHandshake(byte d)
- {
- writeIO(d);
- gpio_write(REQ, high);
- while(isLow(gpio_read(ACK))) {
- if(m_isBusReset) {
- return;
- }
- }
- gpio_write(REQ, low);
- while(isHigh(gpio_read(ACK))) {
- if(m_isBusReset) {
- return;
- }
- }
- }
- /*
- * データインフェーズ.
- * データ配列 p を len バイト送信する。
- */
- void writeDataPhase(int len, byte* p)
- {
- LOGN("DATAIN PHASE");
- gpio_write(MSG, low);
- gpio_write(CD, low);
- gpio_write(IO, high);
- for (int i = 0; i < len; i++) {
- if(m_isBusReset) {
- return;
- }
- writeHandshake(p[i]);
- }
- }
- /*
- * データインフェーズ.
- * SDカードからの読み込みながら len ブロック送信する。
- */
- void writeDataPhaseSD(uint32_t adds, uint32_t len)
- {
- LOGN("DATAIN PHASE(SD)");
- uint32_t pos = adds * BLOCKSIZE;
- m_file.seek(pos);
- gpio_write(MSG, low);
- gpio_write(CD, low);
- gpio_write(IO, high);
- for(uint32_t i = 0; i < len; i++) {
- m_file.read(m_buf, BLOCKSIZE);
- for(int j = 0; j < BLOCKSIZE; j++) {
- if(m_isBusReset) {
- return;
- }
- writeHandshake(m_buf[j]);
- }
- }
- }
- /*
- * データアウトフェーズ.
- * len ブロック読み込みながら SDカードへ書き込む。
- */
- void readDataPhaseSD(uint32_t adds, uint32_t len)
- {
- LOGN("DATAOUT PHASE(SD)");
- uint32_t pos = adds * BLOCKSIZE;
- m_file.seek(pos);
- gpio_write(MSG, low);
- gpio_write(CD, low);
- gpio_write(IO, low);
- for(uint32_t i = 0; i < len; i++) {
- for(int j = 0; j < BLOCKSIZE; j++) {
- if(m_isBusReset) {
- return;
- }
- m_buf[j] = readHandshake();
- }
- m_file.write(m_buf, BLOCKSIZE);
- }
- m_file.flush();
- }
- /*
- * INQUIRY コマンド処理.
- */
- void onInquiryCommand(byte len)
- {
- byte buf[36] = {
- 0x00, //デバイスタイプ
- 0x00, //RMB = 0
- 0x01, //ISO,ECMA,ANSIバージョン
- 0x01, //レスポンスデータ形式
- 35 - 4, //追加データ長
- 0, 0, //Reserve
- 0x00, //サポート機能
- 'T', 'N', 'B', ' ', ' ', ' ', ' ', ' ',
- 'A', 'r', 'd', 'S', 'C', 'S', 'i', 'n', 'o', ' ', ' ',' ', ' ', ' ', ' ', ' ',
- '0', '0', '1', '0',
- };
- writeDataPhase(len < 36 ? len : 36, buf);
- }
- /*
- * REQUEST SENSE コマンド処理.
- */
- void onRequestSenseCommand(byte len)
- {
- byte buf[18] = {
- 0x70, //CheckCondition
- 0, //セグメント番号
- 0x00, //センスキー
- 0, 0, 0, 0, //インフォメーション
- 17 - 7 , //追加データ長
- 0,
- };
- buf[2] = m_senseKey;
- m_senseKey = 0;
- writeDataPhase(len < 18 ? len : 18, buf);
- }
- /*
- * READ CAPACITY コマンド処理.
- */
- void onReadCapacityCommand(byte pmi)
- {
- uint32_t bc = m_fileSize / BLOCKSIZE;
- uint32_t bl = BLOCKSIZE;
- uint8_t buf[8] = {
- bc >> 24, bc >> 16, bc >> 8, bc,
- bl >> 24, bl >> 16, bl >> 8, bl
- };
- writeDataPhase(8, buf);
- }
- /*
- * READ6/10 コマンド処理.
- */
- byte onReadCommand(uint32_t adds, uint32_t len)
- {
- LOGN("-R");
- LOGHEXN(adds);
- LOGHEXN(len);
- gpio_write(LED, high);
- writeDataPhaseSD(adds, len);
- gpio_write(LED, low);
- return 0; //sts
- }
- /*
- * WRITE6/10 コマンド処理.
- */
- byte onWriteCommand(uint32_t adds, uint32_t len)
- {
- LOGN("-W");
- LOGHEXN(adds);
- LOGHEXN(len);
- gpio_write(LED, high);
- readDataPhaseSD(adds, len);
- gpio_write(LED, low);
- return 0; //sts
- }
- /*
- * MODE SENSE コマンド処理.
- */
- void onModeSenseCommand(byte dbd, int pageCode, uint32_t len)
- {
- memset(m_buf, 0, sizeof(m_buf));
- int a = 4;
- if(dbd == 0) {
- uint32_t bc = m_fileSize / BLOCKSIZE;
- uint32_t bl = BLOCKSIZE;
- byte c[8] = {
- 0,//デンシティコード
- bc >> 16, bc >> 8, bc,
- 0, //Reserve
- bl >> 16, bl >> 8, bl
- };
- memcpy(&m_buf[4], c, 8);
- a += 8;
- m_buf[3] = 0x08;
- }
- switch(pageCode) {
- case 0x3F:
- case 0x03: //ドライブパラメータ
- m_buf[a + 0] = 0x03; //ページコード
- m_buf[a + 1] = 0x16; // ページ長
- m_buf[a + 11] = 0x3F;//セクタ数/トラック
- a += 24;
- if(pageCode != 0x3F) {
- break;
- }
- case 0x04: //ドライブパラメータ
- {
- uint32_t bc = m_fileSize / BLOCKSIZE;
- m_buf[a + 0] = 0x04; //ページコード
- m_buf[a + 1] = 0x16; // ページ長
- m_buf[a + 2] = bc >> 16;// シリンダ長
- m_buf[a + 3] = bc >> 8;
- m_buf[a + 4] = bc;
- m_buf[a + 5] = 1; //ヘッド数
- a += 24;
- }
- if(pageCode != 0x3F) {
- break;
- }
- default:
- break;
- }
- m_buf[0] = a - 1;
- writeDataPhase(len < a ? len : a, m_buf);
- }
- /*
- * MsgIn2.
- */
- void MsgIn2(int msg)
- {
- LOGN("MsgIn2");
- gpio_write(MSG, high);
- gpio_write(CD, high);
- gpio_write(IO, high);
- writeHandshake(msg);
- }
- /*
- * MsgOut2.
- */
- void MsgOut2()
- {
- LOGN("MsgOut2");
- gpio_write(MSG, high);
- gpio_write(CD, high);
- gpio_write(IO, low);
- m_msb[m_msc] = readHandshake();
- m_msc++;
- m_msc %= 256;
- }
- /*
- * メインループ.
- */
- void loop()
- {
- int sts = 0;
- int msg = 0;
- //BSY,SELが+はバスフリー
- // セレクションチェック
- // BSYが-の間ループ
- if(isHigh(gpio_read(BSY))) {
- return;
- }
- // SELが+の間ループ
- if(isLow(gpio_read(SEL))) {
- return;
- }
- // BSY+ SEL-
- byte db = readIO();
- if((db & (1 << SCSIID)) == 0) {
- return;
- }
- LOGN("Selection");
- m_isBusReset = false;
- // セレクトされたらBSYを-にする
- gpio_mode(BSY, GPIO_OUTPUT_PP);
- gpio_write(BSY, high);
- while(isHigh(gpio_read(SEL))) {
- if(m_isBusReset) {
- goto BusFree;
- }
- }
- if(isHigh(gpio_read(ATN))) {
- bool syncenable = false;
- int syncperiod = 50;
- int syncoffset = 0;
- m_msc = 0;
- memset(m_msb, 0x00, sizeof(m_msb));
- while(isHigh(gpio_read(ATN))) {
- MsgOut2();
- }
- for(int i = 0; i < m_msc; i++) {
- // ABORT
- if (m_msb[i] == 0x06) {
- goto BusFree;
- }
- // BUS DEVICE RESET
- if (m_msb[i] == 0x0C) {
- syncoffset = 0;
- goto BusFree;
- }
- // IDENTIFY
- if (m_msb[i] >= 0x80) {
- }
- // 拡張メッセージ
- if (m_msb[i] == 0x01) {
- // 同期転送が可能な時だけチェック
- if (!syncenable || m_msb[i + 2] != 0x01) {
- MsgIn2(0x07);
- break;
- }
- // Transfer period factor(50 x 4 = 200nsに制限)
- syncperiod = m_msb[i + 3];
- if (syncperiod > 50) {
- syncoffset = 50;
- }
- // REQ/ACK offset(16に制限)
- syncoffset = m_msb[i + 4];
- if (syncoffset > 16) {
- syncoffset = 16;
- }
- // STDR応答メッセージ生成
- MsgIn2(0x01);
- MsgIn2(0x03);
- MsgIn2(0x01);
- MsgIn2(syncperiod);
- MsgIn2(syncoffset);
- break;
- }
- }
- }
- LOGN("Command");
- gpio_write(MSG, low);
- gpio_write(CD, high);
- gpio_write(IO, low);
- int len;
- byte cmd[12];
- cmd[0] = readHandshake();
- LOGHEX(cmd[0]);
- len = 1;
- switch(cmd[0] >> 5) {
- case 0b000:
- len = 6;
- break;
- case 0b001:
- len = 10;
- break;
- case 0b010:
- len = 10;
- break;
- case 0b101:
- len = 12;
- break;
- default:
- break;
- }
- for(int i = 1; i < len; i++ ) {
- cmd[i] = readHandshake();
- LOGHEX(cmd[i]);
- }
- LOGN("");
- switch(cmd[0]) {
- case 0x00:
- LOGN("[Test Unit]");
- break;
- case 0x01:
- LOGN("[Rezero Unit]");
- break;
- case 0x03:
- LOGN("[RequestSense]");
- onRequestSenseCommand(cmd[4]);
- break;
- case 0x04:
- LOGN("[FormatUnit]");
- break;
- case 0x06:
- LOGN("[FormatUnit]");
- break;
- case 0x07:
- LOGN("[ReassignBlocks]");
- break;
- case 0x08:
- LOGN("[Read6]");
- sts = onReadCommand((((uint32_t)cmd[1] & 0x1F) << 16) | ((uint32_t)cmd[2] << 8) | cmd[3], (cmd[4] == 0) ? 0x100 : cmd[4]);
- break;
- case 0x0A:
- LOGN("[Write6]");
- sts = onWriteCommand((((uint32_t)cmd[1] & 0x1F) << 16) | ((uint32_t)cmd[2] << 8) | cmd[3], (cmd[4] == 0) ? 0x100 : cmd[4]);
- break;
- case 0x0B:
- LOGN("[Seek6]");
- break;
- case 0x12:
- LOGN("[Inquiry]");
- onInquiryCommand(cmd[4]);
- break;
- case 0x1A:
- LOGN("[ModeSense6]");
- onModeSenseCommand(cmd[1]&0x80, cmd[2] & 0x3F, cmd[4]);
- break;
- case 0x1B:
- LOGN("[StartStopUnit]");
- break;
- case 0x1E:
- LOGN("[PreAllowMed.Removal]");
- break;
- case 0x25:
- LOGN("[ReadCapacity]");
- onReadCapacityCommand(cmd[8]);
- break;
- case 0x28:
- LOGN("[Read10]");
- sts = onReadCommand(((uint32_t)cmd[2] << 24) | ((uint32_t)cmd[3] << 16) | ((uint32_t)cmd[4] << 8) | cmd[5], ((uint32_t)cmd[7] << 8) | cmd[8]);
- break;
- case 0x2A:
- LOGN("[Write10]");
- sts = onWriteCommand(((uint32_t)cmd[2] << 24) | ((uint32_t)cmd[3] << 16) | ((uint32_t)cmd[4] << 8) | cmd[5], ((uint32_t)cmd[7] << 8) | cmd[8]);
- break;
- case 0x2B:
- LOGN("[Seek10]");
- break;
- case 0x5A:
- LOGN("[ModeSense10]");
- onModeSenseCommand(cmd[1] & 0x80, cmd[2] & 0x3F, ((uint32_t)cmd[7] << 8) | cmd[8]);
- break;
- default:
- LOGN("[*Unknown]");
- sts = 2;
- m_senseKey = 5;
- break;
- }
- if(m_isBusReset) {
- goto BusFree;
- }
- LOGN("Sts");
- gpio_write(MSG, low);
- gpio_write(CD, high);
- gpio_write(IO, high);
- writeHandshake(sts);
- if(m_isBusReset) {
- goto BusFree;
- }
- LOGN("MsgIn");
- gpio_write(MSG, high);
- gpio_write(CD, high);
- gpio_write(IO, high);
- writeHandshake(msg);
- BusFree:
- LOGN("BusFree");
- m_isBusReset = false;
- gpio_write(REQ, low);
- gpio_write(MSG, low);
- gpio_write(CD, low);
- gpio_write(IO, low);
- // gpio_write(BSY, low);
- gpio_mode(BSY, GPIO_INPUT_PU);
- }
|