📄 mediabay.c
字号:
if (id == MB_NO) {#ifdef CONFIG_BLK_DEV_IDE bay->cd_retry = 0;#endif printk(KERN_INFO "media bay %d is empty\n", bay->index); } } } else { bay->last_value = id; bay->value_count = 0; }}int __pmaccheck_media_bay(struct device_node *which_bay, int what){#ifdef CONFIG_BLK_DEV_IDE int i; for (i=0; i<media_bay_count; i++) if (which_bay == media_bays[i].dev_node) { 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;}int __pmaccheck_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 (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 __pmacmedia_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++) if (which_bay == media_bays[i].dev_node) { int timeout = 5000; media_bays[i].cd_base = base; media_bays[i].cd_irq = irq; if ((MB_CD != media_bays[i].content_id) || media_bays[i].state != mb_up) return 0; printk(KERN_DEBUG "Registered ide %d for media bay %d\n", index, i); do { if (MB_IDE_READY(i)) { media_bays[i].cd_index = index; return 0; } mdelay(1); } while(--timeout); printk(KERN_DEBUG "Timeount waiting IDE in bay %d\n", i); return -ENODEV; } #endif return -ENODEV;}static void __pmacmedia_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) != 0)) return; 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) { pmu_suspend(); bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq); 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; } if (bay->timer == 0) { printk("\nIDE Timeout in bay %d !\n", i); MBDBG("mediabay%d: nIDE Timeout !\n", i); set_mb_power(bay, 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 __pmacmedia_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) media_bay_step(i); current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); if (signal_pending(current)) return 0; }}#ifdef MB_USE_INTERRUPTSstatic void __pmacmedia_bay_intr(int irq, void *devid, struct pt_regs *regs){}#endif#ifdef CONFIG_PMAC_PBOOK/* * notify clients before sleep and reset bus afterwards */int __pmacmb_notify_sleep(struct pmu_sleep_notifier *self, int when){ struct media_bay_info* bay; int i; switch (when) { case PBOOK_SLEEP_REQUEST: case PBOOK_SLEEP_REJECT: break; case PBOOK_SLEEP_NOW: for (i=0; i<media_bay_count; i++) { bay = &media_bays[i]; set_mb_power(bay, 0); mdelay(10); } break; case PBOOK_WAKE: for (i=0; i<media_bay_count; i++) { bay = &media_bays[i]; /* 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 */ set_mb_power(bay, 0); mdelay(MB_POWER_DELAY); if (bay->ops->content(bay) != bay->content_id) continue; 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 { mdelay(1000/HZ); media_bay_step(i); } while((media_bays[i].state != mb_empty) && (media_bays[i].state != mb_up)); } break; } return PBOOK_SLEEP_OK;}#endif /* CONFIG_PMAC_PBOOK *//* 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", 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. */void __pmacmedia_bay_init(void){ struct device_node *np; int n,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 } np = find_devices("media-bay"); n = 0; while(np && (n<MAX_BAYS)) { struct media_bay_info* bay = &media_bays[n]; if (!np->parent || np->n_addrs == 0 || !request_OF_resource(np, 0, NULL)) { np = np->next; printk(KERN_ERR "media-bay: Can't request IO resource !\n"); continue; } bay->mb_type = mb_ohare; if (device_is_compatible(np, "keylargo-media-bay")) { bay->mb_type = mb_keylargo; bay->ops = &keylargo_mb_ops; } else if (device_is_compatible(np, "heathrow-media-bay")) { bay->mb_type = mb_heathrow; bay->ops = &heathrow_mb_ops; } else if (device_is_compatible(np, "ohare-media-bay")) { bay->mb_type = mb_ohare; bay->ops = &ohare_mb_ops; } else { printk(KERN_ERR "mediabay: Unknown bay type !\n"); np = np->next; continue; } bay->base = (volatile u32*)ioremap(np->parent->addrs[0].address, 0x1000); /* Enable probe logic on keylargo */ if (bay->mb_type == mb_keylargo) MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_ENABLE);#ifdef MB_USE_INTERRUPTS if (np->n_intrs == 0) { printk(KERN_ERR "media bay %d has no irq\n",n); np = np->next; continue; } if (request_irq(np->intrs[0].line, media_bay_intr, 0, "Media bay", (void *)n)) { printk(KERN_ERR "Couldn't get IRQ %d for media bay %d\n", np->intrs[0].line, n); np = np->next; continue; }#endif media_bay_count++; printk(KERN_INFO "mediabay%d: Registered %s media-bay\n", n, bay->ops->name); bay->dev_node = np; bay->index = n; /* Force an immediate detect */ set_mb_power(bay, 0); mdelay(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 { mdelay(1000/HZ); media_bay_step(n); } while((bay->state != mb_empty) && (bay->state != mb_up)); n++; np=np->next; } if (media_bay_count) {#ifdef CONFIG_PMAC_PBOOK pmu_register_sleep_notifier(&mb_sleep_notifier);#endif /* CONFIG_PMAC_PBOOK */ kernel_thread(media_bay_task, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -