in i82092.c [589:662]
static int i82092aa_set_mem_map(struct pcmcia_socket *socket,
struct pccard_mem_map *mem)
{
struct socket_info *sock_info = container_of(socket, struct socket_info,
socket);
unsigned int sock = sock_info->number;
struct pci_bus_region region;
unsigned short base, i;
unsigned char map;
pcibios_resource_to_bus(sock_info->dev->bus, ®ion, mem->res);
map = mem->map;
if (map > 4)
return -EINVAL;
if ((mem->card_start > 0x3ffffff) || (region.start > region.end) ||
(mem->speed > 1000)) {
dev_err(&sock_info->dev->dev,
"invalid mem map for socket %i: %llx to %llx with a start of %x\n",
sock,
(unsigned long long)region.start,
(unsigned long long)region.end,
mem->card_start);
return -EINVAL;
}
/* Turn off the window before changing anything */
if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
/* write the start address */
base = I365_MEM(map);
i = (region.start >> 12) & 0x0fff;
if (mem->flags & MAP_16BIT)
i |= I365_MEM_16BIT;
if (mem->flags & MAP_0WS)
i |= I365_MEM_0WS;
indirect_write16(sock, base+I365_W_START, i);
/* write the stop address */
i = (region.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(sock, base+I365_W_STOP, i);
/* card start */
i = ((mem->card_start - region.start) >> 12) & 0x3fff;
if (mem->flags & MAP_WRPROT)
i |= I365_MEM_WRPROT;
if (mem->flags & MAP_ATTRIB)
i |= I365_MEM_REG;
indirect_write16(sock, base+I365_W_OFF, i);
/* Enable the window if necessary */
if (mem->flags & MAP_ACTIVE)
indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
return 0;
}