in pd6729.c [466:541]
static int pd6729_set_mem_map(struct pcmcia_socket *sock,
struct pccard_mem_map *mem)
{
struct pd6729_socket *socket
= container_of(sock, struct pd6729_socket, socket);
unsigned short base, i;
unsigned char map;
map = mem->map;
if (map > 4) {
dev_warn(&sock->dev, "invalid map requested\n");
return -EINVAL;
}
if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) {
dev_warn(&sock->dev, "invalid invalid address / speed\n");
return -EINVAL;
}
/* Turn off the window before changing anything */
if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_MEM(map))
indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_MEM(map));
/* write the start address */
base = I365_MEM(map);
i = (mem->res->start >> 12) & 0x0fff;
if (mem->flags & MAP_16BIT)
i |= I365_MEM_16BIT;
if (mem->flags & MAP_0WS)
i |= I365_MEM_0WS;
indirect_write16(socket, base + I365_W_START, i);
/* write the stop address */
i = (mem->res->end >> 12) & 0x0fff;
switch (to_cycles(mem->speed)) {
case 0:
break;
case 1:
i |= I365_MEM_WS0;
break;
case 2:
i |= I365_MEM_WS1;
break;
default:
i |= I365_MEM_WS1 | I365_MEM_WS0;
break;
}
indirect_write16(socket, base + I365_W_STOP, i);
/* Take care of high byte */
indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24);
/* card start */
i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
if (mem->flags & MAP_WRPROT)
i |= I365_MEM_WRPROT;
if (mem->flags & MAP_ATTRIB) {
/* dev_dbg(&sock->dev, "requesting attribute memory for "
"socket %i\n", socket->number);*/
i |= I365_MEM_REG;
} else {
/* dev_dbg(&sock->dev, "requesting normal memory for "
"socket %i\n", socket->number);*/
}
indirect_write16(socket, base + I365_W_OFF, i);
/* Enable the window if necessary */
if (mem->flags & MAP_ACTIVE)
indirect_setbit(socket, I365_ADDRWIN, I365_ENA_MEM(map));
return 0;
}