Annotation of previous/src/scsi.c, revision 1.1.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.