diff options
-rw-r--r-- | kern/rbtree.h | 164 | ||||
-rw-r--r-- | kern/startup.c | 4 | ||||
-rw-r--r-- | linux/src/drivers/block/ide.c | 73 | ||||
-rw-r--r-- | linux/src/drivers/block/ide.h | 3 |
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 |