Re: UMC 8881/8886 chipset

Bruce Perens (johns@chiark.greenend.org.uk)
Mon, 16 Jun 97 19:53 BST


In article <m0wbnYt-0004oBC@chiark.greenend.org.uk>,
John Sullivan <john.quillion@stjohns.co.uk> wrote:
>and I don't have access to 8673/8881 to test those... I'll post the
>patch for this sometime tomorrow however.

Here it is. You'll need hdparm to take advantage, and it ought to be a
whole lot cleaner. PIO mode 3 works for me. Pushing it higher could do
seriously strange things. Best to test timings on a read-only
filesystem, and power-cycle if it locks up.

To activate it you'll need to enable umc8672 support in the kernel
config, and use ide0=umc8672 on the kernel command-line.

diff -rc linux-pure/drivers/block/umc8672.c
linux-kanargh/drivers/block/umc8672.c
*** linux-pure/drivers/block/umc8672.c Sat May 31 15:12:22 1997
--- linux-kanargh/drivers/block/umc8672.c Thu May 29 20:58:40 1997
***************
*** 8,14 ****
* Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien)
*
* This file provides support for the advanced features
! * of the UMC 8672 IDE interface.
*
* Version 0.01 Initial version, hacked out of ide.c,
* and #include'd rather than compiled separately.
--- 8,14 ----
* Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien)
*
* This file provides support for the advanced features
! * of the UMC 8672 and UMC8673/8666 IDE interface.
*
* Version 0.01 Initial version, hacked out of ide.c,
* and #include'd rather than compiled separately.
***************
*** 16,21 ****
--- 16,22 ----
*
* Version 0.02 now configs/compiles separate from ide.c -ml
* Version 0.03 enhanced auto-tune, fix display bug
+ * Version 0.04 added support for 8673/8666 PCI chipsets
* Version 0.05 replace sti() with restore_flags() -ml
* add detection of possible race condition -ml
*/
***************
*** 27,32 ****
--- 28,37 ----
* D28832 Achim
* Germany
*
+ * PCI Controller Support from
+ * John Sullivan
+ * (currently john.quillion@stjohns.co.uk)
+ *
* To enable UMC8672 support there must a lilo line like
* append="ide0=umc8672"...
* To set the speed according to the abilities of the hardware there
must be a
***************
*** 60,65 ****
--- 65,71 ----
#define UMC_DRIVE3 1 /* In case of crash reduce speed
*/

static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2,
UMC_DRIVE3};
+ static byte umc8673_ver,umc8673_spd,umc8673_fen;
static const byte pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */

/* 0 1 2 3 4 5 6 7 8 9 10 11
*/
***************
*** 68,73 ****
--- 74,85 ----
{0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
{0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};

+ /* 0 1 2 3 4 5 6 7 8 9 10 11 12
13 14 15 16 17 18 19 20 21 */
+ static const byte speedtab8886 [3][22] = {
+ {0x4, 0x3, 0x3, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x2, 0x1, 0x0, 0x4 },
+ {0xc, 0x6, 0x6, 0x5, 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, 0x4, 0x3, 0x3, 0x3,
0x2, 0x2, 0x1, 0x1, 0x5, 0x4, 0x3, 0xc },
+ {0xc, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x7, 0x6, 0x5, 0x4, 0x4, 0x3, 0x2,
0x2, 0x1, 0x1, 0x0, 0xc, 0x6, 0x3, 0xc}};
+
static void out_umc (char port,char wert)
{
outb_p (port,0x108);
***************
*** 105,115 ****
speeds[0], speeds[1], speeds[2], speeds[3]);
}

static void tune_umc (ide_drive_t *drive, byte pio)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
!
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name,
pio, pio_to_umc[pio]);
save_flags(flags);
--- 117,158 ----
speeds[0], speeds[1], speeds[2], speeds[3]);
}

