summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kern/rbtree.h164
-rw-r--r--kern/startup.c4
-rw-r--r--linux/src/drivers/block/ide.c73
-rw-r--r--linux/src/drivers/block/ide.h3
4 files changed, 135 insertions, 109 deletions
diff --git a/kern/rbtree.h b/kern/rbtree.h
index c75e685..5a65d1e 100644
--- a/kern/rbtree.h
+++ b/kern/rbtree.h
@@ -117,23 +117,23 @@ static inline int rbtree_empty(const struct rbtree *tree)
*
* See rbtree_insert().
*/
-#define rbtree_lookup(tree, key, cmp_fn) \
-MACRO_BEGIN \
- struct rbtree_node *cur; \
- int diff; \
- \
- cur = (tree)->root; \
- \
- while (cur != NULL) { \
- diff = cmp_fn(key, cur); \
- \
- if (diff == 0) \
- break; \
- \
- cur = cur->children[rbtree_d2i(diff)]; \
- } \
- \
- cur; \
+#define rbtree_lookup(tree, key, cmp_fn) \
+MACRO_BEGIN \
+ struct rbtree_node *___cur; \
+ int ___diff; \
+ \
+ ___cur = (tree)->root; \
+ \
+ while (___cur != NULL) { \
+ ___diff = cmp_fn(key, ___cur); \
+ \
+ if (___diff == 0) \
+ break; \
+ \
+ ___cur = ___cur->children[rbtree_d2i(___diff)]; \
+ } \
+ \
+ ___cur; \
MACRO_END
/*
@@ -146,30 +146,30 @@ MACRO_END
* The constraints that apply to the key parameter are the same as for
* rbtree_lookup().
*/
-#define rbtree_lookup_nearest(tree, key, cmp_fn, dir) \
-MACRO_BEGIN \
- struct rbtree_node *cur, *prev; \
- int diff, index; \
- \
- prev = NULL; \
- index = -1; \
- cur = (tree)->root; \
- \
- while (cur != NULL) { \
- diff = cmp_fn(key, cur); \
- \
- if (diff == 0) \
- break; \
- \
- prev = cur; \
- index = rbtree_d2i(diff); \
- cur = cur->children[index]; \
- } \
- \
- if (cur == NULL) \
- cur = rbtree_nearest(prev, index, dir); \
- \
- cur; \
+#define rbtree_lookup_nearest(tree, key, cmp_fn, dir) \
+MACRO_BEGIN \
+ struct rbtree_node *___cur, *___prev; \
+ int ___diff, ___index; \
+ \
+ ___prev = NULL; \
+ ___index = -1; \
+ ___cur = (tree)->root; \
+ \
+ while (___cur != NULL) { \
+ ___diff = cmp_fn(key, ___cur); \
+ \
+ if (___diff == 0) \
+ break; \
+ \
+ ___prev = ___cur; \
+ ___index = rbtree_d2i(___diff); \
+ ___cur = ___cur->children[___index]; \
+ } \
+ \
+ if (___cur == NULL) \
+ ___cur = rbtree_nearest(___prev, ___index, dir); \
+ \
+ ___cur; \
MACRO_END
/*
@@ -188,24 +188,24 @@ MACRO_END
*
* See rbtree_lookup().
*/
-#define rbtree_insert(tree, node, cmp_fn) \
-MACRO_BEGIN \
- struct rbtree_node *cur, *prev; \
- int diff, index; \
- \
- prev = NULL; \
- index = -1; \
- cur = (tree)->root; \
- \
- while (cur != NULL) { \
- diff = cmp_fn(node, cur); \
- assert(diff != 0); \
- prev = cur; \
- index = rbtree_d2i(diff); \
- cur = cur->children[index]; \
- } \
- \
- rbtree_insert_rebalance(tree, prev, index, node); \
+#define rbtree_insert(tree, node, cmp_fn) \
+MACRO_BEGIN \
+ struct rbtree_node *___cur, *___prev; \
+ int ___diff, ___index; \
+ \
+ ___prev = NULL; \
+ ___index = -1; \
+ ___cur = (tree)->root; \
+ \
+ while (___cur != NULL) { \
+ ___diff = cmp_fn(node, ___cur); \
+ assert(___diff != 0); \
+ ___prev = ___cur; \
+ ___index = rbtree_d2i(___diff); \
+ ___cur = ___cur->children[___index]; \
+ } \
+ \
+ rbtree_insert_rebalance(tree, ___prev, ___index, node); \
MACRO_END
/*
@@ -222,26 +222,26 @@ MACRO_END
*/
#define rbtree_lookup_slot(tree, key, cmp_fn, slot) \
MACRO_BEGIN \
- struct rbtree_node *cur, *prev; \
- int diff, index; \
+ struct rbtree_node *___cur, *___prev; \
+ int ___diff, ___index; \
\
- prev = NULL; \
- index = 0; \
- cur = (tree)->root; \
+ ___prev = NULL; \
+ ___index = 0; \
+ ___cur = (tree)->root; \
\
- while (cur != NULL) { \
- diff = cmp_fn(key, cur); \
+ while (___cur != NULL) { \
+ ___diff = cmp_fn(key, ___cur); \
\
- if (diff == 0) \
+ if (___diff == 0) \
break; \
\
- prev = cur; \
- index = rbtree_d2i(diff); \
- cur = cur->children[index]; \
+ ___prev = ___cur; \
+ ___index = rbtree_d2i(___diff); \
+ ___cur = ___cur->children[___index]; \
} \
\
- (slot) = rbtree_slot(prev, index); \
- cur; \
+ (slot) = rbtree_slot(___prev, ___index); \
+ ___cur; \
MACRO_END
/*
@@ -253,15 +253,17 @@ MACRO_END
* must not compare equal to an existing node in the tree (i.e. the slot
* must denote a null node).
*/
-#define rbtree_insert_slot(tree, slot, node) \
-MACRO_BEGIN \
- struct rbtree_node *parent; \
- int index; \
- \
- parent = rbtree_slot_parent(slot); \
- index = rbtree_slot_index(slot); \
- rbtree_insert_rebalance(tree, parent, index, node); \
-MACRO_END
+static inline void
+rbtree_insert_slot(struct rbtree *tree, unsigned long slot,
+ struct rbtree_node *node)
+{
+ struct rbtree_node *parent;
+ int index;
+
+ parent = rbtree_slot_parent(slot);
+ index = rbtree_slot_index(slot);
+ rbtree_insert_rebalance(tree, parent, index, node);
+}
/*
* Remove a node from a tree.
diff --git a/kern/startup.c b/kern/startup.c
index 3bdda16..6dced43 100644
--- a/kern/startup.c
+++ b/kern/startup.c
@@ -141,10 +141,10 @@ void setup_main()
timestamp_init();
- mapable_time_init();
-
machine_init();
+ mapable_time_init();
+
machine_info.max_cpus = NCPUS;
machine_info.memory_size = phys_last_addr - phys_first_addr; /* XXX mem_size */
machine_info.avail_cpus = 0;
diff --git a/linux/src/drivers/block/ide.c b/linux/src/drivers/block/ide.c
index cfd8b5b..7ab790d 100644
--- a/linux/src/drivers/block/ide.c
+++ b/linux/src/drivers/block/ide.c
@@ -604,6 +604,9 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int t
*
* Returns: 1 if lba_capacity looks sensible
* 0 otherwise
+ *
+ * Note: we must not change id->cyls here, otherwise a second call
+ * of this routine might no longer find lba_capacity ok.
*/
static int lba_capacity_is_ok (struct hd_driveid *id)
{
@@ -611,10 +614,16 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
unsigned long chs_sects = id->cyls * id->heads * id->sectors;
unsigned long _10_percent = chs_sects / 10;
- /* very large drives (8GB+) may lie about the number of cylinders */
- if (id->cyls == 16383 && id->heads == 16 && id->sectors == 63 && lba_sects > chs_sects) {
+ /*
+ * The ATA spec tells large drives to return
+ * C/H/S = 16383/16/63 independent of their size.
+ * Some drives can be jumpered to use 15 heads instead of 16.
+ */
+ if (id->cyls == 16383 && id->sectors == 63 &&
+ (id->heads == 15 || id->heads == 16) &&
+ id->lba_capacity >= 16383*63*id->heads)
return 1; /* lba_capacity is our only option */
- }
+
/* perform a rough sanity check on lba_sects: within 10% is "okay" */
if ((lba_sects - chs_sects) < _10_percent)
return 1; /* lba_capacity is good */
@@ -631,11 +640,13 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
/*
* current_capacity() returns the capacity (in sectors) of a drive
* according to its current geometry/LBA settings.
+ *
+ * It also sets select.b.lba.
*/
static unsigned long current_capacity (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
- unsigned long capacity = drive->cyl * drive->head * drive->sect;
+ unsigned long capacity;
if (!drive->present)
return 0;
@@ -645,8 +656,10 @@ static unsigned long current_capacity (ide_drive_t *drive)
#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
if (drive->media != ide_disk)
return 0x7fffffff; /* cdrom or tape */
+
drive->select.b.lba = 0;
/* Determine capacity, and use LBA if the drive properly supports it */
+ capacity = drive->cyl * drive->head * drive->sect;
if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) {
if (id->lba_capacity >= capacity) {
capacity = id->lba_capacity;
@@ -2568,8 +2581,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
}
/* Handle logical geometry translation by the drive */
if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads
- && (id->cur_heads <= 16) && id->cur_sectors)
- {
+ && (id->cur_heads <= 16) && id->cur_sectors) {
/*
* Extract the physical drive geometry for our use.
* Note that we purposely do *not* update the bios info.
@@ -2594,7 +2606,8 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
}
}
/* Use physical geometry if what we have still makes no sense */
- if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) {
+ if ((!drive->head || drive->head > 16) &&
+ id->heads && id->heads <= 16) {
drive->cyl = id->cyls;
drive->head = id->heads;
drive->sect = id->sectors;
@@ -2603,21 +2616,22 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
/* calculate drive capacity, and select LBA if possible */
capacity = current_capacity (drive);
- /* Correct the number of cyls if the bios value is too small */
- if (!drive->forced_geom &&
- capacity > drive->bios_cyl * drive->bios_sect * drive->bios_head) {
- unsigned long cylsize;
- cylsize = drive->bios_sect * drive->bios_head;
- if (cylsize == 0 || capacity/cylsize > 65535) {
- drive->bios_sect = 63;
- drive->bios_head = 255;
- cylsize = 63*255;
- }
- if (capacity/cylsize > 65535)
- drive->bios_cyl = 65535;
- else
- drive->bios_cyl = capacity/cylsize;
- }
+ /*
+ * if possible, give fdisk access to more of the drive,
+ * by correcting bios_cyls:
+ */
+ if (capacity > drive->bios_cyl * drive->bios_head * drive->bios_sect
+ && !drive->forced_geom && drive->bios_sect && drive->bios_head) {
+ int cyl = (capacity / drive->bios_sect) / drive->bios_head;
+ if (cyl <= 65535)
+ drive->bios_cyl = cyl;
+ else {
+ /* OK until 539 GB */
+ drive->bios_sect = 63;
+ drive->bios_head = 255;
+ drive->bios_cyl = capacity / (63*255);
+ }
+ }
if (!strncmp((char *)id->model, "BMI ", 4) &&
strstr((char *)id->model, " ENHANCED IDE ") &&
@@ -3346,7 +3360,7 @@ done:
* This routine is called from the partition-table code in genhd.c
* to "convert" a drive to a logical geometry with fewer than 1024 cyls.
*
- * The second parameter, "xparm", determines exactly how the translation
+ * The second parameter, "xparm", determines exactly how the translation
* will be handled:
* 0 = convert to CHS with fewer than 1024 cyls
* using the same method as Ontrack DiskManager.
@@ -3354,10 +3368,11 @@ done:
* -1 = similar to "0", plus redirect sector 0 to sector 1.
* >1 = convert to a CHS geometry with "xparm" heads.
*
- * Returns 0 if the translation was not possible, if the device was not
+ * Returns 0 if the translation was not possible, if the device was not
* an IDE disk drive, or if a geometry was "forced" on the commandline.
* Returns 1 if the geometry translation was successful.
*/
+
int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
{
ide_drive_t *drive;
@@ -3365,7 +3380,11 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
const byte *heads = head_vals;
unsigned long tracks;
- if ((drive = get_info_ptr(i_rdev)) == NULL || drive->forced_geom)
+ drive = get_info_ptr(i_rdev);
+ if (!drive)
+ return 0;
+
+ if (drive->forced_geom)
return 0;
if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63)
@@ -3373,6 +3392,10 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
printk("%s ", msg);
+ if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) {
+ return 0; /* small disk: no translation needed */
+ }
+
if (drive->id) {
drive->cyl = drive->id->cyls;
drive->head = drive->id->heads;
diff --git a/linux/src/drivers/block/ide.h b/linux/src/drivers/block/ide.h
index 3351390..edeedc9 100644
--- a/linux/src/drivers/block/ide.h
+++ b/linux/src/drivers/block/ide.h
@@ -152,7 +152,8 @@ typedef unsigned char byte; /* used everywhere */
/*
* Timeouts for various operations:
*/
-#define WAIT_DRQ (5*HZ/100) /* 50msec - spec allows up to 20ms */
+#define WAIT_DRQ (1*HZ) /* 1s - spec allows up to 20ms, but CF
+ * cards and SSD drives need more */
#ifdef CONFIG_APM
#define WAIT_READY (5*HZ) /* 5sec - some laptops are very slow */
#else