Annotation of previous/src/scsi.c, revision 1.1

1.1     ! root        1: /* SCSI Bus and Disk emulation */
        !             2: #include "main.h"
        !             3: #include "ioMem.h"
        !             4: #include "ioMemTables.h"
        !             5: #include "video.h"
        !             6: #include "configuration.h"
        !             7: #include "sysdeps.h"
        !             8: #include "m68000.h"
        !             9: #include "sysReg.h"
        !            10: #include "statusbar.h"
        !            11: #include "scsi.h"
        !            12: #include "dma.h"
        !            13: #include "esp.h"
        !            14: #include "dialog.h"
        !            15: #include "file.h"
        !            16: 
        !            17: 
        !            18: #define COMMAND_ReadInt16(a, i) (((unsigned) a[i] << 8) | a[i + 1])
        !            19: #define COMMAND_ReadInt24(a, i) (((unsigned) a[i] << 16) | ((unsigned) a[i + 1] << 8) | a[i + 2])
        !            20: #define COMMAND_ReadInt32(a, i) (((unsigned) a[i] << 24) | ((unsigned) a[i + 1] << 16) | ((unsigned) a[i + 2] << 8) | a[i + 3])
        !            21: 
        !            22: 
        !            23: #define BLOCKSIZE 512
        !            24: 
        !            25: #define LUN_DISC 0 // for now only LUN 0 is valid for our phys drives
        !            26: 
        !            27: static Uint32 nLastBlockAddr;
        !            28: static bool bSetLastBlockAddr;
        !            29: static Uint8 nLastError;
        !            30: 
        !            31: /* Disk Infos */
        !            32: 
        !            33: bool bCDROM;
        !            34: bool bTargetDevice;
        !            35: Uint32 nDiskSize;
        !            36: 
        !            37: 
        !            38: static FILE *scsidisk = NULL;
        !            39: 
        !            40: FILE* scsiimage[ESP_MAX_DEVS];
        !            41: Uint32 nFileSize[ESP_MAX_DEVS];
        !            42: 
        !            43: 
        !            44: /* Initialize/Uninitialize SCSI disks */
        !            45: void SCSI_Init(void) {
        !            46:     Log_Printf(LOG_WARN, "CALL SCSI INIT\n");
        !            47:     
        !            48:     /* Check if files exist. Present dialog to re-select missing files. */        
        !            49:     int target;
        !            50:     for (target = 0; target < ESP_MAX_DEVS; target++) {
        !            51:         if (File_Exists(ConfigureParams.SCSI.target[target].szImageName) && ConfigureParams.SCSI.target[target].bAttached) {
        !            52:             nFileSize[target] = File_Length(ConfigureParams.SCSI.target[target].szImageName);
        !            53:             scsiimage[target] = ConfigureParams.SCSI.target[target].bCDROM == true ? File_Open(ConfigureParams.SCSI.target[target].szImageName, "r") : File_Open(ConfigureParams.SCSI.target[target].szImageName, "r+");
        !            54:         } else {
        !            55:             nFileSize[target] = 0;
        !            56:             scsiimage[target]=NULL;
        !            57:         }
        !            58:     }
        !            59:     
        !            60:     for (target = 0; target < ESP_MAX_DEVS; target++) {
        !            61:         Log_Printf(LOG_WARN, "Disk0: %s\n", ConfigureParams.SCSI.target[target].szImageName);
        !            62:     }
        !            63: }
        !            64: 
        !            65: void SCSI_Uninit(void) {
        !            66:     int target;
        !            67:     for (target = 0; target < ESP_MAX_DEVS; target++) {
        !            68:         if (scsiimage[target])
        !            69:                File_Close(scsiimage[target]);
        !            70:     }
        !            71:     
        !            72:     scsidisk = NULL;
        !            73: }
        !            74: 
        !            75: void SCSI_Reset(void) {
        !            76:     SCSI_Uninit();
        !            77:     SCSI_Init();
        !            78: }
        !            79: 
        !            80: 
        !            81: 
        !            82: /* INQUIRY response data */
        !            83: static unsigned char inquiry_bytes[] =
        !            84: {
        !            85:        0x00,             /* 0: device type: 0x00 = direct access device, 0x05 = cd-rom, 0x07 = mo-disk */
        !            86:        0x00,             /* 1: &0x7F - device type qulifier 0x00 unsupported, &0x80 - rmb: 0x00 = nonremovable, 0x80 = removable */
        !            87:        0x01,             /* 2: ANSI SCSI standard (first release) compliant */
        !            88:     0x02,             /* 3: Restponse format (format of following data): 0x01 SCSI-1 compliant */
        !            89:        0x31,             /* 4: additional length of the following data */
        !            90:     0x00, 0x00,       /* 5,6: reserved */
        !            91:     0x1C,             /* 7: RelAdr=0, Wbus32=0, Wbus16=0, Sync=1, Linked=1, RSVD=1, CmdQue=0, SftRe=0 */
        !            92:        'P','r','e','v','i','o','u','s',        /*  8-15: Vendor ASCII */
        !            93:        'H','D','D',' ',' ',' ',' ',' ',        /* 16-23: Model ASCII */
        !            94:     ' ',' ',' ',' ',' ',' ',' ',' ',        /* 24-31: Blank space ASCII */
        !            95:     '0','0','0','0','0','0','0','1',        /* 32-39: Revision ASCII */
        !            96:        '0','0','0','0','0','0','0','0',        /* 40-47: Serial Number ASCII */
        !            97:     ' ',' ',' ',' ',' ',' '                 /* 48-53: Blank space ASCII */
        !            98: };
        !            99: 
        !           100: 
        !           101: 
        !           102: void scsi_command_analyzer(Uint8 commandbuf[], int size, int target, int lun) {
        !           103:     int i;
        !           104:     SCSIcommand.source_busid = commandbuf[0];
        !           105:     for (i = 1; i < size; i++) {
        !           106:         SCSIcommand.command[i-1] = commandbuf[i];
        !           107:     }
        !           108: 
        !           109:     SCSIcommand.opcode = SCSIcommand.command[0];
        !           110:     if (target >= ESP_MAX_DEVS) {
        !           111:         Log_Printf(LOG_WARN, "Invalid target: %i!\n", target);
        !           112:         abort();
        !           113:     }
        !           114:     SCSIcommand.target = target;
        !           115:     SCSIcommand.lun = lun;
        !           116:     Log_Printf(LOG_WARN, "SCSI command: Length = %i, Opcode = $%02x, target = %i, lun=%i\n", size, SCSIcommand.opcode, SCSIcommand.target,SCSIcommand.lun);
        !           117:     
        !           118:     scsidisk = scsiimage[target];
        !           119:     nDiskSize = nFileSize[target];
        !           120:     bCDROM = ConfigureParams.SCSI.target[target].bCDROM;
        !           121:     bTargetDevice = ConfigureParams.SCSI.target[target].bAttached;
        !           122: 
        !           123:     //bTargetDevice |= bCDROM; // handle empty cd-rom drive - does not work yet!
        !           124:     if(scsidisk) { // experimental!
        !           125:         SCSIcommand.nodevice = false;
        !           126:         SCSIcommand.timeout = false;
        !           127:         if ((SCSIcommand.lun!=LUN_DISC) && (SCSIcommand.opcode!=HD_REQ_SENSE) && (SCSIcommand.opcode!=HD_INQUIRY))
        !           128:        {
        !           129:                Log_Printf(LOG_WARN, "SCSI command: No device at target %i\n", SCSIcommand.target);
        !           130:         SCSIcommand.nodevice = true;
        !           131:         SCSIcommand.timeout = false;
        !           132:                SCSIcommand.transferdirection_todevice = 0;
        !           133:                SCSIcommand.transfer_data_len=0;
        !           134:                SCSIcommand.returnCode = HD_STATUS_ERROR;
        !           135:                nLastError= HD_REQSENS_NODRIVE;
        !           136:                return;
        !           137:        }
        !           138:         SCSI_Emulate_Command();
        !           139:     } else {   
        !           140:        // hacks for NeXT (to be tested on real life...)
        !           141:        // question is : what an SCSI controler should answer for missing drives (and if SCSI controler is aware of SCSI opcodes)
        !           142:     // if (SCSIcommand.opcode==HD_TEST_UNIT_RDY) {SCSI_TestMissingUnitReady();SCSIcommand.nodevice = false;return;}
        !           143: //        SCSIcommand.nodevice = false;
        !           144: //        SCSIcommand.timeout = false;
        !           145: //     if (SCSIcommand.opcode==HD_REQ_SENSE) {SCSI_Emulate_Command();return;}
        !           146:         Log_Printf(LOG_WARN, "SCSI command: No target %i %s at %d", SCSIcommand.target,__FILE__,__LINE__);
        !           147:         SCSIcommand.nodevice = false;
        !           148:         SCSIcommand.timeout = true;
        !           149:         SCSIcommand.transferdirection_todevice = 0;
        !           150:     }
        !           151: }
        !           152: 
        !           153: void SCSI_Emulate_Command(void)
        !           154: {
        !           155:     
        !           156:        switch(SCSIcommand.opcode)
        !           157:        {
        !           158:             
        !           159:         case HD_TEST_UNIT_RDY:
        !           160:             Log_Printf(LOG_WARN, "SCSI command: Test unit ready\n");
        !           161:             SCSI_TestUnitReady();
        !           162:             break;
        !           163:             
        !           164:         case HD_READ_CAPACITY1:
        !           165:             Log_Printf(LOG_WARN, "SCSI command: Read capacity\n");
        !           166:             SCSI_ReadCapacity();
        !           167:             break;
        !           168:             
        !           169:         case HD_READ_SECTOR:
        !           170:         case HD_READ_SECTOR1:
        !           171:             Log_Printf(LOG_WARN, "SCSI command: Read sector\n");
        !           172:             SCSI_ReadSector();
        !           173:             break;
        !           174:             
        !           175:         case HD_WRITE_SECTOR:
        !           176:         case HD_WRITE_SECTOR1:
        !           177:             Log_Printf(LOG_WARN, "SCSI command: Write sector\n");
        !           178: //            HDC_Cmd_WriteSector();
        !           179:             abort();
        !           180:             break;
        !           181:             
        !           182:         case HD_INQUIRY:
        !           183:             Log_Printf(LOG_WARN, "SCSI command: Inquiry\n");
        !           184:             SCSI_Inquiry();
        !           185:             break;
        !           186:             
        !           187:         case HD_SEEK:
        !           188:             Log_Printf(LOG_WARN, "SCSI command: Seek\n");
        !           189: //            HDC_Cmd_Seek();
        !           190:             abort();
        !           191:             break;
        !           192:             
        !           193:         case HD_SHIP:
        !           194:             Log_Printf(LOG_WARN, "SCSI command: Ship\n");
        !           195:             SCSI_StartStop();
        !           196:             break;
        !           197:             
        !           198:         case HD_REQ_SENSE:
        !           199:             Log_Printf(LOG_WARN, "SCSI command: Request sense\n");
        !           200:             SCSI_RequestSense();
        !           201:             break;
        !           202:             
        !           203:         case HD_MODESELECT:
        !           204:             Log_Printf(LOG_WARN, "MODE SELECT call not implemented yet.\n");
        !           205:             SCSIcommand.returnCode = HD_STATUS_OK;
        !           206:             nLastError = HD_REQSENS_OK;
        !           207:             bSetLastBlockAddr = false;
        !           208: //            FDC_SetDMAStatus(false);
        !           209: //            FDC_AcknowledgeInterrupt();
        !           210:             abort();
        !           211:             break;
        !           212:             
        !           213:         case HD_MODESENSE:
        !           214:             Log_Printf(LOG_WARN, "SCSI command: Mode sense\n");
        !           215:             SCSI_ModeSense();
        !           216:             break;
        !           217:             
        !           218:         case HD_FORMAT_DRIVE:
        !           219:             Log_Printf(LOG_WARN, "SCSI command: Format drive\n");
        !           220: //            HDC_Cmd_FormatDrive();
        !           221:             abort();
        !           222:             break;
        !           223:             
        !           224:             /* as of yet unsupported commands */
        !           225:         case HD_VERIFY_TRACK:
        !           226:         case HD_FORMAT_TRACK:
        !           227:         case HD_CORRECTION:
        !           228:             
        !           229:         default:
        !           230:             Log_Printf(LOG_WARN, "Unknown Command\n");
        !           231:             SCSIcommand.returnCode = HD_STATUS_ERROR;
        !           232:             nLastError = HD_REQSENS_OPCODE;
        !           233:             bSetLastBlockAddr = false;
        !           234: //            FDC_AcknowledgeInterrupt();
        !           235:             break;
        !           236:        }
        !           237:     esp_command_complete();
        !           238:     
        !           239:     /* Update the led each time a command is processed */
        !           240:        Statusbar_EnableHDLed();
        !           241: }
        !           242: 
        !           243: 
        !           244: /* Helpers */
        !           245: 
        !           246: int SCSI_GetTransferLength(void)
        !           247: {
        !           248:        return SCSIcommand.opcode < 0x20?
        !           249:     // class 0
        !           250:     SCSIcommand.command[4] :
        !           251:     // class 1
        !           252:     COMMAND_ReadInt16(SCSIcommand.command, 7);
        !           253: }
        !           254: 
        !           255: unsigned long SCSI_GetOffset(void)
        !           256: {
        !           257:        return SCSIcommand.opcode < 0x20?
        !           258:     // class 0
        !           259:     (COMMAND_ReadInt24(SCSIcommand.command, 1) & 0x1FFFFF) :
        !           260:     // class 1
        !           261:     COMMAND_ReadInt32(SCSIcommand.command, 2);
        !           262: }
        !           263: 
        !           264: // get reserved count for SCSI reply
        !           265: int SCSI_GetCount(void)
        !           266: {
        !           267:        return SCSIcommand.opcode < 0x20?
        !           268:     // class 0
        !           269:     SCSIcommand.command[4] :
        !           270:     // class 1
        !           271:     COMMAND_ReadInt16(SCSIcommand.command, 7);
        !           272: }
        !           273: 
        !           274: MODEPAGE SCSI_GetModePage(Uint8 pagecode) {
        !           275:     MODEPAGE page;
        !           276:     Uint32 sectors;
        !           277:     Uint32 cylinders;
        !           278:     Uint8 heads;
        !           279:     
        !           280:     switch (pagecode) {
        !           281:         case 0x01: // error recovery page
        !           282:             page.pagesize = 8;
        !           283:             page.modepage[0] = 0x01; // &0x80: page savable? (not supported!), &0x7F: page code = 0x01
        !           284:             page.modepage[1] = 0x06; // page length = 6
        !           285:             page.modepage[2] = 0x00; // AWRE, ARRE, TB, RC, EER, PER, DTE, DCR
        !           286:             page.modepage[3] = 0x1B; // retry count
        !           287:             page.modepage[4] = 0x0B; // correction span in bits
        !           288:             page.modepage[5] = 0x00; // head offset count
        !           289:             page.modepage[6] = 0x00; // data strobe offset count
        !           290:             page.modepage[7] = 0xFF; // recovery time limit
        !           291:             break;
        !           292:             
        !           293:         case 0x02: // disconnect/reconnect page
        !           294:         case 0x03: // format device page
        !           295:             page.pagesize = 0;
        !           296:             Log_Printf(LOG_WARN, "Mode Sense: Page %02x not yet emulated!\n", pagecode);
        !           297:             break;
        !           298: 
        !           299:         case 0x04: // rigid disc geometry page
        !           300:             sectors = nDiskSize / BLOCKSIZE;
        !           301:             heads = 16; // max heads per cylinder: 16
        !           302:             cylinders = sectors / (63 * heads); // max sectors per track: 63
        !           303:             if ((sectors % (63 * heads)) != 0) {
        !           304:                 cylinders += 1;
        !           305:             }
        !           306:             Log_Printf(LOG_WARN, "Disk geometry: %i sectors, %i cylinders, %i heads\n", sectors, cylinders, heads);
        !           307:             
        !           308:             page.pagesize = 0; //20;
        !           309:             Log_Printf(LOG_WARN, "Disk geometry page disabled!\n"); abort();
        !           310:             page.modepage[0] = 0x04; // &0x80: page savable? (not supported!), &0x7F: page code = 0x04
        !           311:             page.modepage[1] = 0x12;
        !           312:             page.modepage[2] = (cylinders >> 16) & 0xFF;
        !           313:             page.modepage[3] = (cylinders >> 8) & 0xFF;
        !           314:             page.modepage[4] = cylinders & 0xFF;
        !           315:             page.modepage[5] = heads;
        !           316:             page.modepage[6] = 0x00; // 6,7,8: starting cylinder - write precomp (not supported)
        !           317:             page.modepage[7] = 0x00;
        !           318:             page.modepage[8] = 0x00;
        !           319:             page.modepage[9] = 0x00; // 9,10,11: starting cylinder - reduced write current (not supported)
        !           320:             page.modepage[10] = 0x00;
        !           321:             page.modepage[11] = 0x00;
        !           322:             page.modepage[12] = 0x00; // 12,13: drive step rate (not supported)
        !           323:             page.modepage[13] = 0x00;
        !           324:             page.modepage[14] = 0x00; // 14,15,16: loading zone cylinder (not supported)
        !           325:             page.modepage[15] = 0x00;
        !           326:             page.modepage[16] = 0x00;
        !           327:             page.modepage[17] = 0x00; // &0x03: rotational position locking
        !           328:             page.modepage[18] = 0x00; // rotational position lock offset
        !           329:             page.modepage[19] = 0x00; // reserved
        !           330:             break;
        !           331:             
        !           332:         case 0x08: // caching page
        !           333:         case 0x0C: // notch page
        !           334:         case 0x0D: // power condition page
        !           335:         case 0x38: // cache control page
        !           336:         case 0x3C: // soft ID page (EEPROM)
        !           337:             page.pagesize = 0;
        !           338:             Log_Printf(LOG_WARN, "Mode Sense: Page %02x not yet emulated!\n", pagecode);
        !           339:             break;
        !           340:             
        !           341:         case 0x00: // operating page
        !           342:             page.pagesize = 4;
        !           343:             page.modepage[0] = 0x00; // &0x80: page savable? (not supported!), &0x7F: page code = 0x00
        !           344:             page.modepage[1] = 0x02; // page length = 2
        !           345:             page.modepage[2] = 0x80; // &0x80: usage bit = 1, &0x10: disable unit attention = 0
        !           346:             page.modepage[3] = 0x00; // &0x7F: device type qualifier = 0x00, see inquiry!
        !           347:             break;
        !           348:             
        !           349:         default:
        !           350:             page.pagesize = 0;
        !           351:             Log_Printf(LOG_WARN, "Mode Sense: Invalid page code: %02x!\n", pagecode);
        !           352:             break;
        !           353:     }
        !           354:     return page;
        !           355: }
        !           356: 
        !           357: 
        !           358: 
        !           359: /* SCSI Commands */
        !           360: 
        !           361: void SCSI_TestUnitReady(void)
        !           362: {
        !           363:     SCSIcommand.transfer_data_len = 0;
        !           364:        SCSIcommand.returnCode = HD_STATUS_OK;
        !           365: }
        !           366: 
        !           367: 
        !           368: void SCSI_ReadCapacity(void)
        !           369: {        
        !           370:     Log_Printf(LOG_WARN, "Read disk image: size = %i\n", nDiskSize);
        !           371: 
        !           372:     SCSIcommand.transfer_data_len = 8;
        !           373:   
        !           374:     Uint32 sectors = nDiskSize / BLOCKSIZE;
        !           375:     
        !           376:     static Uint8 scsi_disksize[8];
        !           377: 
        !           378:     scsi_disksize[0] = (sectors >> 24) & 0xFF;
        !           379:     scsi_disksize[1] = (sectors >> 16) & 0xFF;
        !           380:     scsi_disksize[2] = (sectors >> 8) & 0xFF;
        !           381:     scsi_disksize[3] = sectors & 0xFF;
        !           382:     scsi_disksize[4] = (BLOCKSIZE >> 24) & 0xFF;
        !           383:     scsi_disksize[5] = (BLOCKSIZE >> 16) & 0xFF;
        !           384:     scsi_disksize[6] = (BLOCKSIZE >> 8) & 0xFF;
        !           385:     scsi_disksize[7] = BLOCKSIZE & 0xFF;
        !           386:     
        !           387:     memcpy(dma_write_buffer, scsi_disksize, SCSIcommand.transfer_data_len);
        !           388:                SCSIcommand.returnCode = HD_STATUS_OK;
        !           389:                nLastError = HD_REQSENS_OK;
        !           390:     
        !           391:        bSetLastBlockAddr = false;
        !           392: }
        !           393: 
        !           394: 
        !           395: void SCSI_ReadSector(void)
        !           396: {
        !           397:        int n=0;
        !           398:     
        !           399:        nLastBlockAddr = SCSI_GetOffset() * BLOCKSIZE;
        !           400:     SCSIcommand.transfer_data_len = SCSI_GetCount() * BLOCKSIZE;
        !           401:     
        !           402:     
        !           403:        /* seek to the position */
        !           404:        if ((scsidisk==NULL) || (fseek(scsidisk, nLastBlockAddr, SEEK_SET) != 0))
        !           405:        {
        !           406:         SCSIcommand.returnCode = HD_STATUS_ERROR;
        !           407:         nLastError = HD_REQSENS_INVADDR;
        !           408:        }
        !           409:        else
        !           410:        {
        !           411:         n = fread(dma_write_buffer, SCSIcommand.transfer_data_len, 1, scsidisk);
        !           412:         
        !           413:         /* Test to check if we read correct data */
        !           414:         //        Log_Printf(LOG_WARN, "Disk Read Test: $%02x,$%02x,$%02x,$%02x,$%02x,$%02x,$%02x,$%02x\n", dma_write_buffer[0],dma_write_buffer[1],dma_write_buffer[2],dma_write_buffer[3],dma_write_buffer[4],dma_write_buffer[5],dma_write_buffer[6],dma_write_buffer[07]);
        !           415:     }
        !           416: 
        !           417:     if (n == 1) {
        !           418:                        SCSIcommand.returnCode = HD_STATUS_OK;
        !           419:                        nLastError = HD_REQSENS_OK;
        !           420:                }
        !           421:                else
        !           422:                {
        !           423:                        SCSIcommand.returnCode = HD_STATUS_ERROR;
        !           424:                        nLastError = HD_REQSENS_NOSECTOR;
        !           425:                }
        !           426:         
        !           427:                /* Update DMA counter */
        !           428: //             FDC_WriteDMAAddress(nDmaAddr + 512*n);
        !           429: //  }
        !           430:     
        !           431: //     FDC_SetDMAStatus(false);              /* no DMA error */
        !           432: //     FDC_AcknowledgeInterrupt();
        !           433:        bSetLastBlockAddr = true;
        !           434:        //FDCSectorCountRegister = 0;
        !           435: }
        !           436: 
        !           437: 
        !           438: 
        !           439: void SCSI_Inquiry (void) {
        !           440:     
        !           441:     if (bCDROM) {
        !           442:         inquiry_bytes[0] = 0x05;
        !           443:         inquiry_bytes[1] |= 0x80;
        !           444:         inquiry_bytes[16] = 'C';
        !           445:         inquiry_bytes[18] = '-';
        !           446:         inquiry_bytes[19] = 'R';
        !           447:         inquiry_bytes[20] = 'O';
        !           448:         inquiry_bytes[21] = 'M';
        !           449:         Log_Printf(LOG_WARN, "Disk is CD-ROM\n");
        !           450:     } else {
        !           451:         inquiry_bytes[0] = 0x00;
        !           452:         inquiry_bytes[1] &= ~0x80;
        !           453:         inquiry_bytes[16] = 'H';
        !           454:         inquiry_bytes[18] = 'D';
        !           455:         inquiry_bytes[19] = ' ';
        !           456:         inquiry_bytes[20] = ' ';
        !           457:         inquiry_bytes[21] = ' ';
        !           458:         Log_Printf(LOG_WARN, "Disk is HDD\n");
        !           459:     }
        !           460:     
        !           461:     if (SCSIcommand.lun!=LUN_DISC) {        inquiry_bytes[0] = 0x1F;}
        !           462:     
        !           463:     SCSIcommand.transfer_data_len = SCSI_GetTransferLength();
        !           464:     Log_Printf(LOG_WARN, "return length: %d", SCSIcommand.transfer_data_len);
        !           465:     SCSIcommand.transferdirection_todevice = 0;
        !           466:     memcpy(dma_write_buffer, inquiry_bytes, SCSIcommand.transfer_data_len);
        !           467:     
        !           468:     Log_Printf(LOG_WARN, "Inquiry Data: %c,%c,%c,%c,%c,%c,%c,%c\n",dma_write_buffer[8],dma_write_buffer[9],dma_write_buffer[10],dma_write_buffer[11],dma_write_buffer[12],dma_write_buffer[13],dma_write_buffer[14],dma_write_buffer[15]);
        !           469:                 
        !           470:        if (SCSIcommand.transfer_data_len > (int)sizeof(inquiry_bytes))
        !           471:                SCSIcommand.transfer_data_len = sizeof(inquiry_bytes);
        !           472:     
        !           473:     SCSIcommand.returnCode = HD_STATUS_OK;
        !           474:        nLastError = HD_REQSENS_OK;
        !           475:        bSetLastBlockAddr = false;
        !           476: }
        !           477: 
        !           478: 
        !           479: void SCSI_StartStop(void) {
        !           480:     SCSIcommand.transfer_data_len = 0;
        !           481:     SCSIcommand.transferdirection_todevice = 0;
        !           482:     SCSIcommand.returnCode = HD_STATUS_OK;
        !           483: }
        !           484: 
        !           485: 
        !           486: void SCSI_RequestSense(void) {
        !           487:        int nRetLen;
        !           488:        Uint8 retbuf[22];
        !           489: 
        !           490:         SCSIcommand.returnCode = HD_STATUS_OK;
        !           491:         
        !           492:        nRetLen = SCSI_GetCount();
        !           493:     
        !           494:        if ((nRetLen < 4 && nRetLen != 0) || nRetLen > 22)
        !           495:        {
        !           496:                Log_Printf(LOG_WARN, "SCSI: *** Strange REQUEST SENSE *** len=%d!",nRetLen);
        !           497:        }
        !           498:     
        !           499:        /* Limit to sane length */
        !           500:        if (nRetLen <= 0)
        !           501:        {
        !           502:                nRetLen = 4;
        !           503:        }
        !           504:        else if (nRetLen > 22)
        !           505:        {
        !           506:                nRetLen = 22;
        !           507:        }
        !           508: 
        !           509:         Log_Printf(LOG_WARN, "[SCSI] REQ SENSE size = %d %s at %d", nRetLen,__FILE__,__LINE__);
        !           510:         
        !           511:        memset(retbuf, 0, nRetLen);
        !           512:     
        !           513:        if (nRetLen <= 4)
        !           514:        {
        !           515:                retbuf[0] = nLastError;
        !           516:                if (bSetLastBlockAddr)
        !           517:                {
        !           518:                        retbuf[0] |= 0x80;
        !           519:                        retbuf[1] = nLastBlockAddr >> 16;
        !           520:                        retbuf[2] = nLastBlockAddr >> 8;
        !           521:                        retbuf[3] = nLastBlockAddr;
        !           522:                }
        !           523:        }
        !           524:        else
        !           525:        {
        !           526:                retbuf[0] = 0x70;
        !           527:                if (bSetLastBlockAddr)
        !           528:                {
        !           529:                        retbuf[0] |= 0x80;
        !           530:                        retbuf[4] = nLastBlockAddr >> 16;
        !           531:                        retbuf[5] = nLastBlockAddr >> 8;
        !           532:                        retbuf[6] = nLastBlockAddr;
        !           533:                }
        !           534:                switch (nLastError)
        !           535:                {
        !           536:             case HD_REQSENS_OK:  retbuf[2] = 0; break;
        !           537:             case HD_REQSENS_OPCODE:  retbuf[2] = 5; break;
        !           538:             case HD_REQSENS_INVADDR:  retbuf[2] = 5; break;
        !           539:             case HD_REQSENS_INVARG:  retbuf[2] = 5; break;
        !           540:             case HD_REQSENS_NODRIVE:  retbuf[2] = 2; break;
        !           541:             default: retbuf[2] = 4; break;
        !           542:                }
        !           543:                retbuf[7] = 14;
        !           544:                retbuf[12] = nLastError;
        !           545:                retbuf[19] = nLastBlockAddr >> 16;
        !           546:                retbuf[20] = nLastBlockAddr >> 8;
        !           547:                retbuf[21] = nLastBlockAddr;
        !           548:        }
        !           549:     
        !           550:     SCSIcommand.transfer_data_len = nRetLen;
        !           551:     memcpy(dma_write_buffer, retbuf, SCSIcommand.transfer_data_len);
        !           552:     SCSIcommand.returnCode = HD_STATUS_OK;
        !           553: }
        !           554: 
        !           555: 
        !           556: void SCSI_ModeSense(void) {
        !           557:     Uint8 retbuf[256];
        !           558:     MODEPAGE page;
        !           559:     
        !           560:     Uint32 sectors = nDiskSize / BLOCKSIZE;
        !           561: 
        !           562:     Uint8 pagecontrol = (SCSIcommand.command[2] & 0x0C) >> 6;
        !           563:     Uint8 pagecode = SCSIcommand.command[2] & 0x3F;
        !           564:     Uint8 dbd = SCSIcommand.command[1] & 0x08; // disable block descriptor
        !           565:         
        !           566:     Log_Printf(LOG_WARN, "Mode Sense: page = %02x, page_control = %i, %s\n", pagecode, pagecontrol, dbd == 0x08 ? "block descriptor disabled" : "block descriptor enabled");
        !           567:     
        !           568:     /* Header */
        !           569:     retbuf[0] = 0x00; // length of following data
        !           570:     retbuf[1] = 0x00; // medium type (always 0)
        !           571:     retbuf[2] = bCDROM == true ? 0x80 : 0x00; // if media is read-only 0x80, else 0x00
        !           572:     retbuf[3] = 0x08; // block descriptor length
        !           573:     
        !           574:     /* Block descriptor data */
        !           575:     Uint8 header_size = 4;
        !           576:     if (!dbd) {
        !           577:         retbuf[4] = 0x00; // media density code
        !           578:         retbuf[5] = sectors >> 16;  // Number of blocks, high (?)
        !           579:         retbuf[6] = sectors >> 8;   // Number of blocks, med (?)
        !           580:         retbuf[7] = sectors;        // Number of blocks, low (?)
        !           581:         retbuf[8] = 0x00; // reserved
        !           582:         retbuf[9] = (BLOCKSIZE >> 16) & 0xFF;      // Block size in bytes, high
        !           583:         retbuf[10] = (BLOCKSIZE >> 8) & 0xFF;     // Block size in bytes, med
        !           584:         retbuf[11] = BLOCKSIZE & 0xFF;     // Block size in bytes, low
        !           585:         header_size = 12;
        !           586:         Log_Printf(LOG_WARN, "Mode Sense: Block descriptor data: %s, size = %i blocks, blocksize = %i byte\n", bCDROM == true ? "disk is read-only" : "disk is read/write" , sectors, BLOCKSIZE);
        !           587:     }
        !           588:     retbuf[0] = header_size - 1;
        !           589:     
        !           590:     /* Mode Pages */
        !           591:     if (pagecode == 0x3F) { // return all pages!
        !           592:         Uint8 offset = header_size;
        !           593:         Uint8 counter;
        !           594:         for (pagecode = 0; pagecode < 0x3F; pagecode++) {
        !           595:             page = SCSI_GetModePage(pagecode);
        !           596:             switch (pagecontrol) {
        !           597:                 case 0: // current values (not supported, using default values)
        !           598:                     memcpy(page.current, page.modepage, page.pagesize);
        !           599:                     for (counter = 0; counter < page.pagesize; counter++) {
        !           600:                         retbuf[counter+offset] = page.current[counter];
        !           601:                     }
        !           602:                     break;
        !           603:                 case 1: // changeable values (not supported, all 0)
        !           604:                     memset(page.changeable, 0x00, page.pagesize);
        !           605:                     for (counter = 0; counter < page.pagesize; counter++) {
        !           606:                         retbuf[counter+offset] = page.changeable[counter];
        !           607:                     }
        !           608:                     break;
        !           609:                 case 2: // default values
        !           610:                     for (counter = 0; counter < page.pagesize; counter++) {
        !           611:                         retbuf[counter+offset] = page.modepage[counter];
        !           612:                     }
        !           613:                     break;
        !           614:                 case 3: // saved values (not supported, using default values)
        !           615:                     memcpy(page.saved, page.modepage, page.pagesize);
        !           616:                     for (counter = 0; counter < page.pagesize; counter++) {
        !           617:                         retbuf[counter+offset] = page.saved[counter];
        !           618:                     }
        !           619:                     break;
        !           620:                     
        !           621:                 default:
        !           622:                     break;
        !           623:             }
        !           624:             offset += page.pagesize;
        !           625:             retbuf[0] += page.pagesize;
        !           626:         }
        !           627:     } else { // return only single requested page
        !           628:         page = SCSI_GetModePage(pagecode);
        !           629:         
        !           630:         Uint8 counter;
        !           631:         switch (pagecontrol) {
        !           632:             case 0: // current values (not supported, using default values)
        !           633:                 memcpy(page.current, page.modepage, page.pagesize);
        !           634:                 for (counter = 0; counter < page.pagesize; counter++) {
        !           635:                     retbuf[counter+header_size] = page.current[counter];
        !           636:                 }
        !           637:                 break;
        !           638:             case 1: // changeable values (not supported, all 0)
        !           639:                 memset(page.changeable, 0x00, page.pagesize);
        !           640:                 for (counter = 0; counter < page.pagesize; counter++) {
        !           641:                     retbuf[counter+header_size] = page.changeable[counter];
        !           642:                 }
        !           643:                 break;
        !           644:             case 2: // default values
        !           645:                 for (counter = 0; counter < page.pagesize; counter++) {
        !           646:                     retbuf[counter+header_size] = page.modepage[counter];
        !           647:                 }
        !           648:                 break;
        !           649:             case 3: // saved values (not supported, using default values)
        !           650:                 memcpy(page.saved, page.modepage, page.pagesize);
        !           651:                 for (counter = 0; counter < page.pagesize; counter++) {
        !           652:                     retbuf[counter+header_size] = page.saved[counter];
        !           653:                 }
        !           654:                 break;
        !           655:                 
        !           656:             default:
        !           657:                 break;
        !           658:         }
        !           659:         
        !           660:         retbuf[0] += page.pagesize;
        !           661:     }
        !           662:     
        !           663:     
        !           664:     SCSIcommand.transfer_data_len = retbuf[0] + 1;
        !           665:     if (SCSIcommand.transfer_data_len > SCSI_GetTransferLength())
        !           666:         SCSIcommand.transfer_data_len = SCSI_GetTransferLength();
        !           667:     
        !           668:     memcpy(dma_write_buffer, retbuf, SCSIcommand.transfer_data_len);
        !           669:     
        !           670:     SCSIcommand.returnCode = HD_STATUS_OK;
        !           671:     nLastError = HD_REQSENS_OK;
        !           672:     
        !           673:        bSetLastBlockAddr = false;
        !           674: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.