+ static void umc8666_set_speeds(byte speeds[])
+ {
+ int d1,d2;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli ();
+ outb_p(0x4a,0x108); /* enable umc */
+ outb_p(0x6c,0x108);
+
+ d2 = (d1 = 0)+1;
+
+ out_umc(0xb2,(speedtab8886[0][speeds[d1]] |
(speedtab8886[0][speeds[d2]]<<4)));
+ out_umc(0xb3,(speedtab8886[0][speeds[2+d1]] |
(speedtab8886[0][speeds[2+d2]]<<4)));
+ out_umc(0xb4,(speedtab8886[1][speeds[d1]] |
(speedtab8886[1][speeds[d2]]<<4)));
+ out_umc(0xb5,(speedtab8886[1][speeds[2+d1]] |
(speedtab8886[1][speeds[2+d2]]<<4)));
+ out_umc(0xb6,(speedtab8886[2][speeds[d1]] |
(speedtab8886[2][speeds[2]]<<4)));
+ out_umc(0xb7,(speedtab8886[2][speeds[2+d1]] |
(speedtab8886[2][speeds[2+d2]]<<4)));
+
+ out_umc(0xb8,(speedtab8886[1][18+umc8673_spd] |
(speedtab8886[1][18+umc8673_spd]<<4)));
+ out_umc(0xb9,(speedtab8886[1][18+umc8673_spd] |
(speedtab8886[1][18+umc8673_spd]<<4)));
+ out_umc(0xba,(speedtab8886[2][18+umc8673_spd] |
(speedtab8886[2][18+umc8673_spd]<<4)));
+ out_umc(0xbb,(speedtab8886[2][18+umc8673_spd] |
(speedtab8886[2][18+umc8673_spd]<<4)));
+
+ outb_p(0x34,0x108); /* disable umc */
+ restore_flags(flags);
+
+ printk ("umc8666: drive speeds [0 to 18]: %d %d %d %d\n",
+ speeds[0], speeds[1], speeds[2], speeds[3]);
+ }
+
static void tune_umc (ide_drive_t *drive, byte pio)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
!
pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name,
pio, pio_to_umc[pio]);
save_flags(flags);
***************
*** 123,128 ****
--- 166,246 ----
restore_flags(flags);
}

+ static void tune_umc8666 (ide_drive_t *drive, byte pio)
+ {
+ unsigned long flags;
+ ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
+
+ pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+ printk("%s: setting umc8666 to PIO mode%d (speed %d)\n", drive->name,
pio, pio_to_umc[pio]);
+ save_flags(flags);
+ cli();
+ if (hwgroup && hwgroup->handler != NULL) {
+ printk("umc8666: other interface is busy: exiting tune_umc()\n");
+ } else {
+ current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
+ umc8666_set_speeds (current_speeds);
+ }
+ restore_flags(flags);
+ }
+
+ int init_umc8673(void)
+ {
+ unsigned long flags;
+ unsigned char rs;
+
+ save_flags(flags);
+ cli ();
+
+ outb_p(0x4a,0x108); /* enable umc */
+ outb_p(0x6c,0x108); /* get status? reset? */
+ rs = in_umc(0xd5);
+ outb_p(0x34,0x108); /* disable umc */
+
+ umc8673_spd = rs & 3;
+ umc8673_fen = 0;
+ if (rs == 0xb8)
+ {
+ restore_flags(flags);
+ printk ("\numc8673: UM8886A detected\n");
+ umc8673_ver = 3;
+ umc8673_spd = 0;
+ } else if ((rs&0xfc)==0x5c || (rs&0xc0)==0x80) {
+ restore_flags(flags);
+ printk("\numc8673: think we got a UM8673 (0x%02x)!\n",(unsigned
int)rs);
+ printk("umc8673: UM8673x chipset not yet supported\n");
+ if ((rs&0xfc)==0x5c) umc8673_ver=1; else umc8673_ver=2;
+ return 0;
+ } else {
+ restore_flags(flags);
+ return -1;
+ }
+
+ outb_p(0x4a,0x108);
+ outb_p(0x6c,0x108);
+ out_umc(0xb0,0x00);
+ rs = inb_p(0x3f6);
+ out_umc(0xb0,0xc0);
+ outb_p(0x34,0x108);
+
+ if (rs==0x50) {
+ restore_flags(flags);
+ printk("umc8673: chip not enabled!\n");
+ return -1;
+ }
+
+ umc_set_speeds(current_speeds);
+ restore_flags(flags);
+
+ request_region(0x108, 2, "umc8666");
+ ide_hwifs[0].chipset = ide_umc8672;
+ ide_hwifs[1].chipset = ide_umc8672;
+ ide_hwifs[0].tuneproc = &tune_umc8666;
+ ide_hwifs[1].tuneproc = &tune_umc8666;
+
+ return 0;
+ }
+
void init_umc8672 (void) /* called from ide.c */
{
unsigned long flags;
***************
*** 134,144 ****
printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
return;
}
outb_p (0x5A,0x108); /* enable umc */
if (in_umc (0xd5) != 0xa0)
{
restore_flags(flags);
! printk ("umc8672: not found\n");
return;
}
outb_p (0xa5,0x108); /* disable umc */
--- 252,263 ----
printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
return;
}
+
outb_p (0x5A,0x108); /* enable umc */
if (in_umc (0xd5) != 0xa0)
{
restore_flags(flags);
! if (init_umc8673()) printk ("umc8672: not found\n");
return;
}
outb_p (0xa5,0x108); /* disable umc */

John

-- 
i built it up now i take it apart climbed up real high now fall down real far
no need for me to stay the last thing left i just threw it away
i put my faith in god and my trust in you
now there's nothing more fucked up i could do
<p><a href="file:///dev/null">Me.</a>