linux/drivers/ide/ppc/mpc8xx.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/ide/ppc/ide-m8xx.c
   3 *
   4 *  Copyright (C) 2000, 2001 Wolfgang Denk, wd@denx.de
   5 *  Modified for direct IDE interface
   6 *      by Thomas Lange, thomas@corelatus.com
   7 *  Modified for direct IDE interface on 8xx without using the PCMCIA
   8 *  controller
   9 *      by Steven.Scholz@imc-berlin.de
  10 *  Moved out of arch/ppc/kernel/m8xx_setup.c, other minor cleanups
  11 *      by Mathew Locke <mattl@mvista.com>
  12 */
  13
  14#include <linux/errno.h>
  15#include <linux/kernel.h>
  16#include <linux/mm.h>
  17#include <linux/stddef.h>
  18#include <linux/unistd.h>
  19#include <linux/ptrace.h>
  20#include <linux/slab.h>
  21#include <linux/user.h>
  22#include <linux/a.out.h>
  23#include <linux/tty.h>
  24#include <linux/major.h>
  25#include <linux/interrupt.h>
  26#include <linux/reboot.h>
  27#include <linux/init.h>
  28#include <linux/ioport.h>
  29#include <linux/ide.h>
  30#include <linux/bootmem.h>
  31
  32#include <asm/mpc8xx.h>
  33#include <asm/mmu.h>
  34#include <asm/processor.h>
  35#include <asm/io.h>
  36#include <asm/pgtable.h>
  37#include <asm/ide.h>
  38#include <asm/8xx_immap.h>
  39#include <asm/machdep.h>
  40#include <asm/irq.h>
  41
  42static int identify  (volatile u8 *p);
  43static void print_fixed (volatile u8 *p);
  44static void print_funcid (int func);
  45static int check_ide_device (unsigned long base);
  46
  47static void ide_interrupt_ack (void *dev);
  48static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio);
  49
  50typedef struct ide_ioport_desc {
  51        unsigned long   base_off;               /* Offset to PCMCIA memory      */
  52        unsigned long   reg_off[IDE_NR_PORTS];  /* controller register offsets  */
  53        int             irq;                    /* IRQ                          */
  54} ide_ioport_desc_t;
  55
  56ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = {
  57#ifdef IDE0_BASE_OFFSET
  58        { IDE0_BASE_OFFSET,
  59            {
  60                IDE0_DATA_REG_OFFSET,
  61                IDE0_ERROR_REG_OFFSET,
  62                IDE0_NSECTOR_REG_OFFSET,
  63                IDE0_SECTOR_REG_OFFSET,
  64                IDE0_LCYL_REG_OFFSET,
  65                IDE0_HCYL_REG_OFFSET,
  66                IDE0_SELECT_REG_OFFSET,
  67                IDE0_STATUS_REG_OFFSET,
  68                IDE0_CONTROL_REG_OFFSET,
  69                IDE0_IRQ_REG_OFFSET,
  70            },
  71            IDE0_INTERRUPT,
  72        },
  73#ifdef IDE1_BASE_OFFSET
  74        { IDE1_BASE_OFFSET,
  75            {
  76                IDE1_DATA_REG_OFFSET,
  77                IDE1_ERROR_REG_OFFSET,
  78                IDE1_NSECTOR_REG_OFFSET,
  79                IDE1_SECTOR_REG_OFFSET,
  80                IDE1_LCYL_REG_OFFSET,
  81                IDE1_HCYL_REG_OFFSET,
  82                IDE1_SELECT_REG_OFFSET,
  83                IDE1_STATUS_REG_OFFSET,
  84                IDE1_CONTROL_REG_OFFSET,
  85                IDE1_IRQ_REG_OFFSET,
  86            },
  87            IDE1_INTERRUPT,
  88        },
  89#endif /* IDE1_BASE_OFFSET */
  90#endif  /* IDE0_BASE_OFFSET */
  91};
  92
  93ide_pio_timings_t ide_pio_clocks[6];
  94int hold_time[6] =  {30, 20, 15, 10, 10, 10 };   /* PIO Mode 5 with IORDY (nonstandard) */
  95
  96/*
  97 * Warning: only 1 (ONE) PCMCIA slot supported here,
  98 * which must be correctly initialized by the firmware (PPCBoot).
  99 */
 100static int _slot_ = -1;                 /* will be read from PCMCIA registers   */
 101
 102/* Make clock cycles and always round up */
 103#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U )
 104
 105
 106
 107/*
 108 * IDE stuff.
 109 */
 110static int
 111m8xx_ide_default_irq(unsigned long base)
 112{
 113#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 114        if (base >= MAX_HWIFS)
 115                return 0;
 116
 117        printk("[%d] m8xx_ide_default_irq %d\n",__LINE__,ioport_dsc[base].irq);
 118        
 119        return (ioport_dsc[base].irq);
 120#else
 121        return 9;
 122#endif
 123}
 124
 125static unsigned long
 126m8xx_ide_default_io_base(int index)
 127{
 128        return index;
 129}
 130
 131#define M8XX_PCMCIA_CD2(slot)      (0x10000000 >> (slot << 4))
 132#define M8XX_PCMCIA_CD1(slot)      (0x08000000 >> (slot << 4))
 133
 134/*
 135 * The TQM850L hardware has two pins swapped! Grrrrgh!
 136 */
 137#ifdef  CONFIG_TQM850L
 138#define __MY_PCMCIA_GCRX_CXRESET        PCMCIA_GCRX_CXOE
 139#define __MY_PCMCIA_GCRX_CXOE           PCMCIA_GCRX_CXRESET
 140#else
 141#define __MY_PCMCIA_GCRX_CXRESET        PCMCIA_GCRX_CXRESET
 142#define __MY_PCMCIA_GCRX_CXOE           PCMCIA_GCRX_CXOE
 143#endif
 144
 145#if defined(CONFIG_BLK_DEV_MPC8xx_IDE) && defined(CONFIG_IDE_8xx_PCCARD)
 146#define PCMCIA_SCHLVL IDE0_INTERRUPT    /* Status Change Interrupt Level        */
 147static int pcmcia_schlvl = PCMCIA_SCHLVL;
 148#endif
 149
 150/*
 151 * See include/linux/ide.h for definition of hw_regs_t (p, base)
 152 */
 153
 154/*
 155 * m8xx_ide_init_hwif_ports for a direct IDE interface _using_
 156 */
 157#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
 158static void
 159m8xx_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, 
 160                unsigned long ctrl_port, int *irq)
 161{
 162        unsigned long *p = hw->io_ports;
 163        int i;
 164
 165        typedef struct {
 166                ulong br;
 167                ulong or;
 168        } pcmcia_win_t;
 169        volatile pcmcia_win_t *win;
 170        volatile pcmconf8xx_t *pcmp;
 171
 172        uint *pgcrx;
 173        u32 pcmcia_phy_base;
 174        u32 pcmcia_phy_end;
 175        static unsigned long pcmcia_base = 0;
 176        unsigned long base;
 177
 178        *p = 0;
 179        if (irq)
 180                *irq = 0;
 181
 182        pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
 183
 184        if (!pcmcia_base) {
 185                /*
 186                 * Read out PCMCIA registers. Since the reset values
 187                 * are undefined, we sure hope that they have been
 188                 * set up by firmware
 189                 */
 190
 191                /* Scan all registers for valid settings */
 192                pcmcia_phy_base = 0xFFFFFFFF;
 193                pcmcia_phy_end = 0;
 194                /* br0 is start of brX and orX regs */
 195                win = (pcmcia_win_t *) \
 196                        (&(((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0));
 197                for (i = 0; i < 8; i++) {
 198                        if (win->or & 1) {      /* This bank is marked as valid */
 199                                if (win->br < pcmcia_phy_base) {
 200                                        pcmcia_phy_base = win->br;
 201                                }
 202                                if ((win->br + PCMCIA_MEM_SIZE) > pcmcia_phy_end) {
 203                                        pcmcia_phy_end  = win->br + PCMCIA_MEM_SIZE;
 204                                }
 205                                /* Check which slot that has been defined */
 206                                _slot_ = (win->or >> 2) & 1;
 207
 208                        }                                       /* Valid bank */
 209                        win++;
 210                }                                               /* for */
 211
 212                printk ("PCMCIA slot %c: phys mem %08x...%08x (size %08x)\n",
 213                        'A' + _slot_,
 214                        pcmcia_phy_base, pcmcia_phy_end,
 215                        pcmcia_phy_end - pcmcia_phy_base);
 216
 217                pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base,
 218                                                   pcmcia_phy_end-pcmcia_phy_base);
 219
 220#ifdef DEBUG
 221                printk ("PCMCIA virt base: %08lx\n", pcmcia_base);
 222#endif
 223                /* Compute clock cycles for PIO timings */
 224                for (i=0; i<6; ++i) {
 225                        bd_t    *binfo = (bd_t *)__res;
 226
 227                        hold_time[i]   =
 228                                PCMCIA_MK_CLKS (hold_time[i],
 229                                                binfo->bi_busfreq);
 230                        ide_pio_clocks[i].setup_time  =
 231                                PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time,
 232                                                binfo->bi_busfreq);
 233                        ide_pio_clocks[i].active_time =
 234                                PCMCIA_MK_CLKS (ide_pio_timings[i].active_time,
 235                                                binfo->bi_busfreq);
 236                        ide_pio_clocks[i].cycle_time  =
 237                                PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time,
 238                                                binfo->bi_busfreq);
 239#if 0
 240                        printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n",
 241                                i,
 242                                ide_pio_clocks[i].setup_time,
 243                                ide_pio_clocks[i].active_time,
 244                                ide_pio_clocks[i].hold_time,
 245                                ide_pio_clocks[i].cycle_time,
 246                                ide_pio_timings[i].setup_time,
 247                                ide_pio_timings[i].active_time,
 248                                ide_pio_timings[i].hold_time,
 249                                ide_pio_timings[i].cycle_time);
 250#endif
 251                }
 252        }
 253
 254        if (data_port >= MAX_HWIFS)
 255                return;
 256
 257        if (_slot_ == -1) {
 258                printk ("PCMCIA slot has not been defined! Using A as default\n");
 259                _slot_ = 0;
 260        }
 261
 262#ifdef CONFIG_IDE_8xx_PCCARD
 263
 264#ifdef DEBUG
 265        printk ("PIPR = 0x%08X  slot %c ==> mask = 0x%X\n",
 266                pcmp->pcmc_pipr,
 267                'A' + _slot_,
 268                M8XX_PCMCIA_CD1(_slot_) | M8XX_PCMCIA_CD2(_slot_) );
 269#endif /* DEBUG */
 270
 271        if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) {
 272                printk ("No card in slot %c: PIPR=%08x\n",
 273                        'A' + _slot_, (u32) pcmp->pcmc_pipr);
 274                return;         /* No card in slot */
 275        }
 276
 277        check_ide_device (pcmcia_base);
 278
 279#endif  /* CONFIG_IDE_8xx_PCCARD */
 280
 281        base = pcmcia_base + ioport_dsc[data_port].base_off;
 282#ifdef DEBUG
 283        printk ("base: %08x + %08x = %08x\n",
 284                        pcmcia_base, ioport_dsc[data_port].base_off, base);
 285#endif
 286
 287        for (i = 0; i < IDE_NR_PORTS; ++i) {
 288#ifdef DEBUG
 289                printk ("port[%d]: %08x + %08x = %08x\n",
 290                        i,
 291                        base,
 292                        ioport_dsc[data_port].reg_off[i],
 293                        i, base + ioport_dsc[data_port].reg_off[i]);
 294#endif
 295                *p++ = base + ioport_dsc[data_port].reg_off[i];
 296        }
 297
 298        if (irq) {
 299#ifdef CONFIG_IDE_8xx_PCCARD
 300                unsigned int reg;
 301
 302                *irq = ioport_dsc[data_port].irq;
 303                if (_slot_)
 304                        pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb;
 305                else
 306                        pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcra;
 307
 308                reg = *pgcrx;
 309                reg |= mk_int_int_mask (pcmcia_schlvl) << 24;
 310                reg |= mk_int_int_mask (pcmcia_schlvl) << 16;
 311                *pgcrx = reg;
 312#else   /* direct connected IDE drive, i.e. external IRQ, not the PCMCIA irq */
 313                *irq = ioport_dsc[data_port].irq;
 314#endif  /* CONFIG_IDE_8xx_PCCARD */
 315        }
 316
 317        ide_hwifs[data_port].pio_mask = ATA_PIO4;
 318        ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
 319        ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
 320
 321        /* Enable Harddisk Interrupt,
 322         * and make it edge sensitive
 323         */
 324        /* (11-18) Set edge detect for irq, no wakeup from low power mode */
 325        ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=
 326                                        (0x80000000 >> ioport_dsc[data_port].irq);
 327
 328#ifdef CONFIG_IDE_8xx_PCCARD
 329        /* Make sure we don't get garbage irq */
 330        ((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pscr = 0xFFFF;
 331
 332        /* Enable falling edge irq */
 333        pcmp->pcmc_per = 0x100000 >> (16 * _slot_);
 334#endif  /* CONFIG_IDE_8xx_PCCARD */
 335}       /* m8xx_ide_init_hwif_ports() using 8xx internal PCMCIA interface */
 336#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT */
 337
 338/*
 339 * m8xx_ide_init_hwif_ports for a direct IDE interface _not_ using
 340 * MPC8xx's internal PCMCIA interface
 341 */
 342#if defined(CONFIG_IDE_EXT_DIRECT)
 343void m8xx_ide_init_hwif_ports (hw_regs_t *hw,
 344        unsigned long data_port, unsigned long ctrl_port, int *irq)
 345{
 346        unsigned long *p = hw->io_ports;
 347        int i;
 348
 349        u32 ide_phy_base;
 350        u32 ide_phy_end;
 351        static unsigned long ide_base = 0;
 352        unsigned long base;
 353
 354        *p = 0;
 355        if (irq)
 356                *irq = 0;
 357
 358        if (!ide_base) {
 359
 360                /* TODO:
 361                 * - add code to read ORx, BRx
 362                 */
 363                ide_phy_base = CFG_ATA_BASE_ADDR;
 364                ide_phy_end  = CFG_ATA_BASE_ADDR + 0x200;
 365
 366                printk ("IDE phys mem : %08x...%08x (size %08x)\n",
 367                        ide_phy_base, ide_phy_end,
 368                        ide_phy_end - ide_phy_base);
 369                
 370                ide_base=(unsigned long)ioremap(ide_phy_base,
 371                                                ide_phy_end-ide_phy_base);
 372
 373#ifdef DEBUG
 374                printk ("IDE virt base: %08lx\n", ide_base);
 375#endif
 376        }
 377
 378        if (data_port >= MAX_HWIFS)
 379                return;
 380
 381        base = ide_base + ioport_dsc[data_port].base_off;
 382#ifdef DEBUG
 383        printk ("base: %08x + %08x = %08x\n",
 384                ide_base, ioport_dsc[data_port].base_off, base);
 385#endif
 386
 387        for (i = 0; i < IDE_NR_PORTS; ++i) {
 388#ifdef DEBUG
 389                printk ("port[%d]: %08x + %08x = %08x\n",
 390                        i,
 391                        base,
 392                        ioport_dsc[data_port].reg_off[i],
 393                        i, base + ioport_dsc[data_port].reg_off[i]);
 394#endif
 395                *p++ = base + ioport_dsc[data_port].reg_off[i];
 396        }
 397
 398        if (irq) {
 399                /* direct connected IDE drive, i.e. external IRQ */
 400                *irq = ioport_dsc[data_port].irq;
 401        }
 402
 403        ide_hwifs[data_port].pio_mask = ATA_PIO4;
 404        ide_hwifs[data_port].set_pio_mode = m8xx_ide_set_pio_mode;
 405        ide_hwifs[data_port].ack_intr = (ide_ack_intr_t *)ide_interrupt_ack;
 406
 407        /* Enable Harddisk Interrupt,
 408         * and make it edge sensitive
 409         */
 410        /* (11-18) Set edge detect for irq, no wakeup from low power mode */
 411        ((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=
 412                        (0x80000000 >> ioport_dsc[data_port].irq);
 413}       /* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */ 
 414
 415#endif  /* CONFIG_IDE_8xx_DIRECT */
 416
 417
 418/* -------------------------------------------------------------------- */
 419
 420
 421/* PCMCIA Timing */
 422#ifndef PCMCIA_SHT
 423#define PCMCIA_SHT(t)   ((t & 0x0F)<<16)        /* Strobe Hold  Time    */
 424#define PCMCIA_SST(t)   ((t & 0x0F)<<12)        /* Strobe Setup Time    */
 425#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length   */
 426#endif
 427
 428/* Calculate PIO timings */
 429static void m8xx_ide_set_pio_mode(ide_drive_t *drive, const u8 pio)
 430{
 431#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)
 432        volatile pcmconf8xx_t   *pcmp;
 433        ulong timing, mask, reg;
 434
 435        pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
 436
 437        mask = ~(PCMCIA_SHT(0xFF) | PCMCIA_SST(0xFF) | PCMCIA_SL(0xFF));
 438
 439        timing  = PCMCIA_SHT(hold_time[pio]  )
 440                | PCMCIA_SST(ide_pio_clocks[pio].setup_time )
 441                | PCMCIA_SL (ide_pio_clocks[pio].active_time)
 442                ;
 443
 444#if 1
 445        printk ("Setting timing bits 0x%08lx in PCMCIA controller\n", timing);
 446#endif
 447        if ((reg = pcmp->pcmc_por0 & mask) != 0)
 448                pcmp->pcmc_por0 = reg | timing;
 449
 450        if ((reg = pcmp->pcmc_por1 & mask) != 0)
 451                pcmp->pcmc_por1 = reg | timing;
 452
 453        if ((reg = pcmp->pcmc_por2 & mask) != 0)
 454                pcmp->pcmc_por2 = reg | timing;
 455
 456        if ((reg = pcmp->pcmc_por3 & mask) != 0)
 457                pcmp->pcmc_por3 = reg | timing;
 458
 459        if ((reg = pcmp->pcmc_por4 & mask) != 0)
 460                pcmp->pcmc_por4 = reg | timing;
 461
 462        if ((reg = pcmp->pcmc_por5 & mask) != 0)
 463                pcmp->pcmc_por5 = reg | timing;
 464
 465        if ((reg = pcmp->pcmc_por6 & mask) != 0)
 466                pcmp->pcmc_por6 = reg | timing;
 467
 468        if ((reg = pcmp->pcmc_por7 & mask) != 0)
 469                pcmp->pcmc_por7 = reg | timing;
 470
 471#elif defined(CONFIG_IDE_EXT_DIRECT)
 472
 473        printk("%s[%d] %s: not implemented yet!\n",
 474                __FILE__,__LINE__,__FUNCTION__);
 475#endif /* defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_PCMCIA */
 476}
 477
 478static void
 479ide_interrupt_ack (void *dev)
 480{
 481#ifdef CONFIG_IDE_8xx_PCCARD
 482        u_int pscr, pipr;
 483
 484#if (PCMCIA_SOCKETS_NO == 2)
 485        u_int _slot_;
 486#endif
 487
 488        /* get interrupt sources */
 489
 490        pscr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr;
 491        pipr = ((volatile immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;
 492
 493        /*
 494         * report only if both card detect signals are the same
 495         * not too nice done,
 496         * we depend on that CD2 is the bit to the left of CD1...
 497         */
 498
 499        if(_slot_==-1){
 500          printk("PCMCIA slot has not been defined! Using A as default\n");
 501          _slot_=0;
 502        }
 503
 504        if(((pipr & M8XX_PCMCIA_CD2(_slot_)) >> 1) ^
 505           (pipr & M8XX_PCMCIA_CD1(_slot_))         ) {
 506          printk ("card detect interrupt\n");
 507        }
 508        /* clear the interrupt sources */
 509        ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;
 510
 511#else /* ! CONFIG_IDE_8xx_PCCARD */
 512        /*
 513         * Only CONFIG_IDE_8xx_PCCARD is using the interrupt of the
 514         * MPC8xx's PCMCIA controller, so there is nothing to be done here
 515         * for CONFIG_IDE_8xx_DIRECT and CONFIG_IDE_EXT_DIRECT.
 516         * The interrupt is handled somewhere else.     -- Steven
 517         */
 518#endif /* CONFIG_IDE_8xx_PCCARD */
 519}
 520
 521
 522
 523/*
 524 * CIS Tupel codes
 525 */
 526#define CISTPL_NULL             0x00
 527#define CISTPL_DEVICE           0x01
 528#define CISTPL_LONGLINK_CB      0x02
 529#define CISTPL_INDIRECT         0x03
 530#define CISTPL_CONFIG_CB        0x04
 531#define CISTPL_CFTABLE_ENTRY_CB 0x05
 532#define CISTPL_LONGLINK_MFC     0x06
 533#define CISTPL_BAR              0x07
 534#define CISTPL_PWR_MGMNT        0x08
 535#define CISTPL_EXTDEVICE        0x09
 536#define CISTPL_CHECKSUM         0x10
 537#define CISTPL_LONGLINK_A       0x11
 538#define CISTPL_LONGLINK_C       0x12
 539#define CISTPL_LINKTARGET       0x13
 540#define CISTPL_NO_LINK          0x14
 541#define CISTPL_VERS_1           0x15
 542#define CISTPL_ALTSTR           0x16
 543#define CISTPL_DEVICE_A         0x17
 544#define CISTPL_JEDEC_C          0x18
 545#define CISTPL_JEDEC_A          0x19
 546#define CISTPL_CONFIG           0x1a
 547#define CISTPL_CFTABLE_ENTRY    0x1b
 548#define CISTPL_DEVICE_OC        0x1c
 549#define CISTPL_DEVICE_OA        0x1d
 550#define CISTPL_DEVICE_GEO       0x1e
 551#define CISTPL_DEVICE_GEO_A     0x1f
 552#define CISTPL_MANFID           0x20
 553#define CISTPL_FUNCID           0x21
 554#define CISTPL_FUNCE            0x22
 555#define CISTPL_SWIL             0x23
 556#define CISTPL_END              0xff
 557
 558/*
 559 * CIS Function ID codes
 560 */
 561#define CISTPL_FUNCID_MULTI     0x00
 562#define CISTPL_FUNCID_MEMORY    0x01
 563#define CISTPL_FUNCID_SERIAL    0x02
 564#define CISTPL_FUNCID_PARALLEL  0x03
 565#define CISTPL_FUNCID_FIXED     0x04
 566#define CISTPL_FUNCID_VIDEO     0x05
 567#define CISTPL_FUNCID_NETWORK   0x06
 568#define CISTPL_FUNCID_AIMS      0x07
 569#define CISTPL_FUNCID_SCSI      0x08
 570
 571/*
 572 * Fixed Disk FUNCE codes
 573 */
 574#define CISTPL_IDE_INTERFACE    0x01
 575
 576#define CISTPL_FUNCE_IDE_IFACE  0x01
 577#define CISTPL_FUNCE_IDE_MASTER 0x02
 578#define CISTPL_FUNCE_IDE_SLAVE  0x03
 579
 580/* First feature byte */
 581#define CISTPL_IDE_SILICON      0x04
 582#define CISTPL_IDE_UNIQUE       0x08
 583#define CISTPL_IDE_DUAL         0x10
 584
 585/* Second feature byte */
 586#define CISTPL_IDE_HAS_SLEEP    0x01
 587#define CISTPL_IDE_HAS_STANDBY  0x02
 588#define CISTPL_IDE_HAS_IDLE     0x04
 589#define CISTPL_IDE_LOW_POWER    0x08
 590#define CISTPL_IDE_REG_INHIBIT  0x10
 591#define CISTPL_IDE_HAS_INDEX    0x20
 592#define CISTPL_IDE_IOIS16       0x40
 593
 594
 595/* -------------------------------------------------------------------- */
 596
 597
 598#define MAX_TUPEL_SZ    512
 599#define MAX_FEATURES    4
 600
 601static int check_ide_device (unsigned long base)
 602{
 603        volatile u8 *ident = NULL;
 604        volatile u8 *feature_p[MAX_FEATURES];
 605        volatile u8 *p, *start;
 606        int n_features = 0;
 607        u8 func_id = ~0;
 608        u8 code, len;
 609        unsigned short config_base = 0;
 610        int found = 0;
 611        int i;
 612
 613#ifdef DEBUG
 614        printk ("PCMCIA MEM: %08lX\n", base);
 615#endif
 616        start = p = (volatile u8 *) base;
 617
 618        while ((p - start) < MAX_TUPEL_SZ) {
 619
 620                code = *p; p += 2;
 621
 622                if (code == 0xFF) { /* End of chain */
 623                        break;
 624                }
 625
 626                len = *p; p += 2;
 627#ifdef  DEBUG_PCMCIA
 628                { volatile u8 *q = p;
 629                        printk ("\nTuple code %02x  length %d\n\tData:",
 630                                code, len);
 631
 632                        for (i = 0; i < len; ++i) {
 633                                printk (" %02x", *q);
 634                                q+= 2;
 635                        }
 636                }
 637#endif  /* DEBUG_PCMCIA */
 638                switch (code) {
 639                case CISTPL_VERS_1:
 640                        ident = p + 4;
 641                        break;
 642                case CISTPL_FUNCID:
 643                        func_id = *p;
 644                        break;
 645                case CISTPL_FUNCE:
 646                        if (n_features < MAX_FEATURES)
 647                                feature_p[n_features++] = p;
 648                        break;
 649                case CISTPL_CONFIG:
 650                        config_base = (*(p+6) << 8) + (*(p+4));
 651                default:
 652                        break;
 653                }
 654                p += 2 * len;
 655        }
 656
 657        found = identify (ident);
 658
 659        if (func_id != ((u8)~0)) {
 660                print_funcid (func_id);
 661
 662                if (func_id == CISTPL_FUNCID_FIXED)
 663                        found = 1;
 664                else
 665                        return (1);     /* no disk drive */
 666        }
 667
 668        for (i=0; i<n_features; ++i) {
 669                print_fixed (feature_p[i]);
 670        }
 671
 672        if (!found) {
 673                printk ("unknown card type\n");
 674                return (1);
 675        }
 676
 677        /* set level mode irq and I/O mapped device in config reg*/
 678        *((u8 *)(base + config_base)) = 0x41;
 679
 680        return (0);
 681}
 682
 683/* ------------------------------------------------------------------------- */
 684
 685static void print_funcid (int func)
 686{
 687        switch (func) {
 688        case CISTPL_FUNCID_MULTI:
 689                printk (" Multi-Function");
 690                break;
 691        case CISTPL_FUNCID_MEMORY:
 692                printk (" Memory");
 693                break;
 694        case CISTPL_FUNCID_SERIAL:
 695                printk (" Serial Port");
 696                break;
 697        case CISTPL_FUNCID_PARALLEL:
 698                printk (" Parallel Port");
 699                break;
 700        case CISTPL_FUNCID_FIXED:
 701                printk (" Fixed Disk");
 702                break;
 703        case CISTPL_FUNCID_VIDEO:
 704                printk (" Video Adapter");
 705                break;
 706        case CISTPL_FUNCID_NETWORK:
 707                printk (" Network Adapter");
 708                break;
 709        case CISTPL_FUNCID_AIMS:
 710                printk (" AIMS Card");
 711                break;
 712        case CISTPL_FUNCID_SCSI:
 713                printk (" SCSI Adapter");
 714                break;
 715        default:
 716                printk (" Unknown");
 717                break;
 718        }
 719        printk (" Card\n");
 720}
 721
 722/* ------------------------------------------------------------------------- */
 723
 724static void print_fixed (volatile u8 *p)
 725{
 726        if (p == NULL)
 727                return;
 728
 729        switch (*p) {
 730        case CISTPL_FUNCE_IDE_IFACE:
 731            {   u8 iface = *(p+2);
 732
 733                printk ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown");
 734                printk (" interface ");
 735                break;
 736            }
 737        case CISTPL_FUNCE_IDE_MASTER:
 738        case CISTPL_FUNCE_IDE_SLAVE:
 739            {   u8 f1 = *(p+2);
 740                u8 f2 = *(p+4);
 741
 742                printk ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]");
 743
 744                if (f1 & CISTPL_IDE_UNIQUE)
 745                        printk (" [unique]");
 746
 747                printk ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]");
 748
 749                if (f2 & CISTPL_IDE_HAS_SLEEP)
 750                        printk (" [sleep]");
 751
 752                if (f2 & CISTPL_IDE_HAS_STANDBY)
 753                        printk (" [standby]");
 754
 755                if (f2 & CISTPL_IDE_HAS_IDLE)
 756                        printk (" [idle]");
 757
 758                if (f2 & CISTPL_IDE_LOW_POWER)
 759                        printk (" [low power]");
 760
 761                if (f2 & CISTPL_IDE_REG_INHIBIT)
 762                        printk (" [reg inhibit]");
 763
 764                if (f2 & CISTPL_IDE_HAS_INDEX)
 765                        printk (" [index]");
 766
 767                if (f2 & CISTPL_IDE_IOIS16)
 768                        printk (" [IOis16]");
 769
 770                break;
 771            }
 772        }
 773        printk ("\n");
 774}
 775
 776/* ------------------------------------------------------------------------- */
 777
 778
 779#define MAX_IDENT_CHARS         64
 780#define MAX_IDENT_FIELDS        4
 781
 782static u8 *known_cards[] = {
 783        "ARGOSY PnPIDE D5",
 784        NULL
 785};
 786
 787static int identify  (volatile u8 *p)
 788{
 789        u8 id_str[MAX_IDENT_CHARS];
 790        u8 data;
 791        u8 *t;
 792        u8 **card;
 793        int i, done;
 794
 795        if (p == NULL)
 796                return (0);     /* Don't know */
 797
 798        t = id_str;
 799        done =0;
 800
 801        for (i=0; i<=4 && !done; ++i, p+=2) {
 802                while ((data = *p) != '\0') {
 803                        if (data == 0xFF) {
 804                                done = 1;
 805                                break;
 806                        }
 807                        *t++ = data;
 808                        if (t == &id_str[MAX_IDENT_CHARS-1]) {
 809                                done = 1;
 810                                break;
 811                        }
 812                        p += 2;
 813                }
 814                if (!done)
 815                        *t++ = ' ';
 816        }
 817        *t = '\0';
 818        while (--t > id_str) {
 819                if (*t == ' ')
 820                        *t = '\0';
 821                else
 822                        break;
 823        }
 824        printk ("Card ID: %s\n", id_str);
 825
 826        for (card=known_cards; *card; ++card) {
 827                if (strcmp(*card, id_str) == 0) {       /* found! */
 828                        return (1);
 829                }
 830        }
 831
 832        return (0);     /* don't know */
 833}
 834
 835void m8xx_ide_init(void)
 836{
 837        ppc_ide_md.default_irq          = m8xx_ide_default_irq;
 838        ppc_ide_md.default_io_base      = m8xx_ide_default_io_base;
 839        ppc_ide_md.ide_init_hwif        = m8xx_ide_init_hwif_ports;
 840}
 841