mediabay.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 857 行 · 第 1/2 页
C
857 行
if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up) return 0; media_bays[i].cd_index = -1; return -EINVAL; }#endif /* CONFIG_BLK_DEV_IDE */ return -ENODEV;}EXPORT_SYMBOL(check_media_bay);int __pmac check_media_bay_by_base(unsigned long base, int what){#ifdef CONFIG_BLK_DEV_IDE int i; for (i=0; i<media_bay_count; i++) if (media_bays[i].mdev && base == media_bays[i].cd_base) { if ((what == media_bays[i].content_id) && media_bays[i].state == mb_up) return 0; media_bays[i].cd_index = -1; return -EINVAL; } #endif return -ENODEV;}int __pmac media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base, int irq, int index){#ifdef CONFIG_BLK_DEV_IDE int i; for (i=0; i<media_bay_count; i++) { struct media_bay_info* bay = &media_bays[i]; if (bay->mdev && which_bay == bay->mdev->ofdev.node) { int timeout = 5000; down(&bay->lock); bay->cd_base = base; bay->cd_irq = irq; if ((MB_CD != bay->content_id) || bay->state != mb_up) { up(&bay->lock); return 0; } printk(KERN_DEBUG "Registered ide%d for media bay %d\n", index, i); do { if (MB_IDE_READY(i)) { bay->cd_index = index; up(&bay->lock); return 0; } mdelay(1); } while(--timeout); printk(KERN_DEBUG "Timeount waiting IDE in bay %d\n", i); up(&bay->lock); return -ENODEV; } }#endif /* CONFIG_BLK_DEV_IDE */ return -ENODEV;}static void __pmac media_bay_step(int i){ struct media_bay_info* bay = &media_bays[i]; /* We don't poll when powering down */ if (bay->state != mb_powering_down) poll_media_bay(bay); /* If timer expired or polling IDE busy, run state machine */ if ((bay->state != mb_ide_waiting) && (bay->timer != 0)) { bay->timer -= MS_TO_HZ(MB_POLL_DELAY); if (bay->timer > 0) return; bay->timer = 0; } switch(bay->state) { case mb_powering_up: if (bay->ops->setup_bus(bay, bay->last_value) < 0) { MBDBG("mediabay%d: device not supported (kind:%d)\n", i, bay->content_id); set_mb_power(bay, 0); break; } bay->timer = MS_TO_HZ(MB_RESET_DELAY); bay->state = mb_enabling_bay; MBDBG("mediabay%d: enabling (kind:%d)\n", i, bay->content_id); break; case mb_enabling_bay: bay->ops->un_reset(bay); bay->timer = MS_TO_HZ(MB_SETUP_DELAY); bay->state = mb_resetting; MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id); break; case mb_resetting: if (bay->content_id != MB_CD) { MBDBG("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id); bay->state = mb_up; break; }#ifdef CONFIG_BLK_DEV_IDE MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id); bay->ops->un_reset_ide(bay); bay->timer = MS_TO_HZ(MB_IDE_WAIT); bay->state = mb_ide_resetting;#else printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i); set_mb_power(bay, 0);#endif /* CONFIG_BLK_DEV_IDE */ break; #ifdef CONFIG_BLK_DEV_IDE case mb_ide_resetting: bay->timer = MS_TO_HZ(MB_IDE_TIMEOUT); bay->state = mb_ide_waiting; MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id); break; case mb_ide_waiting: if (bay->cd_base == 0) { bay->timer = 0; bay->state = mb_up; MBDBG("mediabay%d: up before IDE init\n", i); break; } else if (MB_IDE_READY(i)) { bay->timer = 0; bay->state = mb_up; if (bay->cd_index < 0) { hw_regs_t hw; printk("mediabay %d, registering IDE...\n", i); pmu_suspend(); ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL); hw.irq = bay->cd_irq; hw.chipset = ide_pmac; bay->cd_index = ide_register_hw(&hw, NULL); pmu_resume(); } if (bay->cd_index == -1) { /* We eventually do a retry */ bay->cd_retry++; printk("IDE register error\n"); set_mb_power(bay, 0); } else { printk(KERN_DEBUG "media-bay %d is ide%d\n", i, bay->cd_index); MBDBG("mediabay %d IDE ready\n", i); } break; } else if (bay->timer > 0) bay->timer -= MS_TO_HZ(MB_POLL_DELAY); if (bay->timer <= 0) { printk("\nIDE Timeout in bay %d !, IDE state is: 0x%02x\n", i, readb(bay->cd_base + 0x70)); MBDBG("mediabay%d: nIDE Timeout !\n", i); set_mb_power(bay, 0); bay->timer = 0; } break;#endif /* CONFIG_BLK_DEV_IDE */ case mb_powering_down: bay->state = mb_empty;#ifdef CONFIG_BLK_DEV_IDE if (bay->cd_index >= 0) { printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, bay->cd_index); ide_unregister(bay->cd_index); bay->cd_index = -1; } if (bay->cd_retry) { if (bay->cd_retry > MAX_CD_RETRIES) { /* Should add an error sound (sort of beep in dmasound) */ printk("\nmedia-bay %d, IDE device badly inserted or unrecognised\n", i); } else { /* Force a new power down/up sequence */ bay->content_id = MB_NO; } }#endif /* CONFIG_BLK_DEV_IDE */ MBDBG("mediabay%d: end of power down\n", i); break; }}/* * This procedure runs as a kernel thread to poll the media bay * once each tick and register and unregister the IDE interface * with the IDE driver. It needs to be a thread because * ide_register can't be called from interrupt context. */static int __pmac media_bay_task(void *x){ int i; strcpy(current->comm, "media-bay");#ifdef MB_IGNORE_SIGNALS sigfillset(¤t->blocked);#endif for (;;) { for (i = 0; i < media_bay_count; ++i) { down(&media_bays[i].lock); if (!media_bays[i].sleeping) media_bay_step(i); up(&media_bays[i].lock); } current->state = TASK_INTERRUPTIBLE; schedule_timeout(MS_TO_HZ(MB_POLL_DELAY)); if (signal_pending(current)) return 0; }}static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_match *match){ struct media_bay_info* bay; volatile u32 *regbase; struct device_node *ofnode; int i; ofnode = mdev->ofdev.node; if (macio_resource_count(mdev) < 1) return -ENODEV; if (macio_request_resources(mdev, "media-bay")) return -EBUSY; /* Media bay registers are located at the beginning of the * mac-io chip, we get the parent address for now (hrm...) */ regbase = (volatile u32 *)ioremap(ofnode->parent->addrs[0].address, 0x100); if (regbase == NULL) { macio_release_resources(mdev); return -ENOMEM; } i = media_bay_count++; bay = &media_bays[i]; bay->mdev = mdev; bay->base = regbase; bay->index = i; bay->ops = match->data; bay->sleeping = 0; init_MUTEX(&bay->lock); /* Init HW probing */ if (bay->ops->init) bay->ops->init(bay); printk(KERN_INFO "mediabay%d: Registered %s media-bay\n", i, bay->ops->name); /* Force an immediate detect */ set_mb_power(bay, 0); msleep(MB_POWER_DELAY); bay->content_id = MB_NO; bay->last_value = bay->ops->content(bay); bay->value_count = MS_TO_HZ(MB_STABLE_DELAY); bay->state = mb_empty; do { msleep(MB_POLL_DELAY); media_bay_step(i); } while((bay->state != mb_empty) && (bay->state != mb_up)); /* Mark us ready by filling our mdev data */ macio_set_drvdata(mdev, bay); /* Startup kernel thread */ if (i == 0) kernel_thread(media_bay_task, NULL, CLONE_KERNEL); return 0;}static int __pmac media_bay_suspend(struct macio_dev *mdev, u32 state){ struct media_bay_info *bay = macio_get_drvdata(mdev); if (state != mdev->ofdev.dev.power_state && state >= 2) { down(&bay->lock); bay->sleeping = 1; set_mb_power(bay, 0); up(&bay->lock); msleep(MB_POLL_DELAY); mdev->ofdev.dev.power_state = state; } return 0;}static int __pmac media_bay_resume(struct macio_dev *mdev){ struct media_bay_info *bay = macio_get_drvdata(mdev); if (mdev->ofdev.dev.power_state != 0) { mdev->ofdev.dev.power_state = 0; /* We re-enable the bay using it's previous content only if it did not change. Note those bozo timings, they seem to help the 3400 get it right. */ /* Force MB power to 0 */ down(&bay->lock); set_mb_power(bay, 0); msleep(MB_POWER_DELAY); if (bay->ops->content(bay) != bay->content_id) { printk("mediabay%d: content changed during sleep...\n", bay->index); up(&bay->lock); return 0; } set_mb_power(bay, 1); bay->last_value = bay->content_id; bay->value_count = MS_TO_HZ(MB_STABLE_DELAY); bay->timer = MS_TO_HZ(MB_POWER_DELAY);#ifdef CONFIG_BLK_DEV_IDE bay->cd_retry = 0;#endif do { msleep(MB_POLL_DELAY); media_bay_step(bay->index); } while((bay->state != mb_empty) && (bay->state != mb_up)); bay->sleeping = 0; up(&bay->lock); } return 0;}/* Definitions of "ops" structures. */static struct mb_ops ohare_mb_ops __pmacdata = { .name = "Ohare", .content = ohare_mb_content, .power = ohare_mb_power, .setup_bus = ohare_mb_setup_bus, .un_reset = ohare_mb_un_reset, .un_reset_ide = ohare_mb_un_reset_ide,};static struct mb_ops heathrow_mb_ops __pmacdata = { .name = "Heathrow", .content = heathrow_mb_content, .power = heathrow_mb_power, .setup_bus = heathrow_mb_setup_bus, .un_reset = heathrow_mb_un_reset, .un_reset_ide = heathrow_mb_un_reset_ide,};static struct mb_ops keylargo_mb_ops __pmacdata = { .name = "KeyLargo", .init = keylargo_mb_init, .content = keylargo_mb_content, .power = keylargo_mb_power, .setup_bus = keylargo_mb_setup_bus, .un_reset = keylargo_mb_un_reset, .un_reset_ide = keylargo_mb_un_reset_ide,};/* * It seems that the bit for the media-bay interrupt in the IRQ_LEVEL * register is always set when there is something in the media bay. * This causes problems for the interrupt code if we attach an interrupt * handler to the media-bay interrupt, because it tends to go into * an infinite loop calling the media bay interrupt handler. * Therefore we do it all by polling the media bay once each tick. */static struct of_match media_bay_match[] ={ { .name = "media-bay", .type = OF_ANY_MATCH, .compatible = "keylargo-media-bay", .data = &keylargo_mb_ops, }, { .name = "media-bay", .type = OF_ANY_MATCH, .compatible = "heathrow-media-bay", .data = &heathrow_mb_ops, }, { .name = "media-bay", .type = OF_ANY_MATCH, .compatible = "ohare-media-bay", .data = &ohare_mb_ops, }, {},};static struct macio_driver media_bay_driver ={ .name = "media-bay", .match_table = media_bay_match, .probe = media_bay_attach, .suspend = media_bay_suspend, .resume = media_bay_resume};static int __init media_bay_init(void){ int i; for (i=0; i<MAX_BAYS; i++) { memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info)); media_bays[i].content_id = -1;#ifdef CONFIG_BLK_DEV_IDE media_bays[i].cd_index = -1;#endif } if (_machine != _MACH_Pmac) return -ENODEV; macio_register_driver(&media_bay_driver); return 0;}device_initcall(media_bay_init);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?