~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/pcmcia/cardbus.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*======================================================================
  2   
  3     Cardbus device configuration
  4     
  5     cardbus.c 1.63 1999/11/08 20:47:02
  6 
  7     The contents of this file are subject to the Mozilla Public
  8     License Version 1.1 (the "License"); you may not use this file
  9     except in compliance with the License. You may obtain a copy of
 10     the License at http://www.mozilla.org/MPL/
 11 
 12     Software distributed under the License is distributed on an "AS
 13     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 14     implied. See the License for the specific language governing
 15     rights and limitations under the License.
 16 
 17     The initial developer of the original code is David A. Hinds
 18     <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
 19     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 20 
 21     Alternatively, the contents of this file may be used under the
 22     terms of the GNU Public License version 2 (the "GPL"), in which
 23     case the provisions of the GPL are applicable instead of the
 24     above.  If you wish to allow the use of your version of this file
 25     only under the terms of the GPL and not to allow others to use
 26     your version of this file under the MPL, indicate your decision
 27     by deleting the provisions above and replace them with the notice
 28     and other provisions required by the GPL.  If you do not delete
 29     the provisions above, a recipient may use your version of this
 30     file under either the MPL or the GPL.
 31     
 32     These routines handle allocating resources for Cardbus cards, as
 33     well as setting up and shutting down Cardbus sockets.  They are
 34     called from cs.c in response to Request/ReleaseConfiguration and
 35     Request/ReleaseIO calls.
 36 
 37 ======================================================================*/
 38 
 39 /*
 40  * This file is going away.  Cardbus handling has been re-written to be
 41  * more of a PCI bridge thing, and the PCI code basically does all the
 42  * resource handling. This has wrappers to make the rest of the PCMCIA
 43  * subsystem not notice that it's not here any more.
 44  *
 45  *              Linus, Jan 2000
 46  */
 47 
 48 
 49 #define __NO_VERSION__
 50 
 51 #include <linux/module.h>
 52 #include <linux/kernel.h>
 53 #include <linux/string.h>
 54 #include <linux/malloc.h>
 55 #include <linux/mm.h>
 56 #include <linux/pci.h>
 57 #include <linux/ioport.h>
 58 #include <asm/irq.h>
 59 #include <asm/io.h>
 60 
 61 #define IN_CARD_SERVICES
 62 #include <pcmcia/version.h>
 63 #include <pcmcia/cs_types.h>
 64 #include <pcmcia/ss.h>
 65 #include <pcmcia/cs.h>
 66 #include <pcmcia/bulkmem.h>
 67 #include <pcmcia/cistpl.h>
 68 #include "cs_internal.h"
 69 #include "rsrc_mgr.h"
 70 
 71 #ifdef PCMCIA_DEBUG
 72 static int pc_debug = PCMCIA_DEBUG;
 73 #endif
 74 
 75 /*====================================================================*/
 76 
 77 #define FIND_FIRST_BIT(n)       ((n) - ((n) & ((n)-1)))
 78 
 79 #define pci_readb               pci_read_config_byte
 80 #define pci_writeb              pci_write_config_byte
 81 #define pci_readw               pci_read_config_word
 82 #define pci_writew              pci_write_config_word
 83 #define pci_readl               pci_read_config_dword
 84 #define pci_writel              pci_write_config_dword
 85 
 86 /* Offsets in the Expansion ROM Image Header */
 87 #define ROM_SIGNATURE           0x0000  /* 2 bytes */
 88 #define ROM_DATA_PTR            0x0018  /* 2 bytes */
 89 
 90 /* Offsets in the CardBus PC Card Data Structure */
 91 #define PCDATA_SIGNATURE        0x0000  /* 4 bytes */
 92 #define PCDATA_VPD_PTR          0x0008  /* 2 bytes */
 93 #define PCDATA_LENGTH           0x000a  /* 2 bytes */
 94 #define PCDATA_REVISION         0x000c
 95 #define PCDATA_IMAGE_SZ         0x0010  /* 2 bytes */
 96 #define PCDATA_ROM_LEVEL        0x0012  /* 2 bytes */
 97 #define PCDATA_CODE_TYPE        0x0014
 98 #define PCDATA_INDICATOR        0x0015
 99 
100 typedef struct cb_config_t {
101         struct pci_dev dev;
102 } cb_config_t;
103 
104 /*=====================================================================
105 
106     Expansion ROM's have a special layout, and pointers specify an
107     image number and an offset within that image.  xlate_rom_addr()
108     converts an image/offset address to an absolute offset from the
109     ROM's base address.
110     
111 =====================================================================*/
112 
113 static u_int xlate_rom_addr(u_char * b, u_int addr)
114 {
115         u_int img = 0, ofs = 0, sz;
116         u_short data;
117         while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
118                 if (img == (addr >> 28))
119                         return (addr & 0x0fffffff) + ofs;
120                 data = readb(b + ROM_DATA_PTR) + (readb(b + ROM_DATA_PTR + 1) << 8);
121                 sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
122                             (readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
123                 if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80))
124                         break;
125                 b += sz;
126                 ofs += sz;
127                 img++;
128         }
129         return 0;
130 }
131 
132 /*=====================================================================
133 
134     These are similar to setup_cis_mem and release_cis_mem for 16-bit
135     cards.  The "result" that is used externally is the cb_cis_virt
136     pointer in the socket_info_t structure.
137     
138 =====================================================================*/
139 
140 void cb_release_cis_mem(socket_info_t * s)
141 {
142         if (s->cb_cis_virt) {
143                 DEBUG(1, "cs: cb_release_cis_mem()\n");
144                 iounmap(s->cb_cis_virt);
145                 s->cb_cis_virt = NULL;
146                 s->cb_cis_res = 0;
147         }
148 }
149 
150 static int cb_setup_cis_mem(socket_info_t * s, struct pci_dev *dev, struct resource *res)
151 {
152         unsigned int start, size;
153 
154         if (res == s->cb_cis_res)
155                 return 0;
156 
157         if (s->cb_cis_res)
158                 cb_release_cis_mem(s);
159 
160         start = res->start;
161         size = res->end - start + 1;
162         s->cb_cis_virt = ioremap(start, size);
163 
164         if (!s->cb_cis_virt)
165                 return -1;
166 
167         s->cb_cis_res = res;
168 
169         return 0;
170 }
171 
172 /*=====================================================================
173 
174     This is used by the CIS processing code to read CIS information
175     from a CardBus device.
176     
177 =====================================================================*/
178 
179 void read_cb_mem(socket_info_t * s, u_char fn, int space,
180                  u_int addr, u_int len, void *ptr)
181 {
182         struct pci_dev *dev;
183         struct resource *res;
184 
185         DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len);
186 
187         if (!s->cb_config)
188                 goto fail;
189 
190         dev = &s->cb_config[fn].dev;
191 
192         /* Config space? */
193         if (space == 0) {
194                 if (addr + len > 0x100)
195                         goto fail;
196                 for (; len; addr++, ptr++, len--)
197                         pci_readb(dev, addr, (u_char *) ptr);
198                 return;
199         }
200 
201         res = dev->resource + space - 1;
202         if (!res->flags)
203                 goto fail;
204 
205         if (cb_setup_cis_mem(s, dev, res) != 0)
206                 goto fail;
207 
208         if (space == 7) {
209                 addr = xlate_rom_addr(s->cb_cis_virt, addr);
210                 if (addr == 0)
211                         goto fail;
212         }
213 
214         if (addr + len > res->end - res->start)
215                 goto fail;
216 
217         memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
218         return;
219 
220 fail:
221         memset(ptr, 0xff, len);
222         return;
223 }
224 
225 /*=====================================================================
226 
227     cb_alloc() and cb_free() allocate and free the kernel data
228     structures for a Cardbus device, and handle the lowest level PCI
229     device setup issues.
230     
231 =====================================================================*/
232 
233 int cb_alloc(socket_info_t * s)
234 {
235         struct pci_bus *bus;
236         struct pci_dev tmp;
237         u_short vend, v, dev;
238         u_char i, hdr, fn;
239         cb_config_t *c;
240         int irq;
241 
242         bus = s->cap.cb_dev->subordinate;
243         memset(&tmp, 0, sizeof(tmp));
244         tmp.bus = bus;
245         tmp.sysdata = bus->sysdata;
246         tmp.devfn = 0;
247 
248         pci_readw(&tmp, PCI_VENDOR_ID, &vend);
249         pci_readw(&tmp, PCI_DEVICE_ID, &dev);
250         printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, "
251                "device 0x%04x\n", bus->number, vend, dev);
252 
253         pci_readb(&tmp, PCI_HEADER_TYPE, &hdr);
254         fn = 1;
255         if (hdr & 0x80) {
256                 do {
257                         tmp.devfn = fn;
258                         if (pci_readw(&tmp, PCI_VENDOR_ID, &v) || !v || v == 0xffff)
259                                 break;
260                         fn++;
261                 } while (fn < 8);
262         }
263         s->functions = fn;
264 
265         c = kmalloc(fn * sizeof(struct cb_config_t), GFP_ATOMIC);
266         if (!c)
267                 return CS_OUT_OF_RESOURCE;
268         memset(c, 0, fn * sizeof(struct cb_config_t));
269 
270         irq = s->cap.pci_irq;
271         for (i = 0; i < fn; i++) {
272                 struct pci_dev *dev = &c[i].dev;
273                 u8 irq_pin;
274                 int r;
275 
276                 dev->bus = bus;
277                 dev->sysdata = bus->sysdata;
278                 dev->devfn = i;
279                 dev->vendor = vend;
280                 pci_readw(dev, PCI_DEVICE_ID, &dev->device);
281                 dev->hdr_type = hdr & 0x7f;
282 
283                 pci_setup_device(dev);
284 
285                 /* FIXME: Do we need to enable the expansion ROM? */
286                 for (r = 0; r < 7; r++) {
287                         struct resource *res = dev->resource + r;
288                         if (res->flags)
289                                 pci_assign_resource(dev, r);
290                 }
291                 pci_enable_device(dev); /* XXX check return */
292 
293                 /* Does this function have an interrupt at all? */
294                 pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin);
295                 if (irq_pin) {
296                         dev->irq = irq;
297                         pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
298                 }
299 
300                 pci_insert_device(dev, bus);
301         }
302 
303         s->cb_config = c;
304         s->irq.AssignedIRQ = irq;
305         return CS_SUCCESS;
306 }
307 
308 void cb_free(socket_info_t * s)
309 {
310         cb_config_t *c = s->cb_config;
311 
312         if (c) {
313                 int i;
314 
315                 s->cb_config = NULL;
316                 for (i = 0 ; i < s->functions ; i++)
317                         pci_remove_device(&c[i].dev);
318 
319                 kfree(c);
320                 printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
321         }
322 }
323 
324 /*=====================================================================
325 
326     cb_config() has the job of allocating all system resources that
327     a Cardbus card requires.  Rather than using the CIS (which seems
328     to not always be present), it treats the card as an ordinary PCI
329     device, and probes the base address registers to determine each
330     function's IO and memory space needs.
331 
332     It is called from the RequestIO card service.
333     
334 ======================================================================*/
335 
336 int cb_config(socket_info_t * s)
337 {
338         return CS_SUCCESS;
339 }
340 
341 /*======================================================================
342 
343     cb_release() releases all the system resources (IO and memory
344     space, and interrupt) committed for a Cardbus card by a prior call
345     to cb_config().
346 
347     It is called from the ReleaseIO() service.
348     
349 ======================================================================*/
350 
351 void cb_release(socket_info_t * s)
352 {
353         DEBUG(0, "cs: cb_release(bus %d)\n", s->cap.cb_dev->subordinate->number);
354 }
355 
356 /*=====================================================================
357 
358     cb_enable() has the job of configuring a socket for a Cardbus
359     card, and initializing the card's PCI configuration registers.
360 
361     It first sets up the Cardbus bridge windows, for IO and memory
362     accesses.  Then, it initializes each card function's base address
363     registers, interrupt line register, and command register.
364 
365     It is called as part of the RequestConfiguration card service.
366     It should be called after a previous call to cb_config() (via the
367     RequestIO service).
368     
369 ======================================================================*/
370 
371 void cb_enable(socket_info_t * s)
372 {
373         struct pci_dev *dev;
374         u_char i;
375 
376         DEBUG(0, "cs: cb_enable(bus %d)\n", s->cap.cb_dev->subordinate->number);
377 
378         /* Configure bridge */
379         cb_release_cis_mem(s);
380 
381         /* Set up PCI interrupt and command registers */
382         for (i = 0; i < s->functions; i++) {
383                 dev = &s->cb_config[i].dev;
384                 pci_writeb(dev, PCI_COMMAND, PCI_COMMAND_MASTER |
385                            PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
386                 pci_writeb(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
387         }
388 
389         if (s->irq.AssignedIRQ) {
390                 for (i = 0; i < s->functions; i++) {
391                         dev = &s->cb_config[i].dev;
392                         pci_writeb(dev, PCI_INTERRUPT_LINE, s->irq.AssignedIRQ);
393                 }
394                 s->socket.io_irq = s->irq.AssignedIRQ;
395                 s->ss_entry->set_socket(s->sock, &s->socket);
396         }
397 }
398 
399 /*======================================================================
400 
401     cb_disable() unconfigures a Cardbus card previously set up by
402     cb_enable().
403 
404     It is called from the ReleaseConfiguration service.
405     
406 ======================================================================*/
407 
408 void cb_disable(socket_info_t * s)
409 {
410         DEBUG(0, "cs: cb_disable(bus %d)\n", s->cap.cb_dev->subordinate->number);
411 
412         /* Turn off bridge windows */
413         cb_release_cis_mem(s);
414 }
415 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.