Hi!
I've modified pd.c to support drives over 8GB.
Now if it detects a big drive it uses LBA mode
to address sectors instead of the CHS addressing.
It works fine with my 45GB WD Caviar, but I haven't
tested it with any other drives. So BE VERY CAREFUL,
try only on drives which don't contain important
data!
The patch is below the message, and the patched pd.c
source is in the attached file.
Tamas Vincze
>=========== cut ============<
--- pd.c.orig Sat Oct 7 20:36:47 2000
+++ pd.c Tue Oct 10 11:42:03 2000
@@ -44,6 +44,7 @@
a logical geometry with 64 heads and 32 sectors
per track, to be consistent with most SCSI
drivers. (0 if not given)
+ This param has no effect if the drive is over
8GB.
<sby> set this to zero to disable the power saving
standby mode, if needed. (1 if not given)
@@ -111,10 +112,13 @@
1.03 GRG 1998.06.16 Eliminate an Ugh.
1.04 GRG 1998.08.15 Extra debugging, use HZ in loop timing
1.05 GRG 1998.09.24 Added jumbo support
+ 1.06 TOM 2000.10.07 Support for drives over 8GB,
+ using LBA mode.
+ by Tamas Vincze <vincze@neb.com>
*/
-#define PD_VERSION "1.05"
+#define PD_VERSION "1.06"
#define PD_MAJOR 45
#define PD_NAME "pd"
#define PD_UNITS 4
@@ -293,7 +297,7 @@
struct pi_adapter pia; /* interface to paride layer */
struct pi_adapter *pi;
int access; /* count of active opens ... */
- int capacity; /* Size of this volume in
sectors */
+ unsigned long capacity; /* Size of this volume in
sectors */
int heads; /* physical geometry */
int sectors;
int cylinders;
@@ -304,6 +308,7 @@
int alt_geom;
int present;
char name[PD_NAMELEN]; /* pda, pdb, etc ... */
+ int lba_mode; /* 1=use LBA addressing */
};
struct pd_unit pd[PD_UNITS];
@@ -389,6 +394,7 @@
PD.alt_geom = DU[D_GEO];
PD.standby = DU[D_SBY];
if (DU[D_PRT]) pd_drive_count++;
+ PD.lba_mode = 0;
}
}
@@ -471,7 +477,7 @@
err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
if (err) return err;
- if (PD.alt_geom) {
+ if (!PD.lba_mode && PD.alt_geom) {
put_user(PD.capacity/(PD_LOG_HEADS*PD_LOG_SECTS),
(short *) &geo->cylinders);
put_user(PD_LOG_HEADS, (char *) &geo->heads);
@@ -715,12 +721,20 @@
/* Don't use this call if the capacity is zero. */
-{ int c1, c0, h, s;
+{ unsigned int c0, c1, h, s, trk;
- s = ( block % PD.sectors) + 1;
- h = ( block / PD.sectors) % PD.heads;
- c0 = ( block / (PD.sectors*PD.heads)) % 256;
- c1 = ( block / (PD.sectors*PD.heads*256));
+ if(PD.lba_mode) {
+ s = block & 0xff;
+ c0 = (block>>=8) & 0xff;
+ c1 = (block>>=8) & 0xff;
+ h = ((block>>8) & 0x0f) + 0x40;
+ } else {
+ trk = block / PD.sectors;
+ s = block % PD.sectors + 1;
+ h = trk % PD.heads;
+ c0 = (trk / PD.heads) & 0xff;
+ c1 = (trk / PD.heads) >> 8;
+ }
pd_send_command(unit,count,s,h,c0,c1,func);
}
@@ -801,6 +815,8 @@
{ int j;
char id[PD_ID_LEN+1];
+ unsigned short cyl, head, sect;
+ unsigned long chs_capacity, lba_capacity;
/* WARNING: here there may be dragons. reset() applies to both
drives,
but we call it only on probing the MASTER. This should allow most
@@ -821,10 +837,36 @@
}
pi_read_block(PI,pd_scratch,512);
pi_disconnect(PI);
- PD.sectors = word_val(6);
- PD.heads = word_val(3);
- PD.cylinders = word_val(1);
- PD.capacity = PD.sectors*PD.heads*PD.cylinders;
+
+ /* calculate CHS & LBA capacity */
+ cyl = word_val(1);
+ head = word_val(3);
+ sect = word_val(6);
+ chs_capacity = cyl * head * sect;
+ lba_capacity = word_val(60) | (word_val(61) << 16);
+
+ /* use LBA mode if the drive is over 8GB */
+ if(
+ /* large drives return CHS=16383/16/63 or 16383/15/63 */
+ (cyl==16383 && (head==15 || head==16) && sect==63 &&
+ lba_capacity > chs_capacity) ||
+ /* the drive might not support CHS translation at all */
+ (cyl==0 && head==0 && sect==0 && lba_capacity>0)
+ ) {
+ PD.lba_mode = 1;
+ PD.capacity = lba_capacity;
+ PD.sectors = 63;
+ PD.heads = 255;
+ if(lba_capacity / (63*255) > 65535)
+ PD.cylinders = 65535;
+ else
+ PD.cylinders = lba_capacity / (63*255);
+ } else {
+ PD.capacity = chs_capacity;
+ PD.sectors = sect;
+ PD.heads = head;
+ PD.cylinders = cyl;
+ }
for(j=0;j<PD_ID_LEN;j++) id[j^1] = pd_scratch[j+PD_ID_OFF];
j = PD_ID_LEN-1;
@@ -833,14 +875,15 @@
PD.removable = (word_val(0) & 0x80);
- printk("%s: %s, %s, %d blocks [%dM], (%d/%d/%d), %s media\n",
+ printk("%s: %s, %s, %lu blocks [%luM], (%d/%d/%d), %s media, %s
mode\n",
PD.name,id,
PD.drive?"slave":"master",
- PD.capacity,PD.capacity/2048,
+ PD.capacity,PD.capacity/2048L,
PD.cylinders,PD.heads,PD.sectors,
- PD.removable?"removable":"fixed");
+ PD.removable?"removable":"fixed",
+ PD.lba_mode?"LBA":"CHS");
- if (PD.capacity) pd_init_dev_parms(unit);
+ if (PD.capacity && !PD.lba_mode) pd_init_dev_parms(unit);
if (!PD.standby) pd_standby_off(unit);
pd_hd[unit<<PD_BITS].nr_sects = PD.capacity;
>=========== cut ============<
-- To unsubscribe, send mail to: linux-parport-request@torque.net --
-- with the single word "unsubscribe" in the body of the message. --
This archive was generated by hypermail 2b29 : Tue Oct 10 2000 - 12:28:12 EDT