1 // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
\r
3 // This file is part of SCSI2SD.
\r
5 // SCSI2SD is free software: you can redistribute it and/or modify
\r
6 // it under the terms of the GNU General Public License as published by
\r
7 // the Free Software Foundation, either version 3 of the License, or
\r
8 // (at your option) any later version.
\r
10 // SCSI2SD is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
\r
18 #include "geometry.h"
\r
23 uint32_t getScsiCapacity()
\r
25 uint32_t capacity = sdDev.capacity / SDSectorsPerSCSISector();
\r
26 if (config->maxSectors && (capacity > config->maxSectors))
\r
28 capacity = config->maxSectors;
\r
34 uint32_t SCSISector2SD(uint32_t scsiSector)
\r
36 return scsiSector * SDSectorsPerSCSISector();
\r
39 // Standard mapping according to ECMA-107 and ISO/IEC 9293:1994
\r
40 // Sector always starts at 1. There is no 0 sector.
\r
41 uint64 CHS2LBA(uint32 c, uint8 h, uint32 s)
\r
44 (((uint64)c) * SCSI_HEADS_PER_CYLINDER + h) *
\r
45 (uint64) SCSI_SECTORS_PER_TRACK
\r
50 void LBA2CHS(uint32 lba, uint32* c, uint8* h, uint32* s)
\r
52 *c = lba / (SCSI_SECTORS_PER_TRACK * SCSI_HEADS_PER_CYLINDER);
\r
53 *h = (lba / SCSI_SECTORS_PER_TRACK) % SCSI_HEADS_PER_CYLINDER;
\r
54 *s = (lba % SCSI_SECTORS_PER_TRACK) + 1;
\r
57 uint64 scsiByteAddress(int format, const uint8* addr)
\r
65 (((uint32) addr[0]) << 24) +
\r
66 (((uint32) addr[1]) << 16) +
\r
67 (((uint32) addr[2]) << 8) +
\r
70 result = (uint64_t) config->bytesPerSector * lba;
\r
73 case ADDRESS_PHYSICAL_BYTE:
\r
76 (((uint32) addr[0]) << 16) +
\r
77 (((uint32) addr[1]) << 8) +
\r
80 uint8 head = addr[3];
\r
83 (((uint32) addr[4]) << 24) +
\r
84 (((uint32) addr[5]) << 16) +
\r
85 (((uint32) addr[6]) << 8) +
\r
88 result = CHS2LBA(cyl, head, 1) * (uint64_t) config->bytesPerSector + bytes;
\r
91 case ADDRESS_PHYSICAL_SECTOR:
\r
94 (((uint32) addr[0]) << 16) +
\r
95 (((uint32) addr[1]) << 8) +
\r
98 uint8 head = scsiDev.data[3];
\r
101 (((uint32) addr[4]) << 24) +
\r
102 (((uint32) addr[5]) << 16) +
\r
103 (((uint32) addr[6]) << 8) +
\r
106 result = CHS2LBA(cyl, head, sector) * (uint64_t) config->bytesPerSector;
\r
110 result = (uint64) -1;
\r
117 void scsiSaveByteAddress(int format, uint64 byteAddr, uint8* buf)
\r
119 uint32 lba = byteAddr / config->bytesPerSector;
\r
120 uint32 byteOffset = byteAddr % config->bytesPerSector;
\r
124 case ADDRESS_BLOCK:
\r
126 buf[0] = lba >> 24;
\r
127 buf[1] = lba >> 16;
\r
137 case ADDRESS_PHYSICAL_BYTE:
\r
144 LBA2CHS(lba, &cyl, &head, §or);
\r
146 bytes = sector * config->bytesPerSector + byteOffset;
\r
148 buf[0] = cyl >> 16;
\r
154 buf[4] = bytes >> 24;
\r
155 buf[5] = bytes >> 16;
\r
156 buf[6] = bytes >> 8;
\r
160 case ADDRESS_PHYSICAL_SECTOR:
\r
166 LBA2CHS(lba, &cyl, &head, §or);
\r
168 buf[0] = cyl >> 16;
\r
174 buf[4] = sector >> 24;
\r
175 buf[5] = sector >> 16;
\r
176 buf[6] = sector >> 8;
\r