patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / net / wireless / prism54 / isl_38xx.c
1 /*
2  *  
3  *  Copyright (C) 2002 Intersil Americas Inc.
4  *  Copyright (C) 2003-2004 Luis R. Rodriguez <mcgrof@ruslug.rutgers.edu>_
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #define __KERNEL_SYSCALLS__
22
23 #include <linux/version.h>
24 #include <linux/module.h>
25 #include <linux/types.h>
26 #include <linux/delay.h>
27
28 #include "isl_38xx.h"
29 #include <linux/firmware.h>
30
31 #include <asm/uaccess.h>
32 #include <asm/io.h>
33
34 #include <linux/config.h>
35 #if !defined(CONFIG_FW_LOADER) && !defined(CONFIG_FW_LOADER_MODULE)
36 #error No Firmware Loading configured in the kernel !
37 #endif
38
39 #include "islpci_dev.h"
40 #include "islpci_mgt.h"
41
42 /******************************************************************************
43     Device Interface & Control functions
44 ******************************************************************************/
45
46 /**
47  * isl38xx_disable_interrupts - disable all interrupts
48  * @device: pci memory base address
49  *
50  *  Instructs the device to disable all interrupt reporting by asserting 
51  *  the IRQ line. New events may still show up in the interrupt identification
52  *  register located at offset %ISL38XX_INT_IDENT_REG.
53  */
54 void
55 isl38xx_disable_interrupts(void *device)
56 {
57         isl38xx_w32_flush(device, 0x00000000, ISL38XX_INT_EN_REG);
58         udelay(ISL38XX_WRITEIO_DELAY);
59 }
60
61 void
62 isl38xx_handle_sleep_request(isl38xx_control_block *control_block,
63                              int *powerstate, void *device_base)
64 {
65         /* device requests to go into sleep mode
66          * check whether the transmit queues for data and management are empty */
67         if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ))
68                 /* data tx queue not empty */
69                 return;
70
71         if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
72                 /* management tx queue not empty */
73                 return;
74
75         /* check also whether received frames are pending */
76         if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ))
77                 /* data rx queue not empty */
78                 return;
79
80         if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ))
81                 /* management rx queue not empty */
82                 return;
83
84 #if VERBOSE > SHOW_ERROR_MESSAGES
85         DEBUG(SHOW_TRACING, "Device going to sleep mode\n");
86 #endif
87
88         /* all queues are empty, allow the device to go into sleep mode */
89         *powerstate = ISL38XX_PSM_POWERSAVE_STATE;
90
91         /* assert the Sleep interrupt in the Device Interrupt Register */
92         isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP,
93                           ISL38XX_DEV_INT_REG);
94         udelay(ISL38XX_WRITEIO_DELAY);
95 }
96
97 void
98 isl38xx_handle_wakeup(isl38xx_control_block *control_block,
99                       int *powerstate, void *device_base)
100 {
101         /* device is in active state, update the powerstate flag */
102         *powerstate = ISL38XX_PSM_ACTIVE_STATE;
103
104         /* now check whether there are frames pending for the card */
105         if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)
106             && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
107                 return;
108
109 #if VERBOSE > SHOW_ERROR_MESSAGES
110         DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n");
111 #endif
112
113         /* either data or management transmit queue has a frame pending
114          * trigger the device by setting the Update bit in the Device Int reg */
115         isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE,
116                           ISL38XX_DEV_INT_REG);
117         udelay(ISL38XX_WRITEIO_DELAY);
118 }
119
120 void
121 isl38xx_trigger_device(int asleep, void *device_base)
122 {
123         struct timeval current_time;
124         u32 reg, counter = 0;
125
126 #if VERBOSE > SHOW_ERROR_MESSAGES
127         DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n");
128 #endif
129
130         /* check whether the device is in power save mode */
131         if (asleep) {
132                 /* device is in powersave, trigger the device for wakeup */
133 #if VERBOSE > SHOW_ERROR_MESSAGES
134                 do_gettimeofday(&current_time);
135                 DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n",
136                       current_time.tv_sec, current_time.tv_usec);
137 #endif
138
139                 DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
140                       current_time.tv_sec, current_time.tv_usec,
141                       readl(device_base + ISL38XX_CTRL_STAT_REG));
142                 udelay(ISL38XX_WRITEIO_DELAY);
143
144                 if (reg = readl(device_base + ISL38XX_INT_IDENT_REG),
145                     reg == 0xabadface) {
146 #if VERBOSE > SHOW_ERROR_MESSAGES
147                         do_gettimeofday(&current_time);
148                         DEBUG(SHOW_TRACING,
149                               "%08li.%08li Device register abadface\n",
150                               current_time.tv_sec, current_time.tv_usec);
151 #endif
152                         /* read the Device Status Register until Sleepmode bit is set */
153                         while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG),
154                                (reg & ISL38XX_CTRL_STAT_SLEEPMODE) == 0) {
155                                 udelay(ISL38XX_WRITEIO_DELAY);
156                                 counter++;
157                         }
158
159                         DEBUG(SHOW_TRACING,
160                               "%08li.%08li Device register read %08x\n",
161                               current_time.tv_sec, current_time.tv_usec,
162                               readl(device_base + ISL38XX_CTRL_STAT_REG));
163                         udelay(ISL38XX_WRITEIO_DELAY);
164
165 #if VERBOSE > SHOW_ERROR_MESSAGES
166                         do_gettimeofday(&current_time);
167                         DEBUG(SHOW_TRACING,
168                               "%08li.%08li Device asleep counter %i\n",
169                               current_time.tv_sec, current_time.tv_usec,
170                               counter);
171 #endif
172                 }
173                 /* assert the Wakeup interrupt in the Device Interrupt Register */
174                 isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_WAKEUP,
175                                   ISL38XX_DEV_INT_REG);
176                 udelay(ISL38XX_WRITEIO_DELAY);
177
178                 /* perform another read on the Device Status Register */
179                 reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
180                 udelay(ISL38XX_WRITEIO_DELAY);
181
182 #if VERBOSE > SHOW_ERROR_MESSAGES
183                 do_gettimeofday(&current_time);
184                 DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
185                       current_time.tv_sec, current_time.tv_usec, reg);
186 #endif
187         } else {
188                 /* device is (still) awake  */
189 #if VERBOSE > SHOW_ERROR_MESSAGES
190                 DEBUG(SHOW_TRACING, "Device is in active state\n");
191 #endif
192                 /* trigger the device by setting the Update bit in the Device Int reg */
193
194                 isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE,
195                                   ISL38XX_DEV_INT_REG);
196                 udelay(ISL38XX_WRITEIO_DELAY);
197         }
198 }
199
200 void
201 isl38xx_interface_reset(void *device_base, dma_addr_t host_address)
202 {
203         u32 reg;
204
205 #if VERBOSE > SHOW_ERROR_MESSAGES
206         DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset \n");
207 #endif
208
209         /* load the address of the control block in the device */
210         isl38xx_w32_flush(device_base, host_address, ISL38XX_CTRL_BLK_BASE_REG);
211         udelay(ISL38XX_WRITEIO_DELAY);
212
213         /* set the reset bit in the Device Interrupt Register */
214         isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET,
215                           ISL38XX_DEV_INT_REG);
216         udelay(ISL38XX_WRITEIO_DELAY);
217
218         /* enable the interrupt for detecting initialization */
219
220         /* Note: Do not enable other interrupts here. We want the
221          * device to have come up first 100% before allowing any other 
222          * interrupts. */
223         reg = ISL38XX_INT_IDENT_INIT;
224
225         isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG);
226         udelay(ISL38XX_WRITEIO_DELAY);  /* allow complete full reset */
227 }
228
229 void
230 isl38xx_enable_common_interrupts(void *device_base) {
231         u32 reg;
232         reg = ( ISL38XX_INT_IDENT_UPDATE | 
233                         ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP);
234         isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG);
235         udelay(ISL38XX_WRITEIO_DELAY);
236 }
237
238 int
239 isl38xx_upload_firmware(char *fw_id, _REQ_FW_DEV_T dev, void *device_base,
240                         dma_addr_t host_address)
241 {
242         u32 reg, rc;
243
244 #if VERBOSE > SHOW_ERROR_MESSAGES
245         DEBUG(SHOW_ERROR_MESSAGES, "isl38xx_upload_firmware(0x%lx, 0x%lx)\n",
246               (long) device_base, (long) host_address);
247 #endif
248
249         /* clear the RAMBoot and the Reset bit */
250         reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
251         reg &= ~ISL38XX_CTRL_STAT_RESET;
252         reg &= ~ISL38XX_CTRL_STAT_RAMBOOT;
253         writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
254         wmb();
255         udelay(ISL38XX_WRITEIO_DELAY);
256
257         /* set the Reset bit without reading the register ! */
258         reg |= ISL38XX_CTRL_STAT_RESET;
259         writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
260         wmb();
261         udelay(ISL38XX_WRITEIO_DELAY);
262
263         /* clear the Reset bit */
264         reg &= ~ISL38XX_CTRL_STAT_RESET;
265         writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
266         wmb();
267
268         /* wait a while for the device to reboot */
269         mdelay(50);
270
271         {
272                 const struct firmware *fw_entry = 0;
273                 long fw_len;
274                 const u32 *fw_ptr;
275
276                 rc = request_firmware(&fw_entry, fw_id, dev);
277                 if (rc) {
278                         printk(KERN_ERR
279                                "%s: request_firmware() failed for '%s'\n",
280                                "prism54", fw_id);
281                         return rc;
282                 }
283                 /* prepare the Direct Memory Base register */
284                 reg = ISL38XX_DEV_FIRMWARE_ADDRES;
285
286                 fw_ptr = (u32 *) fw_entry->data;
287                 fw_len = fw_entry->size;
288
289                 if (fw_len % 4) {
290                         printk(KERN_ERR
291                                "%s: firmware '%s' size is not multiple of 32bit, aborting!\n",
292                                "prism54", fw_id);
293                         release_firmware(fw_entry);
294                         return EILSEQ; /* Illegal byte sequence  */;
295                 }
296
297                 while (fw_len > 0) {
298                         long _fw_len =
299                             (fw_len >
300                              ISL38XX_MEMORY_WINDOW_SIZE) ?
301                             ISL38XX_MEMORY_WINDOW_SIZE : fw_len;
302                         u32 *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN;
303
304                         /* set the cards base address for writting the data */
305                         isl38xx_w32_flush(device_base, reg,
306                                           ISL38XX_DIR_MEM_BASE_REG);
307                         wmb();  /* be paranoid */
308
309                         /* increment the write address for next iteration */
310                         reg += _fw_len;
311                         fw_len -= _fw_len;
312
313                         /* write the data to the Direct Memory Window 32bit-wise */
314                         /* memcpy_toio() doesn't guarantee 32bit writes :-| */
315                         while (_fw_len > 0) {
316                                 /* use non-swapping writel() */
317                                 __raw_writel(*fw_ptr, dev_fw_ptr);
318                                 fw_ptr++, dev_fw_ptr++;
319                                 _fw_len -= 4;
320                         }
321
322                         /* flush PCI posting */
323                         (void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH);
324                         wmb();  /* be paranoid again */
325
326                         BUG_ON(_fw_len != 0);
327                 }
328
329                 BUG_ON(fw_len != 0);
330
331                 release_firmware(fw_entry);
332         }
333
334         /* now reset the device
335          * clear the Reset & ClkRun bit, set the RAMBoot bit */
336         reg = readl(device_base + ISL38XX_CTRL_STAT_REG);
337         reg &= ~ISL38XX_CTRL_STAT_CLKRUN;
338         reg &= ~ISL38XX_CTRL_STAT_RESET;
339         reg |= ISL38XX_CTRL_STAT_RAMBOOT;
340         isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG);
341         wmb();
342         udelay(ISL38XX_WRITEIO_DELAY);
343
344         /* set the reset bit latches the host override and RAMBoot bits
345          * into the device for operation when the reset bit is reset */
346         reg |= ISL38XX_CTRL_STAT_RESET;
347         writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
348         /* don't do flush PCI posting here! */
349         wmb();
350         udelay(ISL38XX_WRITEIO_DELAY);
351
352         /* clear the reset bit should start the whole circus */
353         reg &= ~ISL38XX_CTRL_STAT_RESET;
354         writel(reg, device_base + ISL38XX_CTRL_STAT_REG);
355         /* don't do flush PCI posting here! */
356         wmb();
357         udelay(ISL38XX_WRITEIO_DELAY);
358
359         return 0;
360 }
361
362 int
363 isl38xx_in_queue(isl38xx_control_block *cb, int queue)
364 {
365         const s32 delta = (le32_to_cpu(cb->driver_curr_frag[queue]) -
366                            le32_to_cpu(cb->device_curr_frag[queue]));
367
368         /* determine the amount of fragments in the queue depending on the type
369          * of the queue, either transmit or receive */
370
371         BUG_ON(delta < 0);      /* driver ptr must be ahead of device ptr */
372
373         switch (queue) {
374                 /* send queues */
375         case ISL38XX_CB_TX_MGMTQ:
376                 BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE);
377         case ISL38XX_CB_TX_DATA_LQ:
378         case ISL38XX_CB_TX_DATA_HQ:
379                 BUG_ON(delta > ISL38XX_CB_TX_QSIZE);
380                 return delta;
381                 break;
382
383                 /* receive queues */
384         case ISL38XX_CB_RX_MGMTQ:
385                 BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE);
386                 return ISL38XX_CB_MGMT_QSIZE - delta;
387                 break;
388
389         case ISL38XX_CB_RX_DATA_LQ:
390         case ISL38XX_CB_RX_DATA_HQ:
391                 BUG_ON(delta > ISL38XX_CB_RX_QSIZE);
392                 return ISL38XX_CB_RX_QSIZE - delta;
393                 break;
394         }
395         BUG();
396         return 0;
397 }