aboutsummaryrefslogtreecommitdiff
path: root/inc/scsi.h
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2026-10-26 00:50:06 +0100
committerJavier <dev.git@javispedro.com>2026-10-26 00:50:06 +0100
commit6b8a368c51082fdd010ef5e1b0be4eb9b5059d1a (patch)
treee274d41a8dd5e912e20617a937a1fda5af91f8de /inc/scsi.h
parent9b1cf601360fb194047e6dcc2af75c2f38c611ec (diff)
downloadchu-6b8a368c51082fdd010ef5e1b0be4eb9b5059d1a.tar.gz
chu-6b8a368c51082fdd010ef5e1b0be4eb9b5059d1a.zip
refactor common parts into inc/ch375.h and add win9x, linux drivers
Diffstat (limited to 'inc/scsi.h')
-rw-r--r--inc/scsi.h61
1 files changed, 61 insertions, 0 deletions
diff --git a/inc/scsi.h b/inc/scsi.h
new file mode 100644
index 0000000..a9d8b05
--- /dev/null
+++ b/inc/scsi.h
@@ -0,0 +1,61 @@
+#ifndef SCSICAM_H
+#define SCSICAM_H
+
+/** (from SCSICAM) converts a capacitity in sectors to CHS
+ * keeps cylinders <= 1024 and sectors <= 62,
+ * but may give very large head numbers, though. */
+static int setsize(unsigned long capacity, unsigned int *cyls, unsigned int *hds, unsigned int *secs)
+{
+ unsigned int rv = 0;
+ unsigned long heads, sectors, cylinders, temp;
+
+ cylinders = 1024L; /* Set number of cylinders to max */
+ sectors = 62L; /* Maximize sectors per track */
+
+ temp = cylinders * sectors; /* Compute divisor for heads */
+ heads = capacity / temp; /* Compute value for number of heads */
+ if (capacity % temp) { /* If no remainder, done! */
+ heads++; /* Else, increment number of heads */
+ temp = cylinders * heads; /* Compute divisor for sectors */
+ sectors = capacity / temp; /* Compute value for sectors per
+ track */
+ if (capacity % temp) { /* If no remainder, done! */
+ sectors++; /* Else, increment number of sectors */
+ temp = heads * sectors; /* Compute divisor for cylinders */
+ cylinders = capacity / temp; /* Compute number of cylinders */
+ }
+ }
+ if (cylinders == 0)
+ rv = (unsigned) -1; /* Give error if 0 cylinders */
+
+ *cyls = (unsigned int) cylinders; /* Stuff return values */
+ *secs = (unsigned int) sectors;
+ *hds = (unsigned int) heads;
+ return (rv);
+}
+
+static void guess_geometry(uint32_t num_sectors, unsigned int *cyls, unsigned int *hds, unsigned int *secs)
+{
+ unsigned int cylinders, heads, sectors;
+ // First try to use SCSI CAM approach
+ if (setsize(num_sectors, &cylinders, &heads, &sectors) != 0
+ || cylinders > 1024 || heads > 255 || sectors > 63) {
+ // Didn't work. So now we just use max heads and sectors but a crazy number of cyls
+ if (num_sectors <= 64 * 32 * 65534) {
+ // This follows the same behavior as Linux,
+ // which uses smaller values for heads/sects as long as cyls fits < 65535
+ heads = 64;
+ sectors = 32;
+ } else {
+ heads = 255;
+ sectors = 63;
+ }
+ cylinders = num_sectors / (heads * sectors);
+ }
+
+ *cyls = cylinders;
+ *hds = heads;
+ *secs = sectors;
+}
+
+#endif // SCSICAM_H