Hi,
I have an IBM drive, DTLA-307075 (75GB), and a bios that hangs with
large disks. I use a jumper to clip it to 32GB size, so the bios can
boot into linux. The problem is that WIN_READ_NATIVE_MAX returns 32GB,
and not the true size, and even trying to set the correct size with
WIN_SET_MAX fails. Is there a way to use this combination (Bios, HD,
Linux)?
--
Matan Ziv-Av. [email protected]
On Fri, 8 Dec 2000, Matan Ziv-Av wrote:
>
> Hi,
>
>
> I have an IBM drive, DTLA-307075 (75GB), and a bios that hangs with
> large disks. I use a jumper to clip it to 32GB size, so the bios can
> boot into linux. The problem is that WIN_READ_NATIVE_MAX returns 32GB,
> and not the true size, and even trying to set the correct size with
> WIN_SET_MAX fails. Is there a way to use this combination (Bios, HD,
> Linux)?
Yep you have to use code/patches that are not in the standard kernel.
Which kernel are you using?
Andre Hedrick
CTO Timpanogas Research Group
EVP Linux Development, TRG
Linux ATA Development
On Fri, Dec 08, 2000 at 11:24:56PM +0200, Matan Ziv-Av wrote:
> I have an IBM drive, DTLA-307075 (75GB), and a bios that hangs with
> large disks. I use a jumper to clip it to 32GB size, so the bios can
> boot into linux. The problem is that WIN_READ_NATIVE_MAX returns 32GB,
> and not the true size, and even trying to set the correct size with
> WIN_SET_MAX fails. Is there a way to use this combination (Bios, HD,
> Linux)?
Don't know where you found WIN_READ_NATIVE_MAX,
or what program you tried in order to fiddle with
these things. The ATA standard calls the command
READ NATIVE MAX ADDRESS.
So far I have seen success with READ_NATIVE_MAX_ADDRESS
and SET_MAX_ADDRESS on Maxtor drives but do not offhand
recall any reports on IBM DTLA drives.
(Posted a few times a setmax.c utility that you can try.)
You can also try to contact IBM support.
Files like dtla_spw.pdf only mention that you can clip capacity
using a jumper, but there is no hint that it would be
possible to unclip using SET_MAX_ADDRESS.
Be careful that you do not lock the disk.
(The command only functions as a SET_MAX_ADDRESS when
immediately preceded by a READ_NATIVE_MAX_ADDRESS.)
Andries
OK, thanks to Andries Brouwer, who pointed me to IBM's dtla_spw.pdf, I
solved the problem:
The kernel (2.2.18-pre25 + ide.2.2.18-24.all.20001204.patch.bz2) already
has support for unclipping. The problem is that the IBM drive does not
work with the method used when clipped with the jumper. The solution is
to use software clipping. IBM suggest to do that with their program that
requires windows, 1.44 floppy drive and a BIOS that can boot with the
drive. All three are unavailable for me.
Instead, I use the attached program, which is a modification of setmax,
to clip the drive. This requires only a working linux system where an
extra IDE drive can be attached. I attached the drive to such a system,
and ran ./ibmsetmax -m 66055248 (32GB). From then on, the drive is
clipped, so award bios can boot with it, but it returns the correct
value to READ_NATIVE_MAX, so the kernel unclipping procedure works.
Thanks to Andries and Andre for their help, and I hope this helps others
who want to use large disks with old bios.
--
Matan Ziv-Av. [email protected]
/* ibmsetmax.c - */
#include <stdio.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/hdreg.h>
#ifndef HDIO_DRIVE_CMD_AEB
#define HDIO_DRIVE_CMD_AEB 0x031e
#endif
#define INITIALIZE_DRIVE_PARAMETERS 0x91
#define READ_NATIVE_MAX_ADDRESS 0xf8
#define CHECK_POWER_MODE 0xe5
#define SET_MAX 0xf9
#define LBA 0x40
#define VV 1 /* if set in sectorct then NOT volatile */
struct idecmdin {
unsigned char cmd;
unsigned char feature;
unsigned char nsect;
unsigned char sect, lcyl, hcyl;
unsigned char select;
};
struct idecmdout {
unsigned char status;
unsigned char error;
unsigned char nsect;
unsigned char sect, lcyl, hcyl;
unsigned char select;
};
unsigned int
tolba(unsigned char *args) {
return ((args[6] & 0xf) << 24) + (args[5] << 16) + (args[4] << 8) + args[3];
}
void
fromlba(unsigned char *args, unsigned int lba) {
args[3] = (lba & 0xff);
lba >>= 8;
args[4] = (lba & 0xff);
lba >>= 8;
args[5] = (lba & 0xff);
lba >>= 8;
args[6] = (args[6] & 0xf0) | (lba & 0xf);
}
int
get_identity(int fd) {
unsigned char args[4+512] = {WIN_IDENTIFY,0,0,1,};
struct hd_driveid *id = (struct hd_driveid *)&args[4];
if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
perror("HDIO_DRIVE_CMD");
fprintf(stderr,
"WIN_IDENTIFY failed - trying WIN_PIDENTIFY\n");
args[0] = WIN_PIDENTIFY;
if (ioctl(fd, HDIO_DRIVE_CMD, &args)) {
perror("HDIO_DRIVE_CMD");
fprintf(stderr,
"WIN_PIDENTIFY also failed - giving up\n");
exit(1);
}
}
printf("lba capacity: %d sectors (%lld bytes)\n",
id->lba_capacity,
(long long) id->lba_capacity * 512);
}
/*
* result: in LBA mode precisely what is expected
* in CHS mode the correct H and S, and C mod 65536.
*/
unsigned int
get_native_max(int fd, int slave) {
unsigned char args[7];
int i, max;
for (i=0; i<7; i++)
args[i] = 0;
args[0] = READ_NATIVE_MAX_ADDRESS;
args[6] = (slave ? 0x10 : 0) | LBA;
if (ioctl(fd, HDIO_DRIVE_CMD_AEB, &args)) {
perror("HDIO_DRIVE_CMD_AEB failed READ_NATIVE_MAX_ADDRESS");
for (i=0; i<7; i++)
printf("%d = 0x%x\n", args[i], args[i]);
exit(1);
}
return tolba(args);
}
void
set_max_address(int fd, int slave, int delta) {
unsigned char args[7];
int i, nativemax;
nativemax = get_native_max(fd, slave);
printf("nativemax=%d (0x%x)\n", nativemax, nativemax);
for (i=0; i<7; i++)
args[i] = 0;
args[0] = SET_MAX;
args[1] = 0;
args[2] = 1; /* non-volatile */
fromlba(args, delta-1);
args[6] |= LBA;
if (ioctl(fd, HDIO_DRIVE_CMD_AEB, &args)) {
perror("HDIO_DRIVE_CMD_AEB failed SET_MAX");
for (i=0; i<7; i++)
printf("%d = 0x%x\n", args[i], args[i]);
exit(1);
}
}
static char short_opts[] = "m:";
static const struct option long_opts[] = {
{ "max", required_argument, NULL, 'd' },
{ NULL, 0, NULL, 0 }
};
static char *usage_txt =
"Call: ibmsetmax [-m D] DEVICE\n"
"\n"
"The call \"ibmsetmax -m D DEVICE\" will do a SET_MAX command\n"
"to set the non-volatile maximum accessible sector number D sectors.\n"
"\n"
"The call \"setmax DEVICE\" will do a READ_NATIVE_MAX_ADDRESS\n"
"command, and report the maximum accessible sector number.\n"
"\n"
"This is IDE-only. Probably DEVICE is /dev/hdx for some x.\n\n";
main(int argc, char **argv){
int fd, c;
int delta;
/* If you modify device, also update slave, if necessary. */
/* master: hda, hdc, hde; slave: hdb, hdd, hdf */
char *device = NULL; /* e.g. "/dev/hda" */
int slave = 0;
delta = -1;
while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) {
switch(c) {
case 'm':
delta = atoi(optarg);
break;
case '?':
default:
fprintf(stderr, "unknown option\n");
fprintf(stderr, usage_txt);
exit(1);
}
}
if (optind < argc)
device = argv[optind];
if (!device) {
fprintf(stderr, "no device specified - "
"use e.g. \"setmax /dev/hdb\"\n");
fprintf(stderr, usage_txt);
exit(1);
}
printf("Using device %s\n", device);
fd = open(device, O_RDONLY);
if (fd == -1) {
perror("open");
exit(1);
}
if (delta != -1) {
printf("setting delta=%d\n", delta);
set_max_address(fd, slave, delta);
} else {
int mad = get_native_max(fd, slave);
long long bytes = (long long) (mad+1) * 512;
int hMB = (bytes+50000000)/100000000;
printf("native max address: %d\n", mad);
printf("that is %lld bytes, %d.%d GB\n",
bytes, hMB/10, hMB%10);
}
get_identity(fd);
return 0;
}
On Fri, 8 Dec 2000, Matan Ziv-Av wrote:
> Hi,
>
> I have an IBM drive, DTLA-307075 (75GB), and a bios that hangs with
> large disks. I use a jumper to clip it to 32GB size, so the bios can
> boot into linux. The problem is that WIN_READ_NATIVE_MAX returns 32GB,
> and not the true size, and even trying to set the correct size with
> WIN_SET_MAX fails. Is there a way to use this combination (Bios, HD,
> Linux)?
I had the exact same problem. Jumper-clipping doesn't work, so the
solution to this problem is applying the IDE patch to the kernel
(http://www.linux-ide.org), and then use IBM's Disk Manager utilities to
software-clip the drive (don't set the jumper).
Software-clipping does exactly the same as hardware clipping, except that
a jumper isn't involved, and the drive can be clipped back to full
capacity. Each drive has a flash memory is once you do it you don't have
to do it again.
--
Dan Aloni
[email protected]
On Sat, Dec 09, 2000 at 11:50:59AM +0200, Matan Ziv-Av wrote:
> I use the attached program, which is a modification of setmax,
Good! So we learned something again.
I merged both versions of setmax.c and added text to the
Large Disk HOWTO. See
http://www.win.tue.nl/~aeb/linux/Large-Disk-11.html#ss11.3
Comments are welcome.
Andries
Yeah, get yourself one of those nifty add-in IDE controllers that CAN see
drives greater than 32GB. S'What I did and it works fine.
On Fri, 8 Dec 2000, Matan Ziv-Av wrote:
>
> Hi,
>
>
> I have an IBM drive, DTLA-307075 (75GB), and a bios that hangs with
> large disks. I use a jumper to clip it to 32GB size, so the bios can
> boot into linux. The problem is that WIN_READ_NATIVE_MAX returns 32GB,
> and not the true size, and even trying to set the correct size with
> WIN_SET_MAX fails. Is there a way to use this combination (Bios, HD,
> Linux)?
>
>
>
--
Kelsey Hudson [email protected]
Software Engineer
Compendium Technologies, Inc (619) 725-0771
---------------------------------------------------------------------------