From: Carsten Langgaard <carstenl@mips.com>
To: linux-mips@oss.sgi.com
Subject: Re: Problem with large IDE disk on a MIPS bigendian system.
Date: Fri, 20 Apr 2001 16:15:59 +0200 [thread overview]
Message-ID: <3AE0449F.7E39C0F1@mips.com> (raw)
In-Reply-To: 3AE01EFF.850580E4@mips.com
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
prev parent reply other threads:[~2001-04-20 14:16 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
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 message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3AE0449F.7E39C0F1@mips.com \
--to=carstenl@mips.com \
--cc=linux-mips@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox