📄 idechannel.java
字号:
break; case GPCMD_REQUEST_SENSE: maxLength = 0xff & buffer[4]; for (int i = 0; i < 18; i++) buffer[i] = 0; buffer[0] = (byte)(0x70 | (1 << 7)); buffer[2] = senseKey; buffer[7] = 10; buffer[12] = asc; atapiCommandReply(18, maxLength); break; case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: if (drive.inserted()) { drive.setLock((buffer[4] & 1) != 0); atapiCommandOk(); } else { atapiCommandError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); } break; case GPCMD_READ_10: case GPCMD_READ_12: { int numSectors; int lba; if (!drive.inserted()) { atapiCommandError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; } if (buffer[0] == GPCMD_READ_10) numSectors = bigEndianBytesToShort(buffer, 7); else numSectors = bigEndianBytesToInt(buffer, 6); lba = bigEndianBytesToInt(buffer, 2); if (numSectors == 0) { atapiCommandOk(); break; } if ((((0xffffffffl & lba) + (0xffffffffl & numSectors)) << 2) > drive.getTotalSectors()) { atapiCommandError(SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); break; } atapiCommandRead(lba, numSectors, 2048); } break; case GPCMD_READ_CD: { int numSectors, lba, transferRequest; if (!drive.inserted()) { atapiCommandError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; } numSectors = ((0xff & buffer[6]) << 16) | ((0xff & buffer[7]) << 8) | (0xff & buffer[8]); lba = bigEndianBytesToInt(buffer, 2); if (numSectors == 0) { atapiCommandOk(); break; } if ((((0xffffffffl & lba) + (0xffffffffl & numSectors)) << 2) > drive.getTotalSectors()) { atapiCommandError(SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); break; } transferRequest = 0xff & buffer[9]; switch(transferRequest & 0xf8) { case 0x00: /* nothing */ atapiCommandOk(); break; case 0x10: /* normal read */ atapiCommandRead(lba, numSectors, 2048); break; case 0xf8: /* read all data */ atapiCommandRead(lba, numSectors, 2352); break; default: atapiCommandError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); break; } } break; case GPCMD_SEEK: { int lba; if (!drive.inserted()) { atapiCommandError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; } lba = bigEndianBytesToInt(buffer, 2); if (((0xffffffffl & lba) << 2) > drive.getTotalSectors()) { atapiCommandError(SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); break; } atapiCommandOk(); } break; case GPCMD_START_STOP_UNIT: { boolean start = ((buffer[4] & 1) != 0); boolean eject = ((buffer[4] & 2) != 0); if (eject && !start) { /* eject the disk */ drive.close(); } atapiCommandOk(); } break; case GPCMD_MECHANISM_STATUS: { maxLength = bigEndianBytesToShort(buffer, 8); shortToBigEndianBytes(buffer, 0, (short)0); /* no current LBA */ buffer[2] = 0; buffer[3] = 0; buffer[4] = 0; buffer[5] = 1; shortToBigEndianBytes(buffer, 6, (short)0); atapiCommandReply(8, maxLength); } break; case GPCMD_READ_TOC_PMA_ATIP: { int format, msf, startTrack, length; if (!drive.inserted()) { atapiCommandError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; } maxLength = bigEndianBytesToShort(buffer, 7); format = (0xff & buffer[9]) >>> 6; msf = (buffer[1] >>> 1) & 1; startTrack = 0xff & buffer[6]; switch(format) { case 0: length = cdromReadTOC((int)(drive.getTotalSectors() >>> 2), buffer, msf, startTrack); if (length < 0) { atapiCommandError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); break; } atapiCommandReply(length, maxLength); break; case 1: /* multi session : only a single session defined */ for (int i = 0; i < 12; i++) buffer[i] = 0; buffer[1] = 0x0a; buffer[2] = 0x01; buffer[3] = 0x01; atapiCommandReply(12, maxLength); break; case 2: length = cdromReadTOCRaw((int)(drive.getTotalSectors() >>> 2), buffer, msf, startTrack); if (length < 0) { atapiCommandError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); break; } atapiCommandReply(length, maxLength); break; default: atapiCommandError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); break; } } break; case GPCMD_READ_CDVD_CAPACITY: if (!drive.inserted()) { atapiCommandError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; } /* NOTE: it is really the number of sectors minus 1 */ intToBigEndianBytes(buffer, 0, (int)((drive.getTotalSectors() >>> 2) - 1)); intToBigEndianBytes(buffer, 4, 2048); atapiCommandReply(8, 8); break; case GPCMD_INQUIRY: maxLength = 0xff & buffer[4]; buffer[0] = 0x05; /* CD-ROM */ buffer[1] = (byte)0x80; /* removable */ buffer[2] = 0x00; /* ISO */ buffer[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */ buffer[4] = 31; /* additionnal length */ buffer[5] = 0; /* reserved */ buffer[6] = 0; /* reserved */ buffer[7] = 0; /* reserved */ { byte[] temp = "JPC".getBytes(); int i = 8; for (int j = 0; j < temp.length; i++, j++) buffer[i] = temp[j]; for (; i < 16; i++) buffer[i] = 0; } { byte[] temp = "JPC CD-ROM".getBytes(); int i = 16; for (int j = 0; j < temp.length; i++, j++) buffer[i] = temp[j]; for (; i < 32; i++) buffer[i] = 0; } { byte[] temp = "1.0".getBytes(); int i = 32; for (int j = 0; j < temp.length; i++, j++) buffer[i] = temp[j]; for (; i < 36; i++) buffer[i] = 0; } atapiCommandReply(36, maxLength); break; default: atapiCommandError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE); break; } } private void dummyTransferStop() { this.dataBuffer = this.ioBuffer; this.dataBufferEnd = 0; this.ioBuffer[0] = (byte)0xff; this.ioBuffer[1] = (byte)0xff; this.ioBuffer[2] = (byte)0xff; this.ioBuffer[3] = (byte)0xff; } private void atapiCommandOk() { this.error = 0; this.status = READY_STAT; this.nSector = (this.nSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; this.setIRQ(); } private void atapiCommandError(int senseKey, int asc) { this.error = (byte)(this.senseKey << 4); this.status = READY_STAT | ERR_STAT; this.nSector = (this.nSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; this.senseKey = (byte)senseKey; this.asc = (byte)asc; this.setIRQ(); } private void atapiCommandReply(int size, int maxSize) { size = Math.min(size, maxSize); this.lba = -1; this.packetTransferSize = size; this.elementaryTransferSize = 0; this.ioBufferIndex = 0; this.status = READY_STAT; atapiCommandReplyEnd(); } private void atapiCommandRead(int lba, int numSectors, int sectorSize) { if (this.atapiDMA) atapiCommandReadDMA(lba, numSectors, sectorSize); else atapiCommandReadPIO(lba, numSectors, sectorSize); } private void atapiCommandReadDMA(int lba, int numSectors, int sectorSize) { this.lba = lba; this.packetTransferSize = numSectors * sectorSize; this.ioBufferIndex = sectorSize; this.cdSectorSize = sectorSize; this.status = READY_STAT | DRQ_STAT; dmaStart(IDF_ATAPI_READ_DMA_CB); } private void atapiCommandReadPIO(int lba, int numSectors, int sectorSize) { this.lba = lba; this.packetTransferSize = numSectors * sectorSize; this.elementaryTransferSize = 0; this.ioBufferIndex = sectorSize; this.cdSectorSize = sectorSize; this.status = READY_STAT; atapiCommandReplyEnd(); } private void atapiCommandReplyEnd() { if (this.packetTransferSize <= 0) { //end of transfer transferStop(); this.status = READY_STAT; this.nSector = (this.nSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; this.setIRQ(); } else { /* see if a new sector must be read */ if (this.lba != -1 && this.ioBufferIndex >= this.cdSectorSize) { cdReadSector(this.lba, this.ioBuffer, this.cdSectorSize); this.lba++; this.ioBufferIndex = 0; } if (this.elementaryTransferSize > 0) { // there is some data left to transmit in this elementary transfer int size = Math.min(this.cdSectorSize - this.ioBufferIndex, this.elementaryTransferSize); transferStart(this.ioBuffer, this.ioBufferIndex, size, ETF_ATAPI_COMMAND_REPLY_END); this.packetTransferSize -= size; this.elementaryTransferSize -= size; this.ioBufferIndex += size; } else { /* a new transfer is needed */ this.nSector = (this.nSector & ~7) | ATAPI_INT_REASON_IO; int byteCountLimit = (0xff & this.lcyl) | (0xff00 & (this.hcyl << 8)); if (byteCountLimit == 0xffff) byteCountLimit--; int size = this.packetTransferSize; if (size > byteCountLimit) { /* byte count limit must be even if this case */ if ((byteCountLimit & 1) != 0) byteCountLimit--; size = byteCountLimit; } this.lcyl = (byte)size; this.hcyl = (byte)(size >>> 8); this.elementaryTransferSize = size; /* we cannot transmit more than one sector at a time */ if (this.lba != -1) { size = Math.min(this.cdSectorSize - this.ioBufferIndex, size); } this.transferStart(this.ioBuffer, this.ioBufferIndex, size, ETF_ATAPI_COMMAND_REPLY_END); this.packetTransferSize -= size; this.elementaryTransferSize -= size; this.ioBufferIndex += size; this.setIRQ(); } } } private int atapiCommandReadDMACallback(int address, int size) { int originalSize = size; while (size > 0) { if (packetTransferSize <= 0) break; int length = cdSectorSize - ioBufferIndex; if (length <= 0) { cdReadSector(this.lba, this.ioBuffer, this.cdSectorSize); this.lba++; this.ioBufferIndex = 0; length = this.cdSectorSize; } if (length > size) length = size; bmdma.writeMemory(address, ioBuffer, ioBufferIndex, length); this.packetTransferSize -= length; this.ioBufferIndex += length; size -= length; address += length; } if (packetTransferSize <= 0) { this.status = READY_STAT; this.nSector = (this.nSector & ~0x7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; this.setIRQ(); return 0; } return originalSize - size; } private int cdromReadTOC(int nbSectors, byte[] buffer, int msf, int startTrack) { if ((startTrack > 1) && (startTrack != 0xaa)) return -1; int bufferOffset = 2; buffer[bufferOffset++] = 1; // first session buffer[bufferOffset++] = 1; // last session if (startTrack <= 1) { buffer[bufferOffset++] = 0; // reserved buffer[bufferOffset++] = 0x14; // ADR, control buffer[bufferOffset++] = 1; // track number buffer[bufferOffset++] = 0; // reserved if (msf != 0) { buffer[bufferOffset++] = 0; // reserved lbaToMSF(buff
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -