/* * 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. */ int media_bay_task(void *x) { volatile struct media_bay_info* bay; int i = 0; strcpy(current->comm, "media-bay"); for (;;) { bay = &media_bays[i]; poll_media_bay(i); if (bay->content_id != bay->previous_id) { bay->reset_timer = (bay->content_id != MB_NO) ? MB_RESET_COUNT: 0; bay->ready = 0; #ifdef CONFIG_BLK_DEV_IDE bay->cd_timer = 0; if (bay->content_id != MB_CD && 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; } #endif } else if (bay->reset_timer) { if (--bay->reset_timer == 0) { feature_clear(bay->dev_node, FEATURE_Mediabay_reset); bay->ready = 1; #ifdef CONFIG_BLK_DEV_IDE bay->cd_timer = 0; if (bay->content_id == MB_CD && bay->cd_base != 0) bay->cd_timer = MB_IDE_WAIT; #endif } #ifdef CONFIG_BLK_DEV_IDE } else if (bay->cd_timer && (--bay->cd_timer == 0 || MB_IDE_READY(i)) && bay->cd_index < 0) { bay->cd_timer = 0; printk(KERN_DEBUG "Registering IDE, base:0x%08lx, irq:%d\n", bay->cd_base, bay->cd_irq); printk("\n"); bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq); if (bay->cd_index == -1) printk("\nCD-ROM badly inserted. Remove it and try again !\n"); else printk(KERN_DEBUG "media-bay %d is ide %d\n", i, bay->cd_index); #endif } bay->previous_id = bay->content_id; current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); if (signal_pending(current)) return 0; i = (i+1)%media_bay_count; } }
void ide_config(dev_link_t *link) { client_handle_t handle = link->handle; ide_info_t *info = link->priv; tuple_t tuple; u_short buf[128]; cisparse_t parse; config_info_t conf; cistpl_cftable_entry_t *cfg = &parse.cftable_entry; cistpl_cftable_entry_t dflt = { 0 }; int i, pass, last_ret, last_fn, hd, io_base, ctl_base; DEBUG(0, "ide_config(0x%p)\n", link); tuple.TupleData = (cisdata_t *)buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; tuple.Attributes = 0; tuple.DesiredTuple = CISTPL_CONFIG; CS_CHECK(GetFirstTuple, handle, &tuple); CS_CHECK(GetTupleData, handle, &tuple); CS_CHECK(ParseTuple, handle, &tuple, &parse); link->conf.ConfigBase = parse.config.base; link->conf.Present = parse.config.rmask[0]; /* Configure card */ link->state |= DEV_CONFIG; /* Not sure if this is right... look up the current Vcc */ CS_CHECK(GetConfigurationInfo, handle, &conf); link->conf.Vcc = conf.Vcc; pass = io_base = ctl_base = 0; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; tuple.Attributes = 0; CS_CHECK(GetFirstTuple, handle, &tuple); while (1) { CFG_CHECK(GetTupleData, handle, &tuple); CFG_CHECK(ParseTuple, handle, &tuple, &parse); /* Check for matching Vcc, unless we're desperate */ if (!pass) { if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) goto next_entry; } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) goto next_entry; } } if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) link->conf.Vpp1 = link->conf.Vpp2 = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; link->conf.ConfigIndex = cfg->index; link->io.BasePort1 = io->win[0].base; link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; if (!(io->flags & CISTPL_IO_16BIT)) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; if (io->nwin == 2) { link->io.NumPorts1 = 8; link->io.BasePort2 = io->win[1].base; link->io.NumPorts2 = 1; CFG_CHECK(RequestIO, link->handle, &link->io); io_base = link->io.BasePort1; ctl_base = link->io.BasePort2; } else if ((io->nwin == 1) && (io->win[0].len >= 16)) { link->io.NumPorts1 = io->win[0].len; link->io.NumPorts2 = 0; CFG_CHECK(RequestIO, link->handle, &link->io); io_base = link->io.BasePort1; ctl_base = link->io.BasePort1+0x0e; } else goto next_entry; /* If we've got this far, we're done */ break; } next_entry: if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; if (pass) { CS_CHECK(GetNextTuple, handle, &tuple); } else if (CardServices(GetNextTuple, handle, &tuple) != 0) { CS_CHECK(GetFirstTuple, handle, &tuple); memset(&dflt, 0, sizeof(dflt)); pass++; } } CS_CHECK(RequestIRQ, handle, &link->irq); CS_CHECK(RequestConfiguration, handle, &link->conf); /* deal with brain dead IDE resource management */ release_region(link->io.BasePort1, link->io.NumPorts1); if (link->io.NumPorts2) release_region(link->io.BasePort2, link->io.NumPorts2); /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { hd = ide_register(io_base, ctl_base, link->irq.AssignedIRQ); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { hd = ide_register(io_base+0x10, ctl_base+0x10, link->irq.AssignedIRQ); if (hd >= 0) { io_base += 0x10; ctl_base += 0x10; break; } } __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); } if (hd < 0) { printk(KERN_NOTICE "ide_cs: ide_register() at 0x%3x & 0x%3x" ", irq %u failed\n", io_base, ctl_base, link->irq.AssignedIRQ); goto failed; } MOD_INC_USE_COUNT; info->ndev = 1; sprintf(info->node.dev_name, "hd%c", 'a'+(hd*2)); info->node.major = ide_major[hd]; info->node.minor = 0; info->hd = hd; link->dev = &info->node; printk(KERN_INFO "ide_cs: %s: Vcc = %d.%d, Vpp = %d.%d\n", info->node.dev_name, link->conf.Vcc/10, link->conf.Vcc%10, link->conf.Vpp1/10, link->conf.Vpp1%10); link->state &= ~DEV_CONFIG_PENDING; return; cs_failed: cs_error(link->handle, last_fn, last_ret); failed: ide_release((u_long)link); } /* ide_config */