Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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