summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Purchase <shotofadds@rockbox.org>2008-11-16 15:44:49 +0000
committerRob Purchase <shotofadds@rockbox.org>2008-11-16 15:44:49 +0000
commit93f3367f42326b688968d25607c2cc910eedb815 (patch)
treed02b047e274ff38f84963ab1d2cea6a12a899175
parentbd49ec97b24ac17702743378605783395a65d0bc (diff)
downloadrockbox-93f3367f42326b688968d25607c2cc910eedb815.tar.gz
rockbox-93f3367f42326b688968d25607c2cc910eedb815.zip
Telechips NAND: much improved read reliability on D2/iAudio7. More work is required for M200/DAX, but an improvement is evident nonetheless. LPT buffers are now buffer_alloc'd after determining the required size, so most targets should also see a healthy reduction in RAM usage.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19118 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/ata-nand-telechips.c415
1 files changed, 212 insertions, 203 deletions
diff --git a/firmware/target/arm/ata-nand-telechips.c b/firmware/target/arm/ata-nand-telechips.c
index a6a901d222..60d2211977 100644
--- a/firmware/target/arm/ata-nand-telechips.c
+++ b/firmware/target/arm/ata-nand-telechips.c
@@ -25,18 +25,11 @@
25#include "led.h" 25#include "led.h"
26#include "panic.h" 26#include "panic.h"
27#include "nand_id.h" 27#include "nand_id.h"
28
29/* The NAND driver is currently work-in-progress and as such contains
30 some dead code and debug stuff, such as the next few lines. */
31#include "lcd.h"
32#include "font.h"
33#include "button.h"
34#include "storage.h" 28#include "storage.h"
35#include <sprintf.h> 29#include "buffer.h"
36 30
37#define SECTOR_SIZE 512 31#define SECTOR_SIZE 512
38 32
39/* #define USE_TCC_LPT */
40/* #define USE_ECC_CORRECTION */ 33/* #define USE_ECC_CORRECTION */
41 34
42/* for compatibility */ 35/* for compatibility */
@@ -50,31 +43,41 @@ static bool initialized = false;
50static struct mutex ata_mtx SHAREDBSS_ATTR; 43static struct mutex ata_mtx SHAREDBSS_ATTR;
51 44
52#if defined(COWON_D2) || defined(IAUDIO_7) 45#if defined(COWON_D2) || defined(IAUDIO_7)
53#define SEGMENT_ID_BIGENDIAN 46#define FTL_V2
54#define BLOCKS_PER_SEGMENT 4 47#define BLOCKS_PER_SEGMENT 4
48#define MAX_WRITE_CACHES 8
55#else 49#else
50#define FTL_V1
56#define BLOCKS_PER_SEGMENT 1 51#define BLOCKS_PER_SEGMENT 1
52#define MAX_WRITE_CACHES 4
57#endif 53#endif
58/* NB: blocks_per_segment should become a runtime check based on NAND id */
59 54
60/* Segment type identifiers - main data area */ 55/* Sector type identifiers - main data area */
61#define SEGMENT_MAIN_LPT 0x12 56
62#define SEGMENT_MAIN_DATA1 0x13 57#define SECTYPE_MAIN_LPT 0x12
63#define SEGMENT_MAIN_CACHE 0x15 58#define SECTYPE_MAIN_DATA 0x13
64#define SEGMENT_MAIN_DATA2 0x17 59#define SECTYPE_MAIN_RANDOM_CACHE 0x15
60#define SECTYPE_MAIN_INPLACE_CACHE 0x17
65 61
66/* We don't touch the hidden area at all - these are for reference */ 62/* We don't touch the hidden area at all - these are for reference */
67#define SEGMENT_HIDDEN_LPT 0x22 63#define SECTYPE_HIDDEN_LPT 0x22
68#define SEGMENT_HIDDEN_DATA1 0x23 64#define SECTYPE_HIDDEN_DATA 0x23
69#define SEGMENT_HIDDEN_CACHE 0x25 65#define SECTYPE_HIDDEN_RANDOM_CACHE 0x25
70#define SEGMENT_HIDDEN_DATA2 0x27 66#define SECTYPE_HIDDEN_INPLACE_CACHE 0x27
67
68#ifdef FTL_V1
69#define SECTYPE_FIRMWARE 0x40
70#else
71#define SECTYPE_FIRMWARE 0xE0
72#endif
73
74/* Offsets to data within sector's spare area */
71 75
72/* Offsets to spare area data */
73#define OFF_CACHE_PAGE_LOBYTE 2 76#define OFF_CACHE_PAGE_LOBYTE 2
74#define OFF_CACHE_PAGE_HIBYTE 3 77#define OFF_CACHE_PAGE_HIBYTE 3
75#define OFF_SEGMENT_TYPE 4 78#define OFF_SECTOR_TYPE 4
76 79
77#ifdef SEGMENT_ID_BIGENDIAN 80#ifdef FTL_V2
78#define OFF_LOG_SEG_LOBYTE 7 81#define OFF_LOG_SEG_LOBYTE 7
79#define OFF_LOG_SEG_HIBYTE 6 82#define OFF_LOG_SEG_HIBYTE 6
80#else 83#else
@@ -114,29 +117,29 @@ struct lpt_entry
114 short bank; 117 short bank;
115 short phys_segment; 118 short phys_segment;
116}; 119};
120#ifdef BOOTLOADER
117static struct lpt_entry lpt_lookup[MAX_SEGMENTS]; 121static struct lpt_entry lpt_lookup[MAX_SEGMENTS];
122#else
123/* buffer_alloc'd in nand_init() when the correct size has been determined */
124static struct lpt_entry* lpt_lookup = NULL;
125#endif
118 126
119/* Write Caches */ 127/* Write Caches */
120 128
121#define MAX_WRITE_CACHES 8
122
123struct write_cache 129struct write_cache
124{ 130{
125 short bank;
126 short phys_segment;
127 short log_segment; 131 short log_segment;
132 short inplace_bank;
133 short inplace_phys_segment;
134 short inplace_pages_used;
135 short random_bank;
136 short random_phys_segment;
128 short page_map[MAX_PAGES_PER_BLOCK * BLOCKS_PER_SEGMENT]; 137 short page_map[MAX_PAGES_PER_BLOCK * BLOCKS_PER_SEGMENT];
129}; 138};
130static struct write_cache write_caches[MAX_WRITE_CACHES]; 139static struct write_cache write_caches[MAX_WRITE_CACHES];
131 140
132static int write_caches_in_use = 0; 141static int write_caches_in_use = 0;
133 142
134#ifdef USE_TCC_LPT
135/* Read buffer (used for reading LPT blocks only) */
136static unsigned char page_buf[MAX_PAGE_SIZE + MAX_SPARE_SIZE]
137 __attribute__ ((aligned (4)));
138#endif
139
140#ifdef USE_ECC_CORRECTION 143#ifdef USE_ECC_CORRECTION
141static unsigned int ecc_sectors_corrected = 0; 144static unsigned int ecc_sectors_corrected = 0;
142static unsigned int ecc_bits_corrected = 0; 145static unsigned int ecc_bits_corrected = 0;
@@ -501,18 +504,30 @@ static bool nand_read_sector_of_logical_segment(int log_segment, int sector,
501 504
502 while (!found && cache_num < write_caches_in_use) 505 while (!found && cache_num < write_caches_in_use)
503 { 506 {
504 if (write_caches[cache_num].log_segment == log_segment 507 if (write_caches[cache_num].log_segment == log_segment)
505 && write_caches[cache_num].page_map[page_in_segment] != -1)
506 {
507 found = true;
508 bank = write_caches[cache_num].bank;
509 phys_segment = write_caches[cache_num].phys_segment;
510 page_in_segment = write_caches[cache_num].page_map[page_in_segment];
511 }
512 else
513 { 508 {
514 cache_num++; 509 if (write_caches[cache_num].page_map[page_in_segment] != -1)
510 {
511 /* data is located in random pages cache */
512 found = true;
513
514 bank = write_caches[cache_num].random_bank;
515 phys_segment = write_caches[cache_num].random_phys_segment;
516
517 page_in_segment =
518 write_caches[cache_num].page_map[page_in_segment];
519 }
520 else if (write_caches[cache_num].inplace_pages_used != -1 &&
521 write_caches[cache_num].inplace_pages_used > page_in_segment)
522 {
523 /* data is located in in-place pages cache */
524 found = true;
525
526 bank = write_caches[cache_num].inplace_bank;
527 phys_segment = write_caches[cache_num].inplace_phys_segment;
528 }
515 } 529 }
530 cache_num++;
516 } 531 }
517 532
518 return nand_read_sector_of_phys_segment(bank, phys_segment, 533 return nand_read_sector_of_phys_segment(bank, phys_segment,
@@ -523,15 +538,21 @@ static bool nand_read_sector_of_logical_segment(int log_segment, int sector,
523 538
524/* Miscellaneous helper functions */ 539/* Miscellaneous helper functions */
525 540
526static inline char get_segment_type(char* spare_buf) 541static inline unsigned char get_sector_type(char* spare_buf)
527{ 542{
528 return spare_buf[OFF_SEGMENT_TYPE]; 543 return spare_buf[OFF_SECTOR_TYPE];
529} 544}
530 545
531static inline unsigned short get_log_segment_id(char* spare_buf) 546static inline unsigned short get_log_segment_id(int phys_seg, char* spare_buf)
532{ 547{
533 return (spare_buf[OFF_LOG_SEG_HIBYTE] << 8) | 548 (void)phys_seg;
534 spare_buf[OFF_LOG_SEG_LOBYTE]; 549
550 return ((spare_buf[OFF_LOG_SEG_HIBYTE] << 8) |
551 spare_buf[OFF_LOG_SEG_LOBYTE])
552#if defined(FTL_V1)
553 + 984 * (phys_seg / 1024)
554#endif
555 ;
535} 556}
536 557
537static inline unsigned short get_cached_page_id(char* spare_buf) 558static inline unsigned short get_cached_page_id(char* spare_buf)
@@ -540,123 +561,123 @@ static inline unsigned short get_cached_page_id(char* spare_buf)
540 spare_buf[OFF_CACHE_PAGE_LOBYTE]; 561 spare_buf[OFF_CACHE_PAGE_LOBYTE];
541} 562}
542 563
564static int find_write_cache(int log_segment)
565{
566 int i;
543 567
568 for (i = 0; i < write_caches_in_use; i++)
569 if (write_caches[i].log_segment == log_segment)
570 return i;
544 571
545#ifdef USE_TCC_LPT 572 return -1;
573}
546 574
547/* Reading the LPT from NAND is not yet fully understood. This code is therefore
548 not enabled by default, as it gives much worse results than the bank-scanning
549 approach currently used.
550
551 The LPT is stored in a number of physical segments marked with type 0x12.
552 These are spread non-contiguously across the NAND, and are not stored in
553 sequential order.
554
555 The LPT data is stored in Sector 0 of the first <n> pages of each segment.
556 Each 32-bit value in sequence represents the physical location of a logical
557 segment. This is stored as (physical segment number * bank number).
558
559 NOTE: The bank numbers stored appear to be in reverse order to that required
560 by the nand_chip_select() function. The reason for this anomoly is unknown.
561*/
562 575
563static void read_lpt_block(int bank, int phys_segment) 576static void read_random_writes_cache(int bank, int phys_segment)
564{ 577{
565 int page = 1; /* table starts at page 1 of segment */ 578 int page = 0;
566 bool cont = true; 579 short log_segment;
567 580 unsigned char spare_buf[16];
568 struct lpt_entry* lpt_ptr = NULL;
569
570 while (cont && page < pages_per_block)
571 {
572 int i = 0;
573 unsigned int* int_buf = (int*)page_buf;
574
575 nand_read_sector_of_phys_segment(bank, phys_segment,
576 page, 0, /* only sector 0 is used */
577 page_buf);
578
579 /* Find out which chunk of the LPT table this section contains.
580 Do this by reading the logical segment number of entry 0 */
581 if (lpt_ptr == NULL)
582 {
583 int first_bank = int_buf[0] / segments_per_bank;
584 int first_phys_segment = int_buf[0] % segments_per_bank;
585
586 /* Reverse the stored bank number */
587 if (total_banks > 1)
588 first_bank = (total_banks-1) - first_bank;
589 581
590 unsigned char spare_buf[16]; 582 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page),
583 SECTOR_SIZE, /* offset to first sector's spare */
584 16, spare_buf);
591 585
592 nand_read_raw(first_bank, 586 log_segment = get_log_segment_id(phys_segment, spare_buf);
593 phys_segment_to_page_addr(first_phys_segment, 0), 587
594 SECTOR_SIZE, /* offset */ 588 if (log_segment == -1)
595 16, spare_buf); 589 return;
596 590
597 int first_log_segment = get_log_segment_id(spare_buf); 591 /* Find which cache this is related to */
592 int cache_no = find_write_cache(log_segment);
598 593
599 lpt_ptr = &lpt_lookup[first_log_segment]; 594 if (cache_no == -1)
595 {
596 if (write_caches_in_use < MAX_WRITE_CACHES)
597 {
598 cache_no = write_caches_in_use;
599 write_caches_in_use++;
600 } 600 }
601 601 else
602 while (cont && (i < SECTOR_SIZE/4))
603 { 602 {
604 if (int_buf[i] != 0xFFFFFFFF) 603 panicf("Max NAND write caches reached");
605 {
606 int bank = int_buf[i] / segments_per_bank;
607 int phys_segment = int_buf[i] % segments_per_bank;
608
609 /* Reverse the stored bank number */
610 if (total_banks > 1)
611 bank = (total_banks-1) - bank;
612
613 lpt_ptr->bank = bank;
614 lpt_ptr->phys_segment = phys_segment;
615
616 lpt_ptr++;
617 i++;
618 }
619 else cont = false;
620 } 604 }
621 page++;
622 } 605 }
623}
624
625#endif /* USE_TCC_LPT */
626 606
607 write_caches[cache_no].log_segment = log_segment;
608 write_caches[cache_no].random_bank = bank;
609 write_caches[cache_no].random_phys_segment = phys_segment;
627 610
628static void read_write_cache_segment(int bank, int phys_segment) 611#ifndef FTL_V1
629{
630 int page;
631 unsigned char spare_buf[16];
632
633 if (write_caches_in_use == MAX_WRITE_CACHES)
634 panicf("Max NAND write caches reached");
635
636 write_caches[write_caches_in_use].bank = bank;
637 write_caches[write_caches_in_use].phys_segment = phys_segment;
638
639 /* Loop over each page in the phys segment (from page 1 onwards). 612 /* Loop over each page in the phys segment (from page 1 onwards).
640 Read spare for 1st sector, store location of page in array. */ 613 Read spare for 1st sector, store location of page in array. */
641 for (page = 1; page < pages_per_block * BLOCKS_PER_SEGMENT; page++) 614 for (page = 1; page < pages_per_block * BLOCKS_PER_SEGMENT; page++)
642 { 615 {
643 unsigned short cached_page; 616 unsigned short cached_page;
644 unsigned short log_segment;
645 617
646 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page), 618 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page),
647 SECTOR_SIZE, /* offset to first sector's spare */ 619 SECTOR_SIZE, /* offset to first sector's spare */
648 16, spare_buf); 620 16, spare_buf);
649 621
650 cached_page = get_cached_page_id(spare_buf); 622 cached_page = get_cached_page_id(spare_buf);
651 log_segment = get_log_segment_id(spare_buf); 623
652
653 if (cached_page != 0xFFFF) 624 if (cached_page != 0xFFFF)
625 write_caches[cache_no].page_map[cached_page] = page;
626 }
627#endif /* !FTL_V1 */
628}
629
630
631static void read_inplace_writes_cache(int bank, int phys_segment)
632{
633 int page = 0;
634 short log_segment;
635 unsigned char spare_buf[16];
636
637 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page),
638 SECTOR_SIZE, /* offset to first sector's spare */
639 16, spare_buf);
640
641 log_segment = get_log_segment_id(phys_segment, spare_buf);
642
643 if (log_segment == -1)
644 return;
645
646 /* Find which cache this is related to */
647 int cache_no = find_write_cache(log_segment);
648
649 if (cache_no == -1)
650 {
651 if (write_caches_in_use < MAX_WRITE_CACHES)
652 {
653 cache_no = write_caches_in_use;
654 write_caches_in_use++;
655 }
656 else
654 { 657 {
655 write_caches[write_caches_in_use].log_segment = log_segment; 658 panicf("Max NAND write caches reached");
656 write_caches[write_caches_in_use].page_map[cached_page] = page;
657 } 659 }
658 } 660 }
659 write_caches_in_use++; 661
662 write_caches[cache_no].log_segment = log_segment;
663
664 /* Find how many pages have been written to the new segment */
665 while (log_segment != -1 &&
666 page < (pages_per_block * BLOCKS_PER_SEGMENT) - 1)
667 {
668 page++;
669 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, page),
670 SECTOR_SIZE, 16, spare_buf);
671
672 log_segment = get_log_segment_id(phys_segment, spare_buf);
673 }
674
675 if (page != 0)
676 {
677 write_caches[cache_no].inplace_bank = bank;
678 write_caches[cache_no].inplace_phys_segment = phys_segment;
679 write_caches[cache_no].inplace_pages_used = page;
680 }
660} 681}
661 682
662 683
@@ -700,6 +721,7 @@ int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int incount,
700 return 0; 721 return 0;
701} 722}
702 723
724
703int nand_write_sectors(IF_MV2(int drive,) unsigned long start, int count, 725int nand_write_sectors(IF_MV2(int drive,) unsigned long start, int count,
704 const void* outbuf) 726 const void* outbuf)
705{ 727{
@@ -714,6 +736,7 @@ int nand_write_sectors(IF_MV2(int drive,) unsigned long start, int count,
714 return -1; 736 return -1;
715} 737}
716 738
739
717#ifdef STORAGE_GET_INFO 740#ifdef STORAGE_GET_INFO
718void nand_get_info(struct storage_info *info) 741void nand_get_info(struct storage_info *info)
719{ 742{
@@ -724,15 +747,15 @@ void nand_get_info(struct storage_info *info)
724 info->product="Internal Storage"; 747 info->product="Internal Storage";
725 748
726 /* blocks count */ 749 /* blocks count */
727 info->num_sectors = (pages_per_block * blocks_per_bank / SECTOR_SIZE) 750 info->num_sectors = sectors_per_segment * segments_per_bank * total_banks;
728 * page_size * total_banks; 751 info->sector_size = SECTOR_SIZE;
729 info->sector_size=SECTOR_SIZE;
730} 752}
731#endif 753#endif
732 754
755
733int nand_init(void) 756int nand_init(void)
734{ 757{
735 int i, bank, phys_segment; 758 int bank, phys_segment, lptbuf_size;
736 unsigned char spare_buf[16]; 759 unsigned char spare_buf[16];
737 760
738 if (initialized) return 0; 761 if (initialized) return 0;
@@ -750,28 +773,20 @@ int nand_init(void)
750 /* Get chip characteristics and number of banks */ 773 /* Get chip characteristics and number of banks */
751 nand_get_chip_info(); 774 nand_get_chip_info();
752 775
753 for (i = 0; i < MAX_SEGMENTS; i++) 776#ifndef BOOTLOADER
754 { 777 /* Use chip info to allocate the correct size LPT buffer */
755 lpt_lookup[i].bank = -1; 778 lptbuf_size = sizeof(struct lpt_entry) * segments_per_bank * total_banks;
756 lpt_lookup[i].phys_segment = -1; 779 lpt_lookup = buffer_alloc(lptbuf_size);
757 } 780#else
781 /* Use a static array in the bootloader */
782 lptbuf_size = sizeof(lpt_lookup);
783#endif
758 784
785 memset(lpt_lookup, 0xff, lptbuf_size);
786 memset(write_caches, 0xff, sizeof(write_caches));
787
759 write_caches_in_use = 0; 788 write_caches_in_use = 0;
760 789
761 for (i = 0; i < MAX_WRITE_CACHES; i++)
762 {
763 int page;
764
765 write_caches[i].log_segment = -1;
766 write_caches[i].bank = -1;
767 write_caches[i].phys_segment = -1;
768
769 for (page = 0; page < MAX_PAGES_PER_BLOCK * BLOCKS_PER_SEGMENT; page++)
770 {
771 write_caches[i].page_map[page] = -1;
772 }
773 }
774
775 /* Scan banks to build up block translation table */ 790 /* Scan banks to build up block translation table */
776 for (bank = 0; bank < total_banks; bank++) 791 for (bank = 0; bank < total_banks; bank++)
777 { 792 {
@@ -781,71 +796,65 @@ int nand_init(void)
781 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, 0), 796 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, 0),
782 SECTOR_SIZE, /* offset */ 797 SECTOR_SIZE, /* offset */
783 16, spare_buf); 798 16, spare_buf);
784 799
785 switch (get_segment_type(spare_buf)) 800 int type = get_sector_type(spare_buf);
801
802 if (type == SECTYPE_MAIN_INPLACE_CACHE)
786 { 803 {
787#ifdef USE_TCC_LPT 804 /* Check last sector of sequential write cache block */
788 case SEGMENT_MAIN_LPT: 805 nand_read_raw(bank,
806 phys_segment_to_page_addr(phys_segment,
807 (pages_per_block * BLOCKS_PER_SEGMENT) - 1),
808 page_size + spare_size - 16,
809 16, spare_buf);
810
811 /* If last sector has been written, treat block as main data */
812 if (get_sector_type(spare_buf) != 0xff)
789 { 813 {
790 /* Log->Phys Translation table (for Main data area) */ 814 type = SECTYPE_MAIN_DATA;
791 read_lpt_block(bank, phys_segment);
792 break;
793 } 815 }
794#else 816 }
795 case SEGMENT_MAIN_DATA2: 817
818 switch (type)
819 {
820 case SECTYPE_MAIN_DATA:
796 { 821 {
797 /* Main data area segment */ 822 /* Main data area segment */
798 unsigned short log_segment = get_log_segment_id(spare_buf); 823 unsigned short log_segment =
824 get_log_segment_id(phys_segment, spare_buf);
799 825
800 if (log_segment < MAX_SEGMENTS) 826 if (log_segment < segments_per_bank * total_banks)
801 { 827 {
802 lpt_lookup[log_segment].bank = bank; 828 if (lpt_lookup[log_segment].bank == -1 ||
803 lpt_lookup[log_segment].phys_segment = phys_segment; 829 lpt_lookup[log_segment].phys_segment == -1)
830 {
831 lpt_lookup[log_segment].bank = bank;
832 lpt_lookup[log_segment].phys_segment = phys_segment;
833 }
834 else
835 {
836 //panicf("duplicate data segment 0x%x!", log_segment);
837 }
804 } 838 }
805 break; 839 break;
806 } 840 }
807#endif 841
808 842 case SECTYPE_MAIN_RANDOM_CACHE:
809 case SEGMENT_MAIN_CACHE:
810 { 843 {
811 /* Recently-written page data (for Main data area) */ 844 /* Newly-written random page data (Main data area) */
812 read_write_cache_segment(bank, phys_segment); 845 read_random_writes_cache(bank, phys_segment);
813 break; 846 break;
814 } 847 }
815 } 848
816 } 849 case SECTYPE_MAIN_INPLACE_CACHE:
817 }
818
819#ifndef USE_TCC_LPT
820 /* Scan banks a second time as 0x13 segments appear to override 0x17 */
821 for (bank = 0; bank < total_banks; bank++)
822 {
823 for (phys_segment = 0; phys_segment < segments_per_bank; phys_segment++)
824 {
825 /* Read spare bytes from first sector of each segment */
826 nand_read_raw(bank, phys_segment_to_page_addr(phys_segment, 0),
827 SECTOR_SIZE, /* offset */
828 16, spare_buf);
829
830 switch (get_segment_type(spare_buf)) /* block type */
831 {
832 case SEGMENT_MAIN_DATA1:
833 { 850 {
834 /* Main data area segment */ 851 /* Newly-written sequential page data (Main data area) */
835 unsigned short log_segment = get_log_segment_id(spare_buf); 852 read_inplace_writes_cache(bank, phys_segment);
836
837 if (log_segment < MAX_SEGMENTS)
838 {
839 /* 0x13 seems to override 0x17, so store in our LPT */
840 lpt_lookup[log_segment].bank = bank;
841 lpt_lookup[log_segment].phys_segment = phys_segment;
842 }
843 break; 853 break;
844 } 854 }
845 } 855 }
846 } 856 }
847 } 857 }
848#endif
849 858
850 initialized = true; 859 initialized = true;
851 860