aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-06-27 19:28:53 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-27 21:03:20 -0400
commit1a8d46631e166a3c79fe1466ce8cfc4721fdf780 (patch)
tree71d2d6327019e1a6cb01b5027f2071aea9c4f04a /drivers
parente6ea0b9ec5131ac360581d6924fed536758bd024 (diff)
[PATCH] pcmcia: move pcmcia resource handling out of cs.c
Move the 16-bit PCMICA resource handling from pcmcia_core.o to pcmcia.o. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pcmcia/Makefile2
-rw-r--r--drivers/pcmcia/cistpl.c4
-rw-r--r--drivers/pcmcia/cs.c935
-rw-r--r--drivers/pcmcia/pcmcia_resource.c989
-rw-r--r--drivers/pcmcia/rsrc_mgr.c3
5 files changed, 997 insertions, 936 deletions
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 195e8104ae6b..ef694c74dfb7 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -10,7 +10,7 @@ pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
10pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o 10pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
11obj-$(CONFIG_PCCARD) += pcmcia_core.o 11obj-$(CONFIG_PCCARD) += pcmcia_core.o
12 12
13pcmcia-y += ds.o pcmcia_compat.o 13pcmcia-y += ds.o pcmcia_compat.o pcmcia_resource.o
14pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o 14pcmcia-$(CONFIG_PCMCIA_IOCTL) += pcmcia_ioctl.o
15obj-$(CONFIG_PCMCIA) += pcmcia.o 15obj-$(CONFIG_PCMCIA) += pcmcia.o
16 16
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index af4ff08d6dcd..a8aa7b9cf641 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -182,6 +182,8 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
182 *(u_char *)(ptr+2), *(u_char *)(ptr+3)); 182 *(u_char *)(ptr+2), *(u_char *)(ptr+3));
183 return 0; 183 return 0;
184} 184}
185EXPORT_SYMBOL(pcmcia_read_cis_mem);
186
185 187
186void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr, 188void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
187 u_int len, void *ptr) 189 u_int len, void *ptr)
@@ -239,6 +241,8 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
239 } 241 }
240 } 242 }
241} 243}
244EXPORT_SYMBOL(pcmcia_write_cis_mem);
245
242 246
243/*====================================================================== 247/*======================================================================
244 248
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 574706e74791..6a35a4a9f932 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -89,9 +89,6 @@ INT_MODULE_PARM(unreset_limit, 30); /* unreset_check's */
89/* Access speed for attribute memory windows */ 89/* Access speed for attribute memory windows */
90INT_MODULE_PARM(cis_speed, 300); /* ns */ 90INT_MODULE_PARM(cis_speed, 300); /* ns */
91 91
92/* Access speed for IO windows */
93INT_MODULE_PARM(io_speed, 0); /* ns */
94
95#ifdef DEBUG 92#ifdef DEBUG
96static int pc_debug; 93static int pc_debug;
97 94
@@ -117,11 +114,6 @@ EXPORT_SYMBOL(pcmcia_socket_list);
117EXPORT_SYMBOL(pcmcia_socket_list_rwsem); 114EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
118 115
119 116
120#ifdef CONFIG_PCMCIA_PROBE
121/* mask ofIRQs already reserved by other cards, we should avoid using them */
122static u8 pcmcia_used_irq[NR_IRQS];
123#endif
124
125/*==================================================================== 117/*====================================================================
126 118
127 Low-level PC Card interface drivers need to register with Card 119 Low-level PC Card interface drivers need to register with Card
@@ -748,260 +740,6 @@ void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)
748} /* pcmcia_parse_events */ 740} /* pcmcia_parse_events */
749 741
750 742
751/*======================================================================
752
753 Special stuff for managing IO windows, because they are scarce.
754
755======================================================================*/
756
757static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
758 ioaddr_t num, u_int lines)
759{
760 int i;
761 kio_addr_t try, align;
762
763 align = (*base) ? (lines ? 1<<lines : 0) : 1;
764 if (align && (align < num)) {
765 if (*base) {
766 cs_dbg(s, 0, "odd IO request: num %#x align %#lx\n",
767 num, align);
768 align = 0;
769 } else
770 while (align && (align < num)) align <<= 1;
771 }
772 if (*base & ~(align-1)) {
773 cs_dbg(s, 0, "odd IO request: base %#x align %#lx\n",
774 *base, align);
775 align = 0;
776 }
777 if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
778 *base = s->io_offset | (*base & 0x0fff);
779 return 0;
780 }
781 /* Check for an already-allocated window that must conflict with
782 what was asked for. It is a hack because it does not catch all
783 potential conflicts, just the most obvious ones. */
784 for (i = 0; i < MAX_IO_WIN; i++)
785 if ((s->io[i].NumPorts != 0) &&
786 ((s->io[i].BasePort & (align-1)) == *base))
787 return 1;
788 for (i = 0; i < MAX_IO_WIN; i++) {
789 if (s->io[i].NumPorts == 0) {
790 s->io[i].res = pcmcia_find_io_region(*base, num, align, s);
791 if (s->io[i].res) {
792 s->io[i].Attributes = attr;
793 s->io[i].BasePort = *base = s->io[i].res->start;
794 s->io[i].NumPorts = s->io[i].InUse = num;
795 break;
796 } else
797 return 1;
798 } else if (s->io[i].Attributes != attr)
799 continue;
800 /* Try to extend top of window */
801 try = s->io[i].BasePort + s->io[i].NumPorts;
802 if ((*base == 0) || (*base == try))
803 if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start,
804 s->io[i].res->end + num, s) == 0) {
805 *base = try;
806 s->io[i].NumPorts += num;
807 s->io[i].InUse += num;
808 break;
809 }
810 /* Try to extend bottom of window */
811 try = s->io[i].BasePort - num;
812 if ((*base == 0) || (*base == try))
813 if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num,
814 s->io[i].res->end, s) == 0) {
815 s->io[i].BasePort = *base = try;
816 s->io[i].NumPorts += num;
817 s->io[i].InUse += num;
818 break;
819 }
820 }
821 return (i == MAX_IO_WIN);
822} /* alloc_io_space */
823
824static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
825 ioaddr_t num)
826{
827 int i;
828
829 for (i = 0; i < MAX_IO_WIN; i++) {
830 if ((s->io[i].BasePort <= base) &&
831 (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
832 s->io[i].InUse -= num;
833 /* Free the window if no one else is using it */
834 if (s->io[i].InUse == 0) {
835 s->io[i].NumPorts = 0;
836 release_resource(s->io[i].res);
837 kfree(s->io[i].res);
838 s->io[i].res = NULL;
839 }
840 }
841 }
842}
843
844/*======================================================================
845
846 Access_configuration_register() reads and writes configuration
847 registers in attribute memory. Memory window 0 is reserved for
848 this and the tuple reading services.
849
850======================================================================*/
851
852int pccard_access_configuration_register(struct pcmcia_socket *s,
853 unsigned int function,
854 conf_reg_t *reg)
855{
856 config_t *c;
857 int addr;
858 u_char val;
859
860 if (!s || !s->config)
861 return CS_NO_CARD;
862
863 c = &s->config[function];
864
865 if (c == NULL)
866 return CS_NO_CARD;
867
868 if (!(c->state & CONFIG_LOCKED))
869 return CS_CONFIGURATION_LOCKED;
870
871 addr = (c->ConfigBase + reg->Offset) >> 1;
872
873 switch (reg->Action) {
874 case CS_READ:
875 pcmcia_read_cis_mem(s, 1, addr, 1, &val);
876 reg->Value = val;
877 break;
878 case CS_WRITE:
879 val = reg->Value;
880 pcmcia_write_cis_mem(s, 1, addr, 1, &val);
881 break;
882 default:
883 return CS_BAD_ARGS;
884 break;
885 }
886 return CS_SUCCESS;
887} /* access_configuration_register */
888EXPORT_SYMBOL(pccard_access_configuration_register);
889
890
891/*====================================================================*/
892
893int pccard_get_configuration_info(struct pcmcia_socket *s,
894 unsigned int function,
895 config_info_t *config)
896{
897 config_t *c;
898
899 if (!(s->state & SOCKET_PRESENT))
900 return CS_NO_CARD;
901
902 config->Function = function;
903
904#ifdef CONFIG_CARDBUS
905 if (s->state & SOCKET_CARDBUS) {
906 memset(config, 0, sizeof(config_info_t));
907 config->Vcc = s->socket.Vcc;
908 config->Vpp1 = config->Vpp2 = s->socket.Vpp;
909 config->Option = s->cb_dev->subordinate->number;
910 if (s->state & SOCKET_CARDBUS_CONFIG) {
911 config->Attributes = CONF_VALID_CLIENT;
912 config->IntType = INT_CARDBUS;
913 config->AssignedIRQ = s->irq.AssignedIRQ;
914 if (config->AssignedIRQ)
915 config->Attributes |= CONF_ENABLE_IRQ;
916 config->BasePort1 = s->io[0].BasePort;
917 config->NumPorts1 = s->io[0].NumPorts;
918 }
919 return CS_SUCCESS;
920 }
921#endif
922
923 c = (s->config != NULL) ? &s->config[function] : NULL;
924
925 if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
926 config->Attributes = 0;
927 config->Vcc = s->socket.Vcc;
928 config->Vpp1 = config->Vpp2 = s->socket.Vpp;
929 return CS_SUCCESS;
930 }
931
932 /* !!! This is a hack !!! */
933 memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
934 config->Attributes |= CONF_VALID_CLIENT;
935 config->CardValues = c->CardValues;
936 config->IRQAttributes = c->irq.Attributes;
937 config->AssignedIRQ = s->irq.AssignedIRQ;
938 config->BasePort1 = c->io.BasePort1;
939 config->NumPorts1 = c->io.NumPorts1;
940 config->Attributes1 = c->io.Attributes1;
941 config->BasePort2 = c->io.BasePort2;
942 config->NumPorts2 = c->io.NumPorts2;
943 config->Attributes2 = c->io.Attributes2;
944 config->IOAddrLines = c->io.IOAddrLines;
945
946 return CS_SUCCESS;
947} /* get_configuration_info */
948EXPORT_SYMBOL(pccard_get_configuration_info);
949
950/*======================================================================
951
952 Return information about this version of Card Services.
953
954======================================================================*/
955
956int pcmcia_get_card_services_info(servinfo_t *info)
957{
958 unsigned int socket_count = 0;
959 struct list_head *tmp;
960 info->Signature[0] = 'C';
961 info->Signature[1] = 'S';
962 down_read(&pcmcia_socket_list_rwsem);
963 list_for_each(tmp, &pcmcia_socket_list)
964 socket_count++;
965 up_read(&pcmcia_socket_list_rwsem);
966 info->Count = socket_count;
967 info->Revision = CS_RELEASE_CODE;
968 info->CSLevel = 0x0210;
969 info->VendorString = (char *)release;
970 return CS_SUCCESS;
971} /* get_card_services_info */
972
973
974/*====================================================================*/
975
976int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, int idx, win_req_t *req)
977{
978 window_t *win;
979 int w;
980
981 if (!s || !(s->state & SOCKET_PRESENT))
982 return CS_NO_CARD;
983 for (w = idx; w < MAX_WIN; w++)
984 if (s->state & SOCKET_WIN_REQ(w)) break;
985 if (w == MAX_WIN)
986 return CS_NO_MORE_ITEMS;
987 win = &s->win[w];
988 req->Base = win->ctl.res->start;
989 req->Size = win->ctl.res->end - win->ctl.res->start + 1;
990 req->AccessSpeed = win->ctl.speed;
991 req->Attributes = 0;
992 if (win->ctl.flags & MAP_ATTRIB)
993 req->Attributes |= WIN_MEMORY_TYPE_AM;
994 if (win->ctl.flags & MAP_ACTIVE)
995 req->Attributes |= WIN_ENABLE;
996 if (win->ctl.flags & MAP_16BIT)
997 req->Attributes |= WIN_DATA_WIDTH_16;
998 if (win->ctl.flags & MAP_USE_WAIT)
999 req->Attributes |= WIN_USE_WAIT;
1000 *handle = win;
1001 return CS_SUCCESS;
1002} /* get_window */
1003EXPORT_SYMBOL(pcmcia_get_window);
1004
1005/*===================================================================== 743/*=====================================================================
1006 744
1007 Return the PCI device associated with a card.. 745 Return the PCI device associated with a card..
@@ -1022,143 +760,6 @@ EXPORT_SYMBOL(pcmcia_lookup_bus);
1022 760
1023#endif 761#endif
1024 762
1025/*======================================================================
1026
1027 Get the current socket state bits. We don't support the latched
1028 SocketState yet: I haven't seen any point for it.
1029
1030======================================================================*/
1031
1032int pccard_get_status(struct pcmcia_socket *s, unsigned int function, cs_status_t *status)
1033{
1034 config_t *c;
1035 int val;
1036
1037 s->ops->get_status(s, &val);
1038 status->CardState = status->SocketState = 0;
1039 status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
1040 status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
1041 status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
1042 status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
1043 if (s->state & SOCKET_SUSPEND)
1044 status->CardState |= CS_EVENT_PM_SUSPEND;
1045 if (!(s->state & SOCKET_PRESENT))
1046 return CS_NO_CARD;
1047
1048 c = (s->config != NULL) ? &s->config[function] : NULL;
1049 if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
1050 (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
1051 u_char reg;
1052 if (c->Present & PRESENT_PIN_REPLACE) {
1053 pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
1054 status->CardState |=
1055 (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
1056 status->CardState |=
1057 (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
1058 status->CardState |=
1059 (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
1060 status->CardState |=
1061 (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
1062 } else {
1063 /* No PRR? Then assume we're always ready */
1064 status->CardState |= CS_EVENT_READY_CHANGE;
1065 }
1066 if (c->Present & PRESENT_EXT_STATUS) {
1067 pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
1068 status->CardState |=
1069 (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
1070 }
1071 return CS_SUCCESS;
1072 }
1073 status->CardState |=
1074 (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
1075 status->CardState |=
1076 (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
1077 status->CardState |=
1078 (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
1079 status->CardState |=
1080 (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
1081 return CS_SUCCESS;
1082} /* get_status */
1083EXPORT_SYMBOL(pccard_get_status);
1084
1085/*======================================================================
1086
1087 Change the card address of an already open memory window.
1088
1089======================================================================*/
1090
1091int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
1092{
1093 if ((win == NULL) || (win->magic != WINDOW_MAGIC))
1094 return CS_BAD_HANDLE;
1095 req->Page = 0;
1096 req->CardOffset = win->ctl.card_start;
1097 return CS_SUCCESS;
1098} /* get_mem_page */
1099
1100int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
1101{
1102 struct pcmcia_socket *s;
1103 if ((win == NULL) || (win->magic != WINDOW_MAGIC))
1104 return CS_BAD_HANDLE;
1105 if (req->Page != 0)
1106 return CS_BAD_PAGE;
1107 s = win->sock;
1108 win->ctl.card_start = req->CardOffset;
1109 if (s->ops->set_mem_map(s, &win->ctl) != 0)
1110 return CS_BAD_OFFSET;
1111 return CS_SUCCESS;
1112} /* map_mem_page */
1113
1114/*======================================================================
1115
1116 Modify a locked socket configuration
1117
1118======================================================================*/
1119
1120int pcmcia_modify_configuration(client_handle_t handle,
1121 modconf_t *mod)
1122{
1123 struct pcmcia_socket *s;
1124 config_t *c;
1125
1126 if (CHECK_HANDLE(handle))
1127 return CS_BAD_HANDLE;
1128 s = SOCKET(handle); c = CONFIG(handle);
1129 if (!(s->state & SOCKET_PRESENT))
1130 return CS_NO_CARD;
1131 if (!(c->state & CONFIG_LOCKED))
1132 return CS_CONFIGURATION_LOCKED;
1133
1134 if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
1135 if (mod->Attributes & CONF_ENABLE_IRQ) {
1136 c->Attributes |= CONF_ENABLE_IRQ;
1137 s->socket.io_irq = s->irq.AssignedIRQ;
1138 } else {
1139 c->Attributes &= ~CONF_ENABLE_IRQ;
1140 s->socket.io_irq = 0;
1141 }
1142 s->ops->set_socket(s, &s->socket);
1143 }
1144
1145 if (mod->Attributes & CONF_VCC_CHANGE_VALID)
1146 return CS_BAD_VCC;
1147
1148 /* We only allow changing Vpp1 and Vpp2 to the same value */
1149 if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
1150 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
1151 if (mod->Vpp1 != mod->Vpp2)
1152 return CS_BAD_VPP;
1153 c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
1154 if (s->ops->set_socket(s, &s->socket))
1155 return CS_BAD_VPP;
1156 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
1157 (mod->Attributes & CONF_VPP2_CHANGE_VALID))
1158 return CS_BAD_VPP;
1159
1160 return CS_SUCCESS;
1161} /* modify_configuration */
1162 763
1163/* register pcmcia_callback */ 764/* register pcmcia_callback */
1164int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c) 765int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
@@ -1188,530 +789,6 @@ int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c)
1188} 789}
1189EXPORT_SYMBOL(pccard_register_pcmcia); 790EXPORT_SYMBOL(pccard_register_pcmcia);
1190 791
1191/*====================================================================*/
1192
1193int pcmcia_release_configuration(client_handle_t handle)
1194{
1195 pccard_io_map io = { 0, 0, 0, 0, 1 };
1196 struct pcmcia_socket *s;
1197 int i;
1198
1199 if (CHECK_HANDLE(handle) ||
1200 !(handle->state & CLIENT_CONFIG_LOCKED))
1201 return CS_BAD_HANDLE;
1202 handle->state &= ~CLIENT_CONFIG_LOCKED;
1203 s = SOCKET(handle);
1204
1205#ifdef CONFIG_CARDBUS
1206 if (handle->state & CLIENT_CARDBUS)
1207 return CS_SUCCESS;
1208#endif
1209
1210 if (!(handle->state & CLIENT_STALE)) {
1211 config_t *c = CONFIG(handle);
1212 if (--(s->lock_count) == 0) {
1213 s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
1214 s->socket.Vpp = 0;
1215 s->socket.io_irq = 0;
1216 s->ops->set_socket(s, &s->socket);
1217 }
1218 if (c->state & CONFIG_IO_REQ)
1219 for (i = 0; i < MAX_IO_WIN; i++) {
1220 if (s->io[i].NumPorts == 0)
1221 continue;
1222 s->io[i].Config--;
1223 if (s->io[i].Config != 0)
1224 continue;
1225 io.map = i;
1226 s->ops->set_io_map(s, &io);
1227 }
1228 c->state &= ~CONFIG_LOCKED;
1229 }
1230
1231 return CS_SUCCESS;
1232} /* release_configuration */
1233
1234/*======================================================================
1235
1236 Release_io() releases the I/O ranges allocated by a client. This
1237 may be invoked some time after a card ejection has already dumped
1238 the actual socket configuration, so if the client is "stale", we
1239 don't bother checking the port ranges against the current socket
1240 values.
1241
1242======================================================================*/
1243
1244int pcmcia_release_io(client_handle_t handle, io_req_t *req)
1245{
1246 struct pcmcia_socket *s;
1247
1248 if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
1249 return CS_BAD_HANDLE;
1250 handle->state &= ~CLIENT_IO_REQ;
1251 s = SOCKET(handle);
1252
1253#ifdef CONFIG_CARDBUS
1254 if (handle->state & CLIENT_CARDBUS)
1255 return CS_SUCCESS;
1256#endif
1257
1258 if (!(handle->state & CLIENT_STALE)) {
1259 config_t *c = CONFIG(handle);
1260 if (c->state & CONFIG_LOCKED)
1261 return CS_CONFIGURATION_LOCKED;
1262 if ((c->io.BasePort1 != req->BasePort1) ||
1263 (c->io.NumPorts1 != req->NumPorts1) ||
1264 (c->io.BasePort2 != req->BasePort2) ||
1265 (c->io.NumPorts2 != req->NumPorts2))
1266 return CS_BAD_ARGS;
1267 c->state &= ~CONFIG_IO_REQ;
1268 }
1269
1270 release_io_space(s, req->BasePort1, req->NumPorts1);
1271 if (req->NumPorts2)
1272 release_io_space(s, req->BasePort2, req->NumPorts2);
1273
1274 return CS_SUCCESS;
1275} /* release_io */
1276
1277/*====================================================================*/
1278
1279int pcmcia_release_irq(client_handle_t handle, irq_req_t *req)
1280{
1281 struct pcmcia_socket *s;
1282 if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ))
1283 return CS_BAD_HANDLE;
1284 handle->state &= ~CLIENT_IRQ_REQ;
1285 s = SOCKET(handle);
1286
1287 if (!(handle->state & CLIENT_STALE)) {
1288 config_t *c = CONFIG(handle);
1289 if (c->state & CONFIG_LOCKED)
1290 return CS_CONFIGURATION_LOCKED;
1291 if (c->irq.Attributes != req->Attributes)
1292 return CS_BAD_ATTRIBUTE;
1293 if (s->irq.AssignedIRQ != req->AssignedIRQ)
1294 return CS_BAD_IRQ;
1295 if (--s->irq.Config == 0) {
1296 c->state &= ~CONFIG_IRQ_REQ;
1297 s->irq.AssignedIRQ = 0;
1298 }
1299 }
1300
1301 if (req->Attributes & IRQ_HANDLE_PRESENT) {
1302 free_irq(req->AssignedIRQ, req->Instance);
1303 }
1304
1305#ifdef CONFIG_PCMCIA_PROBE
1306 pcmcia_used_irq[req->AssignedIRQ]--;
1307#endif
1308
1309 return CS_SUCCESS;
1310} /* cs_release_irq */
1311
1312/*====================================================================*/
1313
1314int pcmcia_release_window(window_handle_t win)
1315{
1316 struct pcmcia_socket *s;
1317
1318 if ((win == NULL) || (win->magic != WINDOW_MAGIC))
1319 return CS_BAD_HANDLE;
1320 s = win->sock;
1321 if (!(win->handle->state & CLIENT_WIN_REQ(win->index)))
1322 return CS_BAD_HANDLE;
1323
1324 /* Shut down memory window */
1325 win->ctl.flags &= ~MAP_ACTIVE;
1326 s->ops->set_mem_map(s, &win->ctl);
1327 s->state &= ~SOCKET_WIN_REQ(win->index);
1328
1329 /* Release system memory */
1330 if (win->ctl.res) {
1331 release_resource(win->ctl.res);
1332 kfree(win->ctl.res);
1333 win->ctl.res = NULL;
1334 }
1335 win->handle->state &= ~CLIENT_WIN_REQ(win->index);
1336
1337 win->magic = 0;
1338
1339 return CS_SUCCESS;
1340} /* release_window */
1341
1342/*====================================================================*/
1343
1344int pcmcia_request_configuration(client_handle_t handle,
1345 config_req_t *req)
1346{
1347 int i;
1348 u_int base;
1349 struct pcmcia_socket *s;
1350 config_t *c;
1351 pccard_io_map iomap;
1352
1353 if (CHECK_HANDLE(handle))
1354 return CS_BAD_HANDLE;
1355 s = SOCKET(handle);
1356 if (!(s->state & SOCKET_PRESENT))
1357 return CS_NO_CARD;
1358
1359#ifdef CONFIG_CARDBUS
1360 if (handle->state & CLIENT_CARDBUS)
1361 return CS_UNSUPPORTED_MODE;
1362#endif
1363
1364 if (req->IntType & INT_CARDBUS)
1365 return CS_UNSUPPORTED_MODE;
1366 c = CONFIG(handle);
1367 if (c->state & CONFIG_LOCKED)
1368 return CS_CONFIGURATION_LOCKED;
1369
1370 /* Do power control. We don't allow changes in Vcc. */
1371 if (s->socket.Vcc != req->Vcc)
1372 return CS_BAD_VCC;
1373 if (req->Vpp1 != req->Vpp2)
1374 return CS_BAD_VPP;
1375 s->socket.Vpp = req->Vpp1;
1376 if (s->ops->set_socket(s, &s->socket))
1377 return CS_BAD_VPP;
1378
1379 c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
1380
1381 /* Pick memory or I/O card, DMA mode, interrupt */
1382 c->IntType = req->IntType;
1383 c->Attributes = req->Attributes;
1384 if (req->IntType & INT_MEMORY_AND_IO)
1385 s->socket.flags |= SS_IOCARD;
1386 if (req->IntType & INT_ZOOMED_VIDEO)
1387 s->socket.flags |= SS_ZVCARD | SS_IOCARD;
1388 if (req->Attributes & CONF_ENABLE_DMA)
1389 s->socket.flags |= SS_DMA_MODE;
1390 if (req->Attributes & CONF_ENABLE_SPKR)
1391 s->socket.flags |= SS_SPKR_ENA;
1392 if (req->Attributes & CONF_ENABLE_IRQ)
1393 s->socket.io_irq = s->irq.AssignedIRQ;
1394 else
1395 s->socket.io_irq = 0;
1396 s->ops->set_socket(s, &s->socket);
1397 s->lock_count++;
1398
1399 /* Set up CIS configuration registers */
1400 base = c->ConfigBase = req->ConfigBase;
1401 c->Present = c->CardValues = req->Present;
1402 if (req->Present & PRESENT_COPY) {
1403 c->Copy = req->Copy;
1404 pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
1405 }
1406 if (req->Present & PRESENT_OPTION) {
1407 if (s->functions == 1) {
1408 c->Option = req->ConfigIndex & COR_CONFIG_MASK;
1409 } else {
1410 c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
1411 c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
1412 if (req->Present & PRESENT_IOBASE_0)
1413 c->Option |= COR_ADDR_DECODE;
1414 }
1415 if (c->state & CONFIG_IRQ_REQ)
1416 if (!(c->irq.Attributes & IRQ_FORCED_PULSE))
1417 c->Option |= COR_LEVEL_REQ;
1418 pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
1419 mdelay(40);
1420 }
1421 if (req->Present & PRESENT_STATUS) {
1422 c->Status = req->Status;
1423 pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
1424 }
1425 if (req->Present & PRESENT_PIN_REPLACE) {
1426 c->Pin = req->Pin;
1427 pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
1428 }
1429 if (req->Present & PRESENT_EXT_STATUS) {
1430 c->ExtStatus = req->ExtStatus;
1431 pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
1432 }
1433 if (req->Present & PRESENT_IOBASE_0) {
1434 u_char b = c->io.BasePort1 & 0xff;
1435 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
1436 b = (c->io.BasePort1 >> 8) & 0xff;
1437 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
1438 }
1439 if (req->Present & PRESENT_IOSIZE) {
1440 u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
1441 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
1442 }
1443
1444 /* Configure I/O windows */
1445 if (c->state & CONFIG_IO_REQ) {
1446 iomap.speed = io_speed;
1447 for (i = 0; i < MAX_IO_WIN; i++)
1448 if (s->io[i].NumPorts != 0) {
1449 iomap.map = i;
1450 iomap.flags = MAP_ACTIVE;
1451 switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
1452 case IO_DATA_PATH_WIDTH_16:
1453 iomap.flags |= MAP_16BIT; break;
1454 case IO_DATA_PATH_WIDTH_AUTO:
1455 iomap.flags |= MAP_AUTOSZ; break;
1456 default:
1457 break;
1458 }
1459 iomap.start = s->io[i].BasePort;
1460 iomap.stop = iomap.start + s->io[i].NumPorts - 1;
1461 s->ops->set_io_map(s, &iomap);
1462 s->io[i].Config++;
1463 }
1464 }
1465
1466 c->state |= CONFIG_LOCKED;
1467 handle->state |= CLIENT_CONFIG_LOCKED;
1468 return CS_SUCCESS;
1469} /* request_configuration */
1470
1471/*======================================================================
1472
1473 Request_io() reserves ranges of port addresses for a socket.
1474 I have not implemented range sharing or alias addressing.
1475
1476======================================================================*/
1477
1478int pcmcia_request_io(client_handle_t handle, io_req_t *req)
1479{
1480 struct pcmcia_socket *s;
1481 config_t *c;
1482
1483 if (CHECK_HANDLE(handle))
1484 return CS_BAD_HANDLE;
1485 s = SOCKET(handle);
1486 if (!(s->state & SOCKET_PRESENT))
1487 return CS_NO_CARD;
1488
1489 if (handle->state & CLIENT_CARDBUS) {
1490#ifdef CONFIG_CARDBUS
1491 handle->state |= CLIENT_IO_REQ;
1492 return CS_SUCCESS;
1493#else
1494 return CS_UNSUPPORTED_FUNCTION;
1495#endif
1496 }
1497
1498 if (!req)
1499 return CS_UNSUPPORTED_MODE;
1500 c = CONFIG(handle);
1501 if (c->state & CONFIG_LOCKED)
1502 return CS_CONFIGURATION_LOCKED;
1503 if (c->state & CONFIG_IO_REQ)
1504 return CS_IN_USE;
1505 if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))
1506 return CS_BAD_ATTRIBUTE;
1507 if ((req->NumPorts2 > 0) &&
1508 (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)))
1509 return CS_BAD_ATTRIBUTE;
1510
1511 if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
1512 req->NumPorts1, req->IOAddrLines))
1513 return CS_IN_USE;
1514
1515 if (req->NumPorts2) {
1516 if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
1517 req->NumPorts2, req->IOAddrLines)) {
1518 release_io_space(s, req->BasePort1, req->NumPorts1);
1519 return CS_IN_USE;
1520 }
1521 }
1522
1523 c->io = *req;
1524 c->state |= CONFIG_IO_REQ;
1525 handle->state |= CLIENT_IO_REQ;
1526 return CS_SUCCESS;
1527} /* request_io */
1528
1529/*======================================================================
1530
1531 Request_irq() reserves an irq for this client.
1532
1533 Also, since Linux only reserves irq's when they are actually
1534 hooked, we don't guarantee that an irq will still be available
1535 when the configuration is locked. Now that I think about it,
1536 there might be a way to fix this using a dummy handler.
1537
1538======================================================================*/
1539
1540#ifdef CONFIG_PCMCIA_PROBE
1541static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs)
1542{
1543 return IRQ_NONE;
1544}
1545#endif
1546
1547int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
1548{
1549 struct pcmcia_socket *s;
1550 config_t *c;
1551 int ret = CS_IN_USE, irq = 0;
1552 struct pcmcia_device *p_dev = handle_to_pdev(handle);
1553
1554 if (CHECK_HANDLE(handle))
1555 return CS_BAD_HANDLE;
1556 s = SOCKET(handle);
1557 if (!(s->state & SOCKET_PRESENT))
1558 return CS_NO_CARD;
1559 c = CONFIG(handle);
1560 if (c->state & CONFIG_LOCKED)
1561 return CS_CONFIGURATION_LOCKED;
1562 if (c->state & CONFIG_IRQ_REQ)
1563 return CS_IN_USE;
1564
1565#ifdef CONFIG_PCMCIA_PROBE
1566 if (s->irq.AssignedIRQ != 0) {
1567 /* If the interrupt is already assigned, it must be the same */
1568 irq = s->irq.AssignedIRQ;
1569 } else {
1570 int try;
1571 u32 mask = s->irq_mask;
1572 void *data = NULL;
1573
1574 for (try = 0; try < 64; try++) {
1575 irq = try % 32;
1576
1577 /* marked as available by driver, and not blocked by userspace? */
1578 if (!((mask >> irq) & 1))
1579 continue;
1580
1581 /* avoid an IRQ which is already used by a PCMCIA card */
1582 if ((try < 32) && pcmcia_used_irq[irq])
1583 continue;
1584
1585 /* register the correct driver, if possible, of check whether
1586 * registering a dummy handle works, i.e. if the IRQ isn't
1587 * marked as used by the kernel resource management core */
1588 ret = request_irq(irq,
1589 (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action,
1590 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
1591 (s->functions > 1) ||
1592 (irq == s->pci_irq)) ? SA_SHIRQ : 0,
1593 p_dev->dev.bus_id,
1594 (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
1595 if (!ret) {
1596 if (!(req->Attributes & IRQ_HANDLE_PRESENT))
1597 free_irq(irq, data);
1598 break;
1599 }
1600 }
1601 }
1602#endif
1603 if (ret) {
1604 if (!s->pci_irq)
1605 return ret;
1606 irq = s->pci_irq;
1607 }
1608
1609 if (ret && req->Attributes & IRQ_HANDLE_PRESENT) {
1610 if (request_irq(irq, req->Handler,
1611 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
1612 (s->functions > 1) ||
1613 (irq == s->pci_irq)) ? SA_SHIRQ : 0,
1614 p_dev->dev.bus_id, req->Instance))
1615 return CS_IN_USE;
1616 }
1617
1618 c->irq.Attributes = req->Attributes;
1619 s->irq.AssignedIRQ = req->AssignedIRQ = irq;
1620 s->irq.Config++;
1621
1622 c->state |= CONFIG_IRQ_REQ;
1623 handle->state |= CLIENT_IRQ_REQ;
1624
1625#ifdef CONFIG_PCMCIA_PROBE
1626 pcmcia_used_irq[irq]++;
1627#endif
1628
1629 return CS_SUCCESS;
1630} /* pcmcia_request_irq */
1631
1632/*======================================================================
1633
1634 Request_window() establishes a mapping between card memory space
1635 and system memory space.
1636
1637======================================================================*/
1638
1639int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh)
1640{
1641 struct pcmcia_socket *s;
1642 window_t *win;
1643 u_long align;
1644 int w;
1645
1646 if (CHECK_HANDLE(*handle))
1647 return CS_BAD_HANDLE;
1648 s = (*handle)->Socket;
1649 if (!(s->state & SOCKET_PRESENT))
1650 return CS_NO_CARD;
1651 if (req->Attributes & (WIN_PAGED | WIN_SHARED))
1652 return CS_BAD_ATTRIBUTE;
1653
1654 /* Window size defaults to smallest available */
1655 if (req->Size == 0)
1656 req->Size = s->map_size;
1657 align = (((s->features & SS_CAP_MEM_ALIGN) ||
1658 (req->Attributes & WIN_STRICT_ALIGN)) ?
1659 req->Size : s->map_size);
1660 if (req->Size & (s->map_size-1))
1661 return CS_BAD_SIZE;
1662 if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
1663 (req->Base & (align-1)))
1664 return CS_BAD_BASE;
1665 if (req->Base)
1666 align = 0;
1667
1668 /* Allocate system memory window */
1669 for (w = 0; w < MAX_WIN; w++)
1670 if (!(s->state & SOCKET_WIN_REQ(w))) break;
1671 if (w == MAX_WIN)
1672 return CS_OUT_OF_RESOURCE;
1673
1674 win = &s->win[w];
1675 win->magic = WINDOW_MAGIC;
1676 win->index = w;
1677 win->handle = *handle;
1678 win->sock = s;
1679
1680 if (!(s->features & SS_CAP_STATIC_MAP)) {
1681 win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align,
1682 (req->Attributes & WIN_MAP_BELOW_1MB), s);
1683 if (!win->ctl.res)
1684 return CS_IN_USE;
1685 }
1686 (*handle)->state |= CLIENT_WIN_REQ(w);
1687
1688 /* Configure the socket controller */
1689 win->ctl.map = w+1;
1690 win->ctl.flags = 0;
1691 win->ctl.speed = req->AccessSpeed;
1692 if (req->Attributes & WIN_MEMORY_TYPE)
1693 win->ctl.flags |= MAP_ATTRIB;
1694 if (req->Attributes & WIN_ENABLE)
1695 win->ctl.flags |= MAP_ACTIVE;
1696 if (req->Attributes & WIN_DATA_WIDTH_16)
1697 win->ctl.flags |= MAP_16BIT;
1698 if (req->Attributes & WIN_USE_WAIT)
1699 win->ctl.flags |= MAP_USE_WAIT;
1700 win->ctl.card_start = 0;
1701 if (s->ops->set_mem_map(s, &win->ctl) != 0)
1702 return CS_BAD_ARGS;
1703 s->state |= SOCKET_WIN_REQ(w);
1704
1705 /* Return window handle */
1706 if (s->features & SS_CAP_STATIC_MAP) {
1707 req->Base = win->ctl.static_start;
1708 } else {
1709 req->Base = win->ctl.res->start;
1710 }
1711 *wh = win;
1712
1713 return CS_SUCCESS;
1714} /* request_window */
1715 792
1716/*====================================================================== 793/*======================================================================
1717 794
@@ -1888,20 +965,8 @@ static int pcmcia_socket_hotplug(struct class_device *dev, char **envp,
1888======================================================================*/ 965======================================================================*/
1889/* in alpha order */ 966/* in alpha order */
1890EXPORT_SYMBOL(pcmcia_eject_card); 967EXPORT_SYMBOL(pcmcia_eject_card);
1891EXPORT_SYMBOL(pcmcia_get_card_services_info);
1892EXPORT_SYMBOL(pcmcia_get_mem_page);
1893EXPORT_SYMBOL(pcmcia_insert_card); 968EXPORT_SYMBOL(pcmcia_insert_card);
1894EXPORT_SYMBOL(pcmcia_map_mem_page);
1895EXPORT_SYMBOL(pcmcia_modify_configuration);
1896EXPORT_SYMBOL(pcmcia_release_configuration);
1897EXPORT_SYMBOL(pcmcia_release_io);
1898EXPORT_SYMBOL(pcmcia_release_irq);
1899EXPORT_SYMBOL(pcmcia_release_window);
1900EXPORT_SYMBOL(pcmcia_replace_cis); 969EXPORT_SYMBOL(pcmcia_replace_cis);
1901EXPORT_SYMBOL(pcmcia_request_configuration);
1902EXPORT_SYMBOL(pcmcia_request_io);
1903EXPORT_SYMBOL(pcmcia_request_irq);
1904EXPORT_SYMBOL(pcmcia_request_window);
1905EXPORT_SYMBOL(pcmcia_resume_card); 970EXPORT_SYMBOL(pcmcia_resume_card);
1906EXPORT_SYMBOL(pcmcia_suspend_card); 971EXPORT_SYMBOL(pcmcia_suspend_card);
1907 972
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
new file mode 100644
index 000000000000..cf66b9978942
--- /dev/null
+++ b/drivers/pcmcia/pcmcia_resource.c
@@ -0,0 +1,989 @@
1/*
2 * PCMCIA 16-bit resource management functions
3 *
4 * The initial developer of the original code is David A. Hinds
5 * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
6 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
7 *
8 * Copyright (C) 1999 David A. Hinds
9 * Copyright (C) 2004-2005 Dominik Brodowski
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 */
16
17#include <linux/config.h>
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/interrupt.h>
21#include <linux/delay.h>
22#include <linux/pci.h>
23#include <linux/device.h>
24
25#define IN_CARD_SERVICES
26#include <pcmcia/version.h>
27#include <pcmcia/cs_types.h>
28#include <pcmcia/ss.h>
29#include <pcmcia/cs.h>
30#include <pcmcia/bulkmem.h>
31#include <pcmcia/cistpl.h>
32#include <pcmcia/cisreg.h>
33#include <pcmcia/ds.h>
34
35#include "cs_internal.h"
36#include "ds_internal.h"
37
38
39static const char *release = "Linux Kernel Card Services";
40
41/* Access speed for IO windows */
42static int io_speed = 0;
43module_param(io_speed, int, 0444);
44
45
46#ifdef CONFIG_PCMCIA_PROBE
47/* mask of IRQs already reserved by other cards, we should avoid using them */
48static u8 pcmcia_used_irq[NR_IRQS];
49#endif
50
51
52#ifdef DEBUG
53extern int ds_pc_debug;
54#define cs_socket_name(skt) ((skt)->dev.class_id)
55
56#define ds_dbg(skt, lvl, fmt, arg...) do { \
57 if (ds_pc_debug >= lvl) \
58 printk(KERN_DEBUG "pcmcia_resource: %s: " fmt, \
59 cs_socket_name(skt) , ## arg); \
60} while (0)
61#else
62#define ds_dbg(lvl, fmt, arg...) do { } while (0)
63#endif
64
65
66
67/** alloc_io_space
68 *
69 * Special stuff for managing IO windows, because they are scarce
70 */
71
72static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
73 ioaddr_t num, u_int lines)
74{
75 int i;
76 kio_addr_t try, align;
77
78 align = (*base) ? (lines ? 1<<lines : 0) : 1;
79 if (align && (align < num)) {
80 if (*base) {
81 ds_dbg(s, 0, "odd IO request: num %#x align %#lx\n",
82 num, align);
83 align = 0;
84 } else
85 while (align && (align < num)) align <<= 1;
86 }
87 if (*base & ~(align-1)) {
88 ds_dbg(s, 0, "odd IO request: base %#x align %#lx\n",
89 *base, align);
90 align = 0;
91 }
92 if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
93 *base = s->io_offset | (*base & 0x0fff);
94 return 0;
95 }
96 /* Check for an already-allocated window that must conflict with
97 * what was asked for. It is a hack because it does not catch all
98 * potential conflicts, just the most obvious ones.
99 */
100 for (i = 0; i < MAX_IO_WIN; i++)
101 if ((s->io[i].NumPorts != 0) &&
102 ((s->io[i].BasePort & (align-1)) == *base))
103 return 1;
104 for (i = 0; i < MAX_IO_WIN; i++) {
105 if (s->io[i].NumPorts == 0) {
106 s->io[i].res = pcmcia_find_io_region(*base, num, align, s);
107 if (s->io[i].res) {
108 s->io[i].Attributes = attr;
109 s->io[i].BasePort = *base = s->io[i].res->start;
110 s->io[i].NumPorts = s->io[i].InUse = num;
111 break;
112 } else
113 return 1;
114 } else if (s->io[i].Attributes != attr)
115 continue;
116 /* Try to extend top of window */
117 try = s->io[i].BasePort + s->io[i].NumPorts;
118 if ((*base == 0) || (*base == try))
119 if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start,
120 s->io[i].res->end + num, s) == 0) {
121 *base = try;
122 s->io[i].NumPorts += num;
123 s->io[i].InUse += num;
124 break;
125 }
126 /* Try to extend bottom of window */
127 try = s->io[i].BasePort - num;
128 if ((*base == 0) || (*base == try))
129 if (pcmcia_adjust_io_region(s->io[i].res, s->io[i].res->start - num,
130 s->io[i].res->end, s) == 0) {
131 s->io[i].BasePort = *base = try;
132 s->io[i].NumPorts += num;
133 s->io[i].InUse += num;
134 break;
135 }
136 }
137 return (i == MAX_IO_WIN);
138} /* alloc_io_space */
139
140
141static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
142 ioaddr_t num)
143{
144 int i;
145
146 for (i = 0; i < MAX_IO_WIN; i++) {
147 if ((s->io[i].BasePort <= base) &&
148 (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {
149 s->io[i].InUse -= num;
150 /* Free the window if no one else is using it */
151 if (s->io[i].InUse == 0) {
152 s->io[i].NumPorts = 0;
153 release_resource(s->io[i].res);
154 kfree(s->io[i].res);
155 s->io[i].res = NULL;
156 }
157 }
158 }
159} /* release_io_space */
160
161
162/** pccard_access_configuration_register
163 *
164 * Access_configuration_register() reads and writes configuration
165 * registers in attribute memory. Memory window 0 is reserved for
166 * this and the tuple reading services.
167 */
168
169int pccard_access_configuration_register(struct pcmcia_socket *s,
170 unsigned int function,
171 conf_reg_t *reg)
172{
173 config_t *c;
174 int addr;
175 u_char val;
176
177 if (!s || !s->config)
178 return CS_NO_CARD;
179
180 c = &s->config[function];
181
182 if (c == NULL)
183 return CS_NO_CARD;
184
185 if (!(c->state & CONFIG_LOCKED))
186 return CS_CONFIGURATION_LOCKED;
187
188 addr = (c->ConfigBase + reg->Offset) >> 1;
189
190 switch (reg->Action) {
191 case CS_READ:
192 pcmcia_read_cis_mem(s, 1, addr, 1, &val);
193 reg->Value = val;
194 break;
195 case CS_WRITE:
196 val = reg->Value;
197 pcmcia_write_cis_mem(s, 1, addr, 1, &val);
198 break;
199 default:
200 return CS_BAD_ARGS;
201 break;
202 }
203 return CS_SUCCESS;
204} /* pccard_access_configuration_register */
205EXPORT_SYMBOL(pccard_access_configuration_register);
206
207
208int pccard_get_configuration_info(struct pcmcia_socket *s,
209 unsigned int function,
210 config_info_t *config)
211{
212 config_t *c;
213
214 if (!(s->state & SOCKET_PRESENT))
215 return CS_NO_CARD;
216
217 config->Function = function;
218
219#ifdef CONFIG_CARDBUS
220 if (s->state & SOCKET_CARDBUS) {
221 memset(config, 0, sizeof(config_info_t));
222 config->Vcc = s->socket.Vcc;
223 config->Vpp1 = config->Vpp2 = s->socket.Vpp;
224 config->Option = s->cb_dev->subordinate->number;
225 if (s->state & SOCKET_CARDBUS_CONFIG) {
226 config->Attributes = CONF_VALID_CLIENT;
227 config->IntType = INT_CARDBUS;
228 config->AssignedIRQ = s->irq.AssignedIRQ;
229 if (config->AssignedIRQ)
230 config->Attributes |= CONF_ENABLE_IRQ;
231 config->BasePort1 = s->io[0].BasePort;
232 config->NumPorts1 = s->io[0].NumPorts;
233 }
234 return CS_SUCCESS;
235 }
236#endif
237
238 c = (s->config != NULL) ? &s->config[function] : NULL;
239
240 if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
241 config->Attributes = 0;
242 config->Vcc = s->socket.Vcc;
243 config->Vpp1 = config->Vpp2 = s->socket.Vpp;
244 return CS_SUCCESS;
245 }
246
247 /* !!! This is a hack !!! */
248 memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
249 config->Attributes |= CONF_VALID_CLIENT;
250 config->CardValues = c->CardValues;
251 config->IRQAttributes = c->irq.Attributes;
252 config->AssignedIRQ = s->irq.AssignedIRQ;
253 config->BasePort1 = c->io.BasePort1;
254 config->NumPorts1 = c->io.NumPorts1;
255 config->Attributes1 = c->io.Attributes1;
256 config->BasePort2 = c->io.BasePort2;
257 config->NumPorts2 = c->io.NumPorts2;
258 config->Attributes2 = c->io.Attributes2;
259 config->IOAddrLines = c->io.IOAddrLines;
260
261 return CS_SUCCESS;
262} /* pccard_get_configuration_info */
263EXPORT_SYMBOL(pccard_get_configuration_info);
264
265
266/** pcmcia_get_card_services_info
267 *
268 * Return information about this version of Card Services
269 */
270
271int pcmcia_get_card_services_info(servinfo_t *info)
272{
273 unsigned int socket_count = 0;
274 struct list_head *tmp;
275 info->Signature[0] = 'C';
276 info->Signature[1] = 'S';
277 down_read(&pcmcia_socket_list_rwsem);
278 list_for_each(tmp, &pcmcia_socket_list)
279 socket_count++;
280 up_read(&pcmcia_socket_list_rwsem);
281 info->Count = socket_count;
282 info->Revision = CS_RELEASE_CODE;
283 info->CSLevel = 0x0210;
284 info->VendorString = (char *)release;
285 return CS_SUCCESS;
286} /* get_card_services_info */
287EXPORT_SYMBOL(pcmcia_get_card_services_info);
288
289
290/** pcmcia_get_window
291 */
292int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
293 int idx, win_req_t *req)
294{
295 window_t *win;
296 int w;
297
298 if (!s || !(s->state & SOCKET_PRESENT))
299 return CS_NO_CARD;
300 for (w = idx; w < MAX_WIN; w++)
301 if (s->state & SOCKET_WIN_REQ(w))
302 break;
303 if (w == MAX_WIN)
304 return CS_NO_MORE_ITEMS;
305 win = &s->win[w];
306 req->Base = win->ctl.res->start;
307 req->Size = win->ctl.res->end - win->ctl.res->start + 1;
308 req->AccessSpeed = win->ctl.speed;
309 req->Attributes = 0;
310 if (win->ctl.flags & MAP_ATTRIB)
311 req->Attributes |= WIN_MEMORY_TYPE_AM;
312 if (win->ctl.flags & MAP_ACTIVE)
313 req->Attributes |= WIN_ENABLE;
314 if (win->ctl.flags & MAP_16BIT)
315 req->Attributes |= WIN_DATA_WIDTH_16;
316 if (win->ctl.flags & MAP_USE_WAIT)
317 req->Attributes |= WIN_USE_WAIT;
318 *handle = win;
319 return CS_SUCCESS;
320} /* pcmcia_get_window */
321EXPORT_SYMBOL(pcmcia_get_window);
322
323
324/** pccard_get_status
325 *
326 * Get the current socket state bits. We don't support the latched
327 * SocketState yet: I haven't seen any point for it.
328 */
329
330int pccard_get_status(struct pcmcia_socket *s, unsigned int function,
331 cs_status_t *status)
332{
333 config_t *c;
334 int val;
335
336 s->ops->get_status(s, &val);
337 status->CardState = status->SocketState = 0;
338 status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
339 status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
340 status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
341 status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
342 if (s->state & SOCKET_SUSPEND)
343 status->CardState |= CS_EVENT_PM_SUSPEND;
344 if (!(s->state & SOCKET_PRESENT))
345 return CS_NO_CARD;
346
347 c = (s->config != NULL) ? &s->config[function] : NULL;
348 if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
349 (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
350 u_char reg;
351 if (c->Present & PRESENT_PIN_REPLACE) {
352 pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
353 status->CardState |=
354 (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
355 status->CardState |=
356 (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
357 status->CardState |=
358 (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
359 status->CardState |=
360 (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
361 } else {
362 /* No PRR? Then assume we're always ready */
363 status->CardState |= CS_EVENT_READY_CHANGE;
364 }
365 if (c->Present & PRESENT_EXT_STATUS) {
366 pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
367 status->CardState |=
368 (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
369 }
370 return CS_SUCCESS;
371 }
372 status->CardState |=
373 (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
374 status->CardState |=
375 (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
376 status->CardState |=
377 (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
378 status->CardState |=
379 (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
380 return CS_SUCCESS;
381} /* pccard_get_status */
382EXPORT_SYMBOL(pccard_get_status);
383
384
385/** pcmcia_get_mem_page
386 *
387 * Change the card address of an already open memory window.
388 */
389int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
390{
391 if ((win == NULL) || (win->magic != WINDOW_MAGIC))
392 return CS_BAD_HANDLE;
393 req->Page = 0;
394 req->CardOffset = win->ctl.card_start;
395 return CS_SUCCESS;
396} /* pcmcia_get_mem_page */
397EXPORT_SYMBOL(pcmcia_get_mem_page);
398
399
400int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
401{
402 struct pcmcia_socket *s;
403 if ((win == NULL) || (win->magic != WINDOW_MAGIC))
404 return CS_BAD_HANDLE;
405 if (req->Page != 0)
406 return CS_BAD_PAGE;
407 s = win->sock;
408 win->ctl.card_start = req->CardOffset;
409 if (s->ops->set_mem_map(s, &win->ctl) != 0)
410 return CS_BAD_OFFSET;
411 return CS_SUCCESS;
412} /* pcmcia_map_mem_page */
413EXPORT_SYMBOL(pcmcia_map_mem_page);
414
415
416/** pcmcia_modify_configuration
417 *
418 * Modify a locked socket configuration
419 */
420int pcmcia_modify_configuration(client_handle_t handle,
421 modconf_t *mod)
422{
423 struct pcmcia_socket *s;
424 config_t *c;
425
426 if (CHECK_HANDLE(handle))
427 return CS_BAD_HANDLE;
428 s = SOCKET(handle);
429 c = CONFIG(handle);
430 if (!(s->state & SOCKET_PRESENT))
431 return CS_NO_CARD;
432 if (!(c->state & CONFIG_LOCKED))
433 return CS_CONFIGURATION_LOCKED;
434
435 if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
436 if (mod->Attributes & CONF_ENABLE_IRQ) {
437 c->Attributes |= CONF_ENABLE_IRQ;
438 s->socket.io_irq = s->irq.AssignedIRQ;
439 } else {
440 c->Attributes &= ~CONF_ENABLE_IRQ;
441 s->socket.io_irq = 0;
442 }
443 s->ops->set_socket(s, &s->socket);
444 }
445
446 if (mod->Attributes & CONF_VCC_CHANGE_VALID)
447 return CS_BAD_VCC;
448
449 /* We only allow changing Vpp1 and Vpp2 to the same value */
450 if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
451 (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
452 if (mod->Vpp1 != mod->Vpp2)
453 return CS_BAD_VPP;
454 c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
455 if (s->ops->set_socket(s, &s->socket))
456 return CS_BAD_VPP;
457 } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
458 (mod->Attributes & CONF_VPP2_CHANGE_VALID))
459 return CS_BAD_VPP;
460
461 return CS_SUCCESS;
462} /* modify_configuration */
463EXPORT_SYMBOL(pcmcia_modify_configuration);
464
465
466int pcmcia_release_configuration(client_handle_t handle)
467{
468 pccard_io_map io = { 0, 0, 0, 0, 1 };
469 struct pcmcia_socket *s;
470 int i;
471
472 if (CHECK_HANDLE(handle) ||
473 !(handle->state & CLIENT_CONFIG_LOCKED))
474 return CS_BAD_HANDLE;
475 handle->state &= ~CLIENT_CONFIG_LOCKED;
476 s = SOCKET(handle);
477
478#ifdef CONFIG_CARDBUS
479 if (handle->state & CLIENT_CARDBUS)
480 return CS_SUCCESS;
481#endif
482
483 if (!(handle->state & CLIENT_STALE)) {
484 config_t *c = CONFIG(handle);
485 if (--(s->lock_count) == 0) {
486 s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
487 s->socket.Vpp = 0;
488 s->socket.io_irq = 0;
489 s->ops->set_socket(s, &s->socket);
490 }
491 if (c->state & CONFIG_IO_REQ)
492 for (i = 0; i < MAX_IO_WIN; i++) {
493 if (s->io[i].NumPorts == 0)
494 continue;
495 s->io[i].Config--;
496 if (s->io[i].Config != 0)
497 continue;
498 io.map = i;
499 s->ops->set_io_map(s, &io);
500 }
501 c->state &= ~CONFIG_LOCKED;
502 }
503
504 return CS_SUCCESS;
505} /* pcmcia_release_configuration */
506EXPORT_SYMBOL(pcmcia_release_configuration);
507
508
509/** pcmcia_release_io
510 *
511 * Release_io() releases the I/O ranges allocated by a client. This
512 * may be invoked some time after a card ejection has already dumped
513 * the actual socket configuration, so if the client is "stale", we
514 * don't bother checking the port ranges against the current socket
515 * values.
516 */
517int pcmcia_release_io(client_handle_t handle, io_req_t *req)
518{
519 struct pcmcia_socket *s;
520
521 if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ))
522 return CS_BAD_HANDLE;
523 handle->state &= ~CLIENT_IO_REQ;
524 s = SOCKET(handle);
525
526#ifdef CONFIG_CARDBUS
527 if (handle->state & CLIENT_CARDBUS)
528 return CS_SUCCESS;
529#endif
530
531 if (!(handle->state & CLIENT_STALE)) {
532 config_t *c = CONFIG(handle);
533 if (c->state & CONFIG_LOCKED)
534 return CS_CONFIGURATION_LOCKED;
535 if ((c->io.BasePort1 != req->BasePort1) ||
536 (c->io.NumPorts1 != req->NumPorts1) ||
537 (c->io.BasePort2 != req->BasePort2) ||
538 (c->io.NumPorts2 != req->NumPorts2))
539 return CS_BAD_ARGS;
540 c->state &= ~CONFIG_IO_REQ;
541 }
542
543 release_io_space(s, req->BasePort1, req->NumPorts1);
544 if (req->NumPorts2)
545 release_io_space(s, req->BasePort2, req->NumPorts2);
546
547 return CS_SUCCESS;
548} /* pcmcia_release_io */
549EXPORT_SYMBOL(pcmcia_release_io);
550
551
552int pcmcia_release_irq(client_handle_t handle, irq_req_t *req)
553{
554 struct pcmcia_socket *s;
555 if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ))
556 return CS_BAD_HANDLE;
557 handle->state &= ~CLIENT_IRQ_REQ;
558 s = SOCKET(handle);
559
560 if (!(handle->state & CLIENT_STALE)) {
561 config_t *c = CONFIG(handle);
562 if (c->state & CONFIG_LOCKED)
563 return CS_CONFIGURATION_LOCKED;
564 if (c->irq.Attributes != req->Attributes)
565 return CS_BAD_ATTRIBUTE;
566 if (s->irq.AssignedIRQ != req->AssignedIRQ)
567 return CS_BAD_IRQ;
568 if (--s->irq.Config == 0) {
569 c->state &= ~CONFIG_IRQ_REQ;
570 s->irq.AssignedIRQ = 0;
571 }
572 }
573
574 if (req->Attributes & IRQ_HANDLE_PRESENT) {
575 free_irq(req->AssignedIRQ, req->Instance);
576 }
577
578#ifdef CONFIG_PCMCIA_PROBE
579 pcmcia_used_irq[req->AssignedIRQ]--;
580#endif
581
582 return CS_SUCCESS;
583} /* pcmcia_release_irq */
584EXPORT_SYMBOL(pcmcia_release_irq);
585
586
587int pcmcia_release_window(window_handle_t win)
588{
589 struct pcmcia_socket *s;
590
591 if ((win == NULL) || (win->magic != WINDOW_MAGIC))
592 return CS_BAD_HANDLE;
593 s = win->sock;
594 if (!(win->handle->state & CLIENT_WIN_REQ(win->index)))
595 return CS_BAD_HANDLE;
596
597 /* Shut down memory window */
598 win->ctl.flags &= ~MAP_ACTIVE;
599 s->ops->set_mem_map(s, &win->ctl);
600 s->state &= ~SOCKET_WIN_REQ(win->index);
601
602 /* Release system memory */
603 if (win->ctl.res) {
604 release_resource(win->ctl.res);
605 kfree(win->ctl.res);
606 win->ctl.res = NULL;
607 }
608 win->handle->state &= ~CLIENT_WIN_REQ(win->index);
609
610 win->magic = 0;
611
612 return CS_SUCCESS;
613} /* pcmcia_release_window */
614EXPORT_SYMBOL(pcmcia_release_window);
615
616
617int pcmcia_request_configuration(client_handle_t handle,
618 config_req_t *req)
619{
620 int i;
621 u_int base;
622 struct pcmcia_socket *s;
623 config_t *c;
624 pccard_io_map iomap;
625
626 if (CHECK_HANDLE(handle))
627 return CS_BAD_HANDLE;
628 s = SOCKET(handle);
629 if (!(s->state & SOCKET_PRESENT))
630 return CS_NO_CARD;
631
632#ifdef CONFIG_CARDBUS
633 if (handle->state & CLIENT_CARDBUS)
634 return CS_UNSUPPORTED_MODE;
635#endif
636
637 if (req->IntType & INT_CARDBUS)
638 return CS_UNSUPPORTED_MODE;
639 c = CONFIG(handle);
640 if (c->state & CONFIG_LOCKED)
641 return CS_CONFIGURATION_LOCKED;
642
643 /* Do power control. We don't allow changes in Vcc. */
644 if (s->socket.Vcc != req->Vcc)
645 return CS_BAD_VCC;
646 if (req->Vpp1 != req->Vpp2)
647 return CS_BAD_VPP;
648 s->socket.Vpp = req->Vpp1;
649 if (s->ops->set_socket(s, &s->socket))
650 return CS_BAD_VPP;
651
652 c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
653
654 /* Pick memory or I/O card, DMA mode, interrupt */
655 c->IntType = req->IntType;
656 c->Attributes = req->Attributes;
657 if (req->IntType & INT_MEMORY_AND_IO)
658 s->socket.flags |= SS_IOCARD;
659 if (req->IntType & INT_ZOOMED_VIDEO)
660 s->socket.flags |= SS_ZVCARD | SS_IOCARD;
661 if (req->Attributes & CONF_ENABLE_DMA)
662 s->socket.flags |= SS_DMA_MODE;
663 if (req->Attributes & CONF_ENABLE_SPKR)
664 s->socket.flags |= SS_SPKR_ENA;
665 if (req->Attributes & CONF_ENABLE_IRQ)
666 s->socket.io_irq = s->irq.AssignedIRQ;
667 else
668 s->socket.io_irq = 0;
669 s->ops->set_socket(s, &s->socket);
670 s->lock_count++;
671
672 /* Set up CIS configuration registers */
673 base = c->ConfigBase = req->ConfigBase;
674 c->Present = c->CardValues = req->Present;
675 if (req->Present & PRESENT_COPY) {
676 c->Copy = req->Copy;
677 pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
678 }
679 if (req->Present & PRESENT_OPTION) {
680 if (s->functions == 1) {
681 c->Option = req->ConfigIndex & COR_CONFIG_MASK;
682 } else {
683 c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK;
684 c->Option |= COR_FUNC_ENA|COR_IREQ_ENA;
685 if (req->Present & PRESENT_IOBASE_0)
686 c->Option |= COR_ADDR_DECODE;
687 }
688 if (c->state & CONFIG_IRQ_REQ)
689 if (!(c->irq.Attributes & IRQ_FORCED_PULSE))
690 c->Option |= COR_LEVEL_REQ;
691 pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
692 mdelay(40);
693 }
694 if (req->Present & PRESENT_STATUS) {
695 c->Status = req->Status;
696 pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
697 }
698 if (req->Present & PRESENT_PIN_REPLACE) {
699 c->Pin = req->Pin;
700 pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin);
701 }
702 if (req->Present & PRESENT_EXT_STATUS) {
703 c->ExtStatus = req->ExtStatus;
704 pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus);
705 }
706 if (req->Present & PRESENT_IOBASE_0) {
707 u_char b = c->io.BasePort1 & 0xff;
708 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
709 b = (c->io.BasePort1 >> 8) & 0xff;
710 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
711 }
712 if (req->Present & PRESENT_IOSIZE) {
713 u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1;
714 pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
715 }
716
717 /* Configure I/O windows */
718 if (c->state & CONFIG_IO_REQ) {
719 iomap.speed = io_speed;
720 for (i = 0; i < MAX_IO_WIN; i++)
721 if (s->io[i].NumPorts != 0) {
722 iomap.map = i;
723 iomap.flags = MAP_ACTIVE;
724 switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) {
725 case IO_DATA_PATH_WIDTH_16:
726 iomap.flags |= MAP_16BIT; break;
727 case IO_DATA_PATH_WIDTH_AUTO:
728 iomap.flags |= MAP_AUTOSZ; break;
729 default:
730 break;
731 }
732 iomap.start = s->io[i].BasePort;
733 iomap.stop = iomap.start + s->io[i].NumPorts - 1;
734 s->ops->set_io_map(s, &iomap);
735 s->io[i].Config++;
736 }
737 }
738
739 c->state |= CONFIG_LOCKED;
740 handle->state |= CLIENT_CONFIG_LOCKED;
741 return CS_SUCCESS;
742} /* pcmcia_request_configuration */
743EXPORT_SYMBOL(pcmcia_request_configuration);
744
745
746/** pcmcia_request_io
747 *
748 * Request_io() reserves ranges of port addresses for a socket.
749 * I have not implemented range sharing or alias addressing.
750 */
751int pcmcia_request_io(client_handle_t handle, io_req_t *req)
752{
753 struct pcmcia_socket *s;
754 config_t *c;
755
756 if (CHECK_HANDLE(handle))
757 return CS_BAD_HANDLE;
758 s = SOCKET(handle);
759 if (!(s->state & SOCKET_PRESENT))
760 return CS_NO_CARD;
761
762 if (handle->state & CLIENT_CARDBUS) {
763#ifdef CONFIG_CARDBUS
764 handle->state |= CLIENT_IO_REQ;
765 return CS_SUCCESS;
766#else
767 return CS_UNSUPPORTED_FUNCTION;
768#endif
769 }
770
771 if (!req)
772 return CS_UNSUPPORTED_MODE;
773 c = CONFIG(handle);
774 if (c->state & CONFIG_LOCKED)
775 return CS_CONFIGURATION_LOCKED;
776 if (c->state & CONFIG_IO_REQ)
777 return CS_IN_USE;
778 if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))
779 return CS_BAD_ATTRIBUTE;
780 if ((req->NumPorts2 > 0) &&
781 (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)))
782 return CS_BAD_ATTRIBUTE;
783
784 if (alloc_io_space(s, req->Attributes1, &req->BasePort1,
785 req->NumPorts1, req->IOAddrLines))
786 return CS_IN_USE;
787
788 if (req->NumPorts2) {
789 if (alloc_io_space(s, req->Attributes2, &req->BasePort2,
790 req->NumPorts2, req->IOAddrLines)) {
791 release_io_space(s, req->BasePort1, req->NumPorts1);
792 return CS_IN_USE;
793 }
794 }
795
796 c->io = *req;
797 c->state |= CONFIG_IO_REQ;
798 handle->state |= CLIENT_IO_REQ;
799 return CS_SUCCESS;
800} /* pcmcia_request_io */
801EXPORT_SYMBOL(pcmcia_request_io);
802
803
804/** pcmcia_request_irq
805 *
806 * Request_irq() reserves an irq for this client.
807 *
808 * Also, since Linux only reserves irq's when they are actually
809 * hooked, we don't guarantee that an irq will still be available
810 * when the configuration is locked. Now that I think about it,
811 * there might be a way to fix this using a dummy handler.
812 */
813
814#ifdef CONFIG_PCMCIA_PROBE
815static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs)
816{
817 return IRQ_NONE;
818}
819#endif
820
821int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
822{
823 struct pcmcia_socket *s;
824 config_t *c;
825 int ret = CS_IN_USE, irq = 0;
826 struct pcmcia_device *p_dev = handle_to_pdev(handle);
827
828 if (CHECK_HANDLE(handle))
829 return CS_BAD_HANDLE;
830 s = SOCKET(handle);
831 if (!(s->state & SOCKET_PRESENT))
832 return CS_NO_CARD;
833 c = CONFIG(handle);
834 if (c->state & CONFIG_LOCKED)
835 return CS_CONFIGURATION_LOCKED;
836 if (c->state & CONFIG_IRQ_REQ)
837 return CS_IN_USE;
838
839#ifdef CONFIG_PCMCIA_PROBE
840 if (s->irq.AssignedIRQ != 0) {
841 /* If the interrupt is already assigned, it must be the same */
842 irq = s->irq.AssignedIRQ;
843 } else {
844 int try;
845 u32 mask = s->irq_mask;
846 void *data = NULL;
847
848 for (try = 0; try < 64; try++) {
849 irq = try % 32;
850
851 /* marked as available by driver, and not blocked by userspace? */
852 if (!((mask >> irq) & 1))
853 continue;
854
855 /* avoid an IRQ which is already used by a PCMCIA card */
856 if ((try < 32) && pcmcia_used_irq[irq])
857 continue;
858
859 /* register the correct driver, if possible, of check whether
860 * registering a dummy handle works, i.e. if the IRQ isn't
861 * marked as used by the kernel resource management core */
862 ret = request_irq(irq,
863 (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action,
864 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
865 (s->functions > 1) ||
866 (irq == s->pci_irq)) ? SA_SHIRQ : 0,
867 p_dev->dev.bus_id,
868 (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
869 if (!ret) {
870 if (!(req->Attributes & IRQ_HANDLE_PRESENT))
871 free_irq(irq, data);
872 break;
873 }
874 }
875 }
876#endif
877 if (ret) {
878 if (!s->pci_irq)
879 return ret;
880 irq = s->pci_irq;
881 }
882
883 if (ret && req->Attributes & IRQ_HANDLE_PRESENT) {
884 if (request_irq(irq, req->Handler,
885 ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
886 (s->functions > 1) ||
887 (irq == s->pci_irq)) ? SA_SHIRQ : 0,
888 p_dev->dev.bus_id, req->Instance))
889 return CS_IN_USE;
890 }
891
892 c->irq.Attributes = req->Attributes;
893 s->irq.AssignedIRQ = req->AssignedIRQ = irq;
894 s->irq.Config++;
895
896 c->state |= CONFIG_IRQ_REQ;
897 handle->state |= CLIENT_IRQ_REQ;
898
899#ifdef CONFIG_PCMCIA_PROBE
900 pcmcia_used_irq[irq]++;
901#endif
902
903 return CS_SUCCESS;
904} /* pcmcia_request_irq */
905EXPORT_SYMBOL(pcmcia_request_irq);
906
907
908/** pcmcia_request_window
909 *
910 * Request_window() establishes a mapping between card memory space
911 * and system memory space.
912 */
913int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh)
914{
915 struct pcmcia_socket *s;
916 window_t *win;
917 u_long align;
918 int w;
919
920 if (CHECK_HANDLE(*handle))
921 return CS_BAD_HANDLE;
922 s = (*handle)->Socket;
923 if (!(s->state & SOCKET_PRESENT))
924 return CS_NO_CARD;
925 if (req->Attributes & (WIN_PAGED | WIN_SHARED))
926 return CS_BAD_ATTRIBUTE;
927
928 /* Window size defaults to smallest available */
929 if (req->Size == 0)
930 req->Size = s->map_size;
931 align = (((s->features & SS_CAP_MEM_ALIGN) ||
932 (req->Attributes & WIN_STRICT_ALIGN)) ?
933 req->Size : s->map_size);
934 if (req->Size & (s->map_size-1))
935 return CS_BAD_SIZE;
936 if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
937 (req->Base & (align-1)))
938 return CS_BAD_BASE;
939 if (req->Base)
940 align = 0;
941
942 /* Allocate system memory window */
943 for (w = 0; w < MAX_WIN; w++)
944 if (!(s->state & SOCKET_WIN_REQ(w))) break;
945 if (w == MAX_WIN)
946 return CS_OUT_OF_RESOURCE;
947
948 win = &s->win[w];
949 win->magic = WINDOW_MAGIC;
950 win->index = w;
951 win->handle = *handle;
952 win->sock = s;
953
954 if (!(s->features & SS_CAP_STATIC_MAP)) {
955 win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align,
956 (req->Attributes & WIN_MAP_BELOW_1MB), s);
957 if (!win->ctl.res)
958 return CS_IN_USE;
959 }
960 (*handle)->state |= CLIENT_WIN_REQ(w);
961
962 /* Configure the socket controller */
963 win->ctl.map = w+1;
964 win->ctl.flags = 0;
965 win->ctl.speed = req->AccessSpeed;
966 if (req->Attributes & WIN_MEMORY_TYPE)
967 win->ctl.flags |= MAP_ATTRIB;
968 if (req->Attributes & WIN_ENABLE)
969 win->ctl.flags |= MAP_ACTIVE;
970 if (req->Attributes & WIN_DATA_WIDTH_16)
971 win->ctl.flags |= MAP_16BIT;
972 if (req->Attributes & WIN_USE_WAIT)
973 win->ctl.flags |= MAP_USE_WAIT;
974 win->ctl.card_start = 0;
975 if (s->ops->set_mem_map(s, &win->ctl) != 0)
976 return CS_BAD_ARGS;
977 s->state |= SOCKET_WIN_REQ(w);
978
979 /* Return window handle */
980 if (s->features & SS_CAP_STATIC_MAP) {
981 req->Base = win->ctl.static_start;
982 } else {
983 req->Base = win->ctl.res->start;
984 }
985 *wh = win;
986
987 return CS_SUCCESS;
988} /* pcmcia_request_window */
989EXPORT_SYMBOL(pcmcia_request_window);
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index fca10a1a56d0..0668384ebc8b 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -112,6 +112,7 @@ int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
112 return s->resource_ops->adjust_io_region(res, r_start, r_end, s); 112 return s->resource_ops->adjust_io_region(res, r_start, r_end, s);
113 return -ENOMEM; 113 return -ENOMEM;
114} 114}
115EXPORT_SYMBOL(pcmcia_adjust_io_region);
115 116
116struct resource *pcmcia_find_io_region(unsigned long base, int num, 117struct resource *pcmcia_find_io_region(unsigned long base, int num,
117 unsigned long align, struct pcmcia_socket *s) 118 unsigned long align, struct pcmcia_socket *s)
@@ -120,6 +121,7 @@ struct resource *pcmcia_find_io_region(unsigned long base, int num,
120 return s->resource_ops->find_io(base, num, align, s); 121 return s->resource_ops->find_io(base, num, align, s);
121 return NULL; 122 return NULL;
122} 123}
124EXPORT_SYMBOL(pcmcia_find_io_region);
123 125
124struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align, 126struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
125 int low, struct pcmcia_socket *s) 127 int low, struct pcmcia_socket *s)
@@ -128,6 +130,7 @@ struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
128 return s->resource_ops->find_mem(base, num, align, low, s); 130 return s->resource_ops->find_mem(base, num, align, low, s);
129 return NULL; 131 return NULL;
130} 132}
133EXPORT_SYMBOL(pcmcia_find_mem_region);
131 134
132void release_resource_db(struct pcmcia_socket *s) 135void release_resource_db(struct pcmcia_socket *s)
133{ 136{