Ejemplo n.º 1
0
/*
 * 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;
	}
}
Ejemplo n.º 2
0
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 */