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