in yenta_socket.c [442:504]
static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
struct pci_bus_region region;
int map;
unsigned char addr, enable;
unsigned int start, stop, card_start;
unsigned short word;
pcibios_resource_to_bus(socket->dev->bus, ®ion, mem->res);
map = mem->map;
start = region.start;
stop = region.end;
card_start = mem->card_start;
if (map > 4 || start > stop || ((start ^ stop) >> 24) ||
(card_start >> 26) || mem->speed > 1000)
return -EINVAL;
enable = I365_ENA_MEM(map);
addr = exca_readb(socket, I365_ADDRWIN);
if (addr & enable) {
addr &= ~enable;
exca_writeb(socket, I365_ADDRWIN, addr);
}
exca_writeb(socket, CB_MEM_PAGE(map), start >> 24);
word = (start >> 12) & 0x0fff;
if (mem->flags & MAP_16BIT)
word |= I365_MEM_16BIT;
if (mem->flags & MAP_0WS)
word |= I365_MEM_0WS;
exca_writew(socket, I365_MEM(map) + I365_W_START, word);
word = (stop >> 12) & 0x0fff;
switch (to_cycles(mem->speed)) {
case 0:
break;
case 1:
word |= I365_MEM_WS0;
break;
case 2:
word |= I365_MEM_WS1;
break;
default:
word |= I365_MEM_WS1 | I365_MEM_WS0;
break;
}
exca_writew(socket, I365_MEM(map) + I365_W_STOP, word);
word = ((card_start - start) >> 12) & 0x3fff;
if (mem->flags & MAP_WRPROT)
word |= I365_MEM_WRPROT;
if (mem->flags & MAP_ATTRIB)
word |= I365_MEM_REG;
exca_writew(socket, I365_MEM(map) + I365_W_OFF, word);
if (mem->flags & MAP_ACTIVE)
exca_writeb(socket, I365_ADDRWIN, addr | enable);
return 0;
}