diff -ur kernel-source-2.4.22.orig/drivers/ide/ide-probe.c kernel-source-2.4.22/drivers/ide/ide-probe.c --- kernel-source-2.4.22.orig/drivers/ide/ide-probe.c 2004-04-24 15:10:37.000000000 +0100 +++ kernel-source-2.4.22/drivers/ide/ide-probe.c 2005-02-10 00:26:45.000000000 +0000 @@ -552,6 +552,121 @@ } } +/* + * This function enables the quantum drives that have content protection + * such as the drives used in the TiVo. + */ +static void enable_quantum (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long timeout; + + struct { + u16 challenge1; + u16 challenge2; + u16 padding[254]; + } *chalresp; + + /* + * Magic incantation for reading Challenge from drive + */ + SELECT_DRIVE(drive); + ide_delay_50ms(); + hwif->OUTB(0x82, IDE_NSECTOR_REG); + ide_delay_50ms(); + hwif->OUTB(0x6f, IDE_SECTOR_REG); + ide_delay_50ms(); + hwif->OUTB(0xbe, IDE_LCYL_REG); + ide_delay_50ms(); + hwif->OUTB(0x50, IDE_HCYL_REG); + ide_delay_50ms(); + SELECT_DRIVE(drive); + ide_delay_50ms(); + hwif->OUTB(QUANTUM_SECURITY, IDE_COMMAND_REG); + + timeout = jiffies + WAIT_WORSTCASE; + do { + if (jiffies > timeout) { + printk("failed (timeout)\n"); + return; + } + ide_delay_50ms(); + } while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT); + ide_delay_50ms(); + if (hwif->INB(IDE_STATUS_REG) != 0x58) { + return; /* no content protection */ + } + + chalresp = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */ + ata_input_data(drive, chalresp, SECTOR_WORDS); + + + + printk("%s: Unlocking %s \n", drive->name, + drive->id->model); + + printk("%s: Challenge: 0x%x%x ", drive->name, + chalresp->challenge1, + chalresp->challenge2); + + /* XOR challenge with 0x6f566954 (oViT = TiVo!) */ + chalresp->challenge1 ^= 0x6f56; + chalresp->challenge2 ^= 0x6954; + + printk("Response: 0x%x%x\n", chalresp->challenge1, + chalresp->challenge2); + + /* + * Magic incantation for writing Response to drive + */ + SELECT_DRIVE(drive); + ide_delay_50ms(); + hwif->OUTB(0x83, IDE_NSECTOR_REG); + ide_delay_50ms(); + hwif->OUTB(0xef, IDE_SECTOR_REG); + ide_delay_50ms(); + hwif->OUTB(0xc2, IDE_LCYL_REG); + ide_delay_50ms(); + hwif->OUTB(0x86, IDE_HCYL_REG); + ide_delay_50ms(); + SELECT_DRIVE(drive); + ide_delay_50ms(); + hwif->OUTB(QUANTUM_SECURITY, IDE_COMMAND_REG); + + timeout = jiffies + WAIT_WORSTCASE; + do { + if (jiffies > timeout) { + printk("failed (timeout)\n"); + kfree(chalresp); + return; + } + ide_delay_50ms(); + } while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT); + + ide_delay_50ms(); + if (hwif->INB(IDE_STATUS_REG) != 0x58) { + printk("%s: Unable to unlock - 0x%x\n", drive->name, + hwif->INB(IDE_STATUS_REG)); + kfree(chalresp); + return; + } + + ata_output_data(drive, chalresp, SECTOR_WORDS); + ide_delay_50ms(); + if (hwif->INB(IDE_STATUS_REG) != 0x50) { + printk("%s: Unable to unlock - 0x%x\n", drive->name, + hwif->INB(IDE_STATUS_REG)); + kfree(chalresp); + return; + } + + kfree(chalresp); + + if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ + (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ + } +} + /** * probe_for_drives - upper level drive probe * @drive: drive to probe for @@ -595,6 +710,8 @@ } if (strstr(drive->id->model, "E X A B Y T E N E S T")) enable_nest(drive); + if (strstr(drive->id->model, "QUANTUM")) + enable_quantum(drive); if (!drive->present) /* drive not found */ return 0; diff -ur kernel-source-2.4.22.orig/fs/partitions/Config.in kernel-source-2.4.22/fs/partitions/Config.in --- kernel-source-2.4.22.orig/fs/partitions/Config.in 2002-11-28 23:53:15.000000000 +0000 +++ kernel-source-2.4.22/fs/partitions/Config.in 2005-02-10 00:26:45.000000000 +0000 @@ -18,6 +18,9 @@ bool ' IBM disk label and partition support' CONFIG_IBM_PARTITION fi bool ' Macintosh partition map support' CONFIG_MAC_PARTITION + if [ "$CONFIG_MAC_PARTITION" = "y" ]; then + bool ' TiVo partition map support' CONFIG_TIVO_PARTITION + fi bool ' PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL diff -ur kernel-source-2.4.22.orig/fs/partitions/mac.c kernel-source-2.4.22/fs/partitions/mac.c --- kernel-source-2.4.22.orig/fs/partitions/mac.c 2002-08-03 01:39:45.000000000 +0100 +++ kernel-source-2.4.22/fs/partitions/mac.c 2005-02-10 00:26:45.000000000 +0000 @@ -38,11 +38,26 @@ md = (struct mac_driver_desc *) read_dev_sector(bdev, 0, §); if (!md) return -1; - if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) { - put_dev_sector(sect); - return 0; + + switch(be16_to_cpu(md->signature)) { + case MAC_DRIVER_MAGIC: + secsize = be16_to_cpu(md->block_size); + break; + +#ifdef CONFIG_TIVO_PARTITION + case TIVO_DRIVER_MAGIC: + /* The TiVo map does not have a valid Mac block 0 + * fill in the block size. + */ + secsize = 512; + break; +#endif + + default: + put_dev_sector(sect); + return 0; } - secsize = be16_to_cpu(md->block_size); + put_dev_sector(sect); data = read_dev_sector(bdev, secsize/512, §); if (!data) diff -ur kernel-source-2.4.22.orig/fs/partitions/mac.h kernel-source-2.4.22/fs/partitions/mac.h --- kernel-source-2.4.22.orig/fs/partitions/mac.h 2002-08-03 01:39:45.000000000 +0100 +++ kernel-source-2.4.22/fs/partitions/mac.h 2005-02-10 00:26:45.000000000 +0000 @@ -40,6 +40,7 @@ #define MAC_STATUS_BOOTABLE 8 /* partition is bootable */ #define MAC_DRIVER_MAGIC 0x4552 +#define TIVO_DRIVER_MAGIC 0x1492 /* Driver descriptor structure, in block 0 */ struct mac_driver_desc { diff -ur kernel-source-2.4.22.orig/include/linux/hdreg.h kernel-source-2.4.22/include/linux/hdreg.h --- kernel-source-2.4.22.orig/include/linux/hdreg.h 2003-06-01 04:06:37.000000000 +0100 +++ kernel-source-2.4.22/include/linux/hdreg.h 2005-02-10 00:26:45.000000000 +0000 @@ -311,6 +311,8 @@ #define WIN_SET_MAX 0xF9 #define DISABLE_SEAGATE 0xFB +#define QUANTUM_SECURITY 0xF0 + /* WIN_SMART sub-commands */ #define SMART_READ_VALUES 0xD0