* Problem with large IDE disk on a MIPS bigendian system.
@ 2001-04-20 11:35 Carsten Langgaard
2001-04-20 14:15 ` Carsten Langgaard
0 siblings, 1 reply; 2+ messages in thread
From: Carsten Langgaard @ 2001-04-20 11:35 UTC (permalink / raw)
To: linux-mips
I have noticed that a bigendian kernel can't quite handled IDE disk,
which is larger than 8GB and support LBA mode (logical addressing mode).
The IDE driver read some of the data incorrectly and therefore doesn't
recognize that the drive support LBA mode, and therefore assume that the
drive use CHS mode (physical addressing mode). The ATA spec tells large
drives to return C/H/S = 16383/16/63 independent of their size, which in
this case result in the IDE drive believe that the disk is only 8GB.
I looked a little bit on the MIPS specific IDE code (in
include/asm-mips/ide.h) and the way things are handled for bigendian
systems.
I have attached a patch below which should handle the IDE data
correctly. I also believe it's more in sync with the other bigendian
architectures.
Now I can see the full size of my 30GB disk, it is hard to find a
smaller disk these days :-)
/Carsten
Index: include/asm-mips/ide.h
===================================================================
RCS file: /home/repository/sw/linux-2.4.0/include/asm-mips/ide.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 ide.h
--- include/asm-mips/ide.h 2001/02/26 09:18:02 1.1.1.2
+++ include/asm-mips/ide.h 2001/04/20 09:57:59
@@ -14,6 +14,7 @@
#ifdef __KERNEL__
#include <linux/config.h>
+#include <asm/io.h>
#ifndef MAX_HWIFS
# ifdef CONFIG_BLK_DEV_IDEPCI
@@ -89,13 +90,21 @@
typedef union {
unsigned all : 8; /* all of the bits
together */
struct {
+#ifdef __MIPSEB__
+ unsigned bit7 : 1; /* always 1 */
+ unsigned lba : 1; /* using LBA instead of
CHS */
+ unsigned bit5 : 1; /* always 1 */
+ unsigned unit : 1; /* drive select number,
0 or 1 */
+ unsigned head : 4; /* always zeros here */
+#else
unsigned head : 4; /* always zeros here */
unsigned unit : 1; /* drive select number,
0 or 1 */
unsigned bit5 : 1; /* always 1 */
unsigned lba : 1; /* using LBA instead of
CHS */
unsigned bit7 : 1; /* always 1 */
+#endif
} b;
- } select_t;
+} select_t;
static __inline__ int ide_request_irq(unsigned int irq, void
(*handler)(int,void *, struct pt_regs *),
unsigned long flags, const char *device, void
*dev_id)
@@ -125,57 +134,99 @@
ide_ops->ide_release_region(from, extent);
}
+#undef SUPPORT_SLOW_DATA_PORTS
+#define SUPPORT_SLOW_DATA_PORTS 0
-#if defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__)
+#undef SUPPORT_VLB_SYNC
+#define SUPPORT_VLB_SYNC 0
-#ifdef insl
-#undef insl
-#endif
-#ifdef outsl
-#undef outsl
-#endif
-#ifdef insw
-#undef insw
-#endif
-#ifdef outsw
-#undef outsw
-#endif
+#if defined(__MIPSEB__)
-#define insw(p,a,c)
\
-do {
\
- unsigned short *ptr = (unsigned short *)(a);
\
- unsigned int i = (c);
\
- while (i--)
\
- *ptr++ = inw(p);
\
-} while (0)
-#define insl(p,a,c)
\
-do {
\
- unsigned long *ptr = (unsigned long *)(a);
\
- unsigned int i = (c);
\
- while (i--)
\
- *ptr++ = inl(p);
\
-} while (0)
-#define outsw(p,a,c)
\
-do {
\
- unsigned short *ptr = (unsigned short *)(a);
\
- unsigned int i = (c);
\
- while (i--)
\
- outw(*ptr++, (p));
\
-} while (0)
-#define outsl(p,a,c) {
\
- unsigned long *ptr = (unsigned long *)(a);
\
- unsigned int i = (c);
\
- while (i--)
\
- outl(*ptr++, (p));
\
-} while (0)
+#define T_CHAR (0x0000) /* char: don't touch */
+#define T_SHORT (0x4000) /* short: 12 -> 21 */
+#define T_INT (0x8000) /* int: 1234 -> 4321 */
+#define T_TEXT (0xc000) /* text: 12 -> 21 */
+
+#define T_MASK_TYPE (0xc000)
+#define T_MASK_COUNT (0x3fff)
+
+#define D_CHAR(cnt) (T_CHAR | (cnt))
+#define D_SHORT(cnt) (T_SHORT | (cnt))
+#define D_INT(cnt) (T_INT | (cnt))
+#define D_TEXT(cnt) (T_TEXT | (cnt))
+
+static u_short driveid_types[] = {
+ D_SHORT(10), /* config - vendor2 */
+ D_TEXT(20), /* serial_no */
+ D_SHORT(3), /* buf_type - ecc_bytes */
+ D_TEXT(48), /* fw_rev - model */
+ D_CHAR(2), /* max_multsect - vendor3 */
+ D_SHORT(1), /* dword_io */
+ D_CHAR(2), /* vendor4 - capability */
+ D_SHORT(1), /* reserved50 */
+ D_CHAR(4), /* vendor5 - tDMA */
+ D_SHORT(4), /* field_valid - cur_sectors */
+ D_INT(1), /* cur_capacity */
+ D_CHAR(2), /* multsect - multsect_valid */
+ D_INT(1), /* lba_capacity */
+ D_SHORT(194) /* dma_1word - reservedyy */
+};
-#endif /* defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) */
+#define num_driveid_types
(sizeof(driveid_types)/sizeof(*driveid_types))
+static __inline__ void ide_fix_driveid(struct hd_driveid *id)
+{
+ u_char *p = (u_char *)id;
+ int i, j, cnt;
+ u_char t;
+
+ for (i = 0; i < num_driveid_types; i++) {
+ cnt = driveid_types[i] & T_MASK_COUNT;
+ switch (driveid_types[i] & T_MASK_TYPE) {
+ case T_CHAR:
+ p += cnt;
+ break;
+ case T_SHORT:
+ for (j = 0; j < cnt; j++) {
+ t = p[0];
+ p[0] = p[1];
+ p[1] = t;
+ p += 2;
+ }
+ break;
+ case T_INT:
+ for (j = 0; j < cnt; j++) {
+ t = p[0];
+ p[0] = p[3];
+ p[3] = t;
+ t = p[1];
+ p[1] = p[2];
+ p[2] = t;
+ p += 4;
+ }
+ break;
+ case T_TEXT:
+ for (j = 0; j < cnt; j += 2) {
+ t = p[0];
+ p[0] = p[1];
+ p[1] = t;
+ p += 2;
+ }
+ break;
+ };
+ }
+}
+
+#else /* defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) */
+
+#define ide_fix_driveid(id) do {} while (0)
+
+#endif
+
/*
* The following are not needed for the non-m68k ports
*/
#define ide_ack_intr(hwif) (1)
-#define ide_fix_driveid(id) do {} while (0)
#define ide_release_lock(lock) do {} while (0)
#define ide_get_lock(lock, hdlr, data) do {} while (0)
--
_ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com
|\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527
| \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555
TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556
Denmark http://www.mips.com
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: Problem with large IDE disk on a MIPS bigendian system.
2001-04-20 11:35 Problem with large IDE disk on a MIPS bigendian system Carsten Langgaard
@ 2001-04-20 14:15 ` Carsten Langgaard
0 siblings, 0 replies; 2+ messages in thread
From: Carsten Langgaard @ 2001-04-20 14:15 UTC (permalink / raw)
To: linux-mips
I should probably point out that the fix change the addressing mode on
large disks (>8GB) supporting LBA mode.
So you want be able to run on a system which was created by an older
kernel, but it probably didn't work properly anyway before the fix.
This only count for bigendian systems on large disks.
/Carsten
Carsten Langgaard wrote:
> I have noticed that a bigendian kernel can't quite handled IDE disk,
> which is larger than 8GB and support LBA mode (logical addressing mode).
>
> The IDE driver read some of the data incorrectly and therefore doesn't
> recognize that the drive support LBA mode, and therefore assume that the
> drive use CHS mode (physical addressing mode). The ATA spec tells large
> drives to return C/H/S = 16383/16/63 independent of their size, which in
> this case result in the IDE drive believe that the disk is only 8GB.
>
> I looked a little bit on the MIPS specific IDE code (in
> include/asm-mips/ide.h) and the way things are handled for bigendian
> systems.
> I have attached a patch below which should handle the IDE data
> correctly. I also believe it's more in sync with the other bigendian
> architectures.
> Now I can see the full size of my 30GB disk, it is hard to find a
> smaller disk these days :-)
>
> /Carsten
>
> Index: include/asm-mips/ide.h
> ===================================================================
> RCS file: /home/repository/sw/linux-2.4.0/include/asm-mips/ide.h,v
> retrieving revision 1.1.1.2
> diff -u -r1.1.1.2 ide.h
> --- include/asm-mips/ide.h 2001/02/26 09:18:02 1.1.1.2
> +++ include/asm-mips/ide.h 2001/04/20 09:57:59
> @@ -14,6 +14,7 @@
> #ifdef __KERNEL__
>
> #include <linux/config.h>
> +#include <asm/io.h>
>
> #ifndef MAX_HWIFS
> # ifdef CONFIG_BLK_DEV_IDEPCI
> @@ -89,13 +90,21 @@
> typedef union {
> unsigned all : 8; /* all of the bits
> together */
> struct {
> +#ifdef __MIPSEB__
> + unsigned bit7 : 1; /* always 1 */
> + unsigned lba : 1; /* using LBA instead of
> CHS */
> + unsigned bit5 : 1; /* always 1 */
> + unsigned unit : 1; /* drive select number,
> 0 or 1 */
> + unsigned head : 4; /* always zeros here */
> +#else
> unsigned head : 4; /* always zeros here */
> unsigned unit : 1; /* drive select number,
> 0 or 1 */
> unsigned bit5 : 1; /* always 1 */
> unsigned lba : 1; /* using LBA instead of
> CHS */
> unsigned bit7 : 1; /* always 1 */
> +#endif
> } b;
> - } select_t;
> +} select_t;
>
> static __inline__ int ide_request_irq(unsigned int irq, void
> (*handler)(int,void *, struct pt_regs *),
> unsigned long flags, const char *device, void
> *dev_id)
> @@ -125,57 +134,99 @@
> ide_ops->ide_release_region(from, extent);
> }
>
> +#undef SUPPORT_SLOW_DATA_PORTS
> +#define SUPPORT_SLOW_DATA_PORTS 0
>
> -#if defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__)
> +#undef SUPPORT_VLB_SYNC
> +#define SUPPORT_VLB_SYNC 0
>
> -#ifdef insl
> -#undef insl
> -#endif
> -#ifdef outsl
> -#undef outsl
> -#endif
> -#ifdef insw
> -#undef insw
> -#endif
> -#ifdef outsw
> -#undef outsw
> -#endif
> +#if defined(__MIPSEB__)
>
> -#define insw(p,a,c)
> \
> -do {
> \
> - unsigned short *ptr = (unsigned short *)(a);
> \
> - unsigned int i = (c);
> \
> - while (i--)
> \
> - *ptr++ = inw(p);
> \
> -} while (0)
> -#define insl(p,a,c)
> \
> -do {
> \
> - unsigned long *ptr = (unsigned long *)(a);
> \
> - unsigned int i = (c);
> \
> - while (i--)
> \
> - *ptr++ = inl(p);
> \
> -} while (0)
> -#define outsw(p,a,c)
> \
> -do {
> \
> - unsigned short *ptr = (unsigned short *)(a);
> \
> - unsigned int i = (c);
> \
> - while (i--)
> \
> - outw(*ptr++, (p));
> \
> -} while (0)
> -#define outsl(p,a,c) {
> \
> - unsigned long *ptr = (unsigned long *)(a);
> \
> - unsigned int i = (c);
> \
> - while (i--)
> \
> - outl(*ptr++, (p));
> \
> -} while (0)
> +#define T_CHAR (0x0000) /* char: don't touch */
> +#define T_SHORT (0x4000) /* short: 12 -> 21 */
> +#define T_INT (0x8000) /* int: 1234 -> 4321 */
> +#define T_TEXT (0xc000) /* text: 12 -> 21 */
> +
> +#define T_MASK_TYPE (0xc000)
> +#define T_MASK_COUNT (0x3fff)
> +
> +#define D_CHAR(cnt) (T_CHAR | (cnt))
> +#define D_SHORT(cnt) (T_SHORT | (cnt))
> +#define D_INT(cnt) (T_INT | (cnt))
> +#define D_TEXT(cnt) (T_TEXT | (cnt))
> +
> +static u_short driveid_types[] = {
> + D_SHORT(10), /* config - vendor2 */
> + D_TEXT(20), /* serial_no */
> + D_SHORT(3), /* buf_type - ecc_bytes */
> + D_TEXT(48), /* fw_rev - model */
> + D_CHAR(2), /* max_multsect - vendor3 */
> + D_SHORT(1), /* dword_io */
> + D_CHAR(2), /* vendor4 - capability */
> + D_SHORT(1), /* reserved50 */
> + D_CHAR(4), /* vendor5 - tDMA */
> + D_SHORT(4), /* field_valid - cur_sectors */
> + D_INT(1), /* cur_capacity */
> + D_CHAR(2), /* multsect - multsect_valid */
> + D_INT(1), /* lba_capacity */
> + D_SHORT(194) /* dma_1word - reservedyy */
> +};
>
> -#endif /* defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) */
> +#define num_driveid_types
> (sizeof(driveid_types)/sizeof(*driveid_types))
>
> +static __inline__ void ide_fix_driveid(struct hd_driveid *id)
> +{
> + u_char *p = (u_char *)id;
> + int i, j, cnt;
> + u_char t;
> +
> + for (i = 0; i < num_driveid_types; i++) {
> + cnt = driveid_types[i] & T_MASK_COUNT;
> + switch (driveid_types[i] & T_MASK_TYPE) {
> + case T_CHAR:
> + p += cnt;
> + break;
> + case T_SHORT:
> + for (j = 0; j < cnt; j++) {
> + t = p[0];
> + p[0] = p[1];
> + p[1] = t;
> + p += 2;
> + }
> + break;
> + case T_INT:
> + for (j = 0; j < cnt; j++) {
> + t = p[0];
> + p[0] = p[3];
> + p[3] = t;
> + t = p[1];
> + p[1] = p[2];
> + p[2] = t;
> + p += 4;
> + }
> + break;
> + case T_TEXT:
> + for (j = 0; j < cnt; j += 2) {
> + t = p[0];
> + p[0] = p[1];
> + p[1] = t;
> + p += 2;
> + }
> + break;
> + };
> + }
> +}
> +
> +#else /* defined(CONFIG_SWAP_IO_SPACE) && defined(__MIPSEB__) */
> +
> +#define ide_fix_driveid(id) do {} while (0)
> +
> +#endif
> +
> /*
> * The following are not needed for the non-m68k ports
> */
> #define ide_ack_intr(hwif) (1)
> -#define ide_fix_driveid(id) do {} while (0)
> #define ide_release_lock(lock) do {} while (0)
> #define ide_get_lock(lock, hdlr, data) do {} while (0)
>
> --
> _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com
> |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527
> | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555
> TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556
> Denmark http://www.mips.com
--
_ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com
|\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527
| \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555
TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556
Denmark http://www.mips.com
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2001-04-20 14:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-04-20 11:35 Problem with large IDE disk on a MIPS bigendian system Carsten Langgaard
2001-04-20 14:15 ` Carsten Langgaard
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox