static int tcic_set_socket()

in tcic.c [619:690]


static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
    u_char reg;
    u_short scf1, scf2;

    dev_dbg(&sock->dev, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
	  "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,
	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
    tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);

    reg = tcic_getb(TCIC_PWR);
    reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));

    if (state->Vcc == 50) {
	switch (state->Vpp) {
	case 0:   reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
	case 50:  reg |= TCIC_PWR_VCC(psock); break;
	case 120: reg |= TCIC_PWR_VPP(psock); break;
	default:  return -EINVAL;
	}
    } else if (state->Vcc != 0)
	return -EINVAL;

    if (reg != tcic_getb(TCIC_PWR))
	tcic_setb(TCIC_PWR, reg);

    reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
    if (state->flags & SS_OUTPUT_ENA) {
	tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
	reg |= TCIC_ILOCK_CRESENA;
    } else
	tcic_setb(TCIC_SCTRL, 0);
    if (state->flags & SS_RESET)
	reg |= TCIC_ILOCK_CRESET;
    tcic_aux_setb(TCIC_AUX_ILOCK, reg);
    
    tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
    scf1 = TCIC_SCF1_FINPACK;
    scf1 |= TCIC_IRQ(state->io_irq);
    if (state->flags & SS_IOCARD) {
	scf1 |= TCIC_SCF1_IOSTS;
	if (state->flags & SS_SPKR_ENA)
	    scf1 |= TCIC_SCF1_SPKR;
	if (state->flags & SS_DMA_MODE)
	    scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
    }
    tcic_setw(TCIC_DATA, scf1);

    /* Some general setup stuff, and configure status interrupt */
    reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
    tcic_aux_setb(TCIC_AUX_WCTL, reg);
    tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
		  TCIC_IRQ(cs_irq));
    
    /* Card status change interrupt mask */
    tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
    scf2 = TCIC_SCF2_MALL;
    if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
    if (state->flags & SS_IOCARD) {
	if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
    } else {
	if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
	if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
	if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
    }
    tcic_setw(TCIC_DATA, scf2);
    /* For the ISA bus, the irq should be active-high totem-pole */
    tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);

    return 0;
} /* tcic_set_socket */