blob: 72a699c127040371f134b45db3eba0ed48c38906 [file] [log] [blame]
Arnd Bergmannd16044cf2010-09-30 10:24:07 +02001#include <linux/fs.h>
2
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07003#include "headers.h"
4/***************************************************************
5* Function - bcm_char_open()
6*
7* Description - This is the "open" entry point for the character
8* driver.
9*
10* Parameters - inode: Pointer to the Inode structure of char device
11* filp : File pointer of the char device
12*
13* Returns - Zero(Success)
14****************************************************************/
Stephen Hemminger9e0a3162010-11-01 10:17:54 -040015
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070016static int bcm_char_open(struct inode *inode, struct file * filp)
17{
Javier Martinez Canillas1e123322011-02-12 04:38:22 +010018 PMINI_ADAPTER Adapter = NULL;
19 PPER_TARANG_DATA pTarang = NULL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070020
21 Adapter = GET_BCM_ADAPTER(gblpnetdev);
Alexander Beregalovf4a0e6b2011-03-09 03:53:34 +030022 pTarang = kzalloc(sizeof(PER_TARANG_DATA), GFP_KERNEL);
Javier Martinez Canillas1e123322011-02-12 04:38:22 +010023 if (!pTarang)
24 return -ENOMEM;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070025
Javier Martinez Canillas1e123322011-02-12 04:38:22 +010026 pTarang->Adapter = Adapter;
27 pTarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070028
29 down(&Adapter->RxAppControlQueuelock);
Javier Martinez Canillas1e123322011-02-12 04:38:22 +010030 pTarang->next = Adapter->pTarangs;
31 Adapter->pTarangs = pTarang;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070032 up(&Adapter->RxAppControlQueuelock);
33
34 /* Store the Adapter structure */
35 filp->private_data = pTarang;
36
Kevin McKinney6c15e002011-08-15 22:07:41 -040037 /* Start Queuing the control response Packets */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070038 atomic_inc(&Adapter->ApplicationRunning);
Arnd Bergmannd16044cf2010-09-30 10:24:07 +020039
40 nonseekable_open(inode, filp);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070041 return 0;
42}
Javier Martinez Canillas1e123322011-02-12 04:38:22 +010043
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070044static int bcm_char_release(struct inode *inode, struct file *filp)
45{
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010046 PPER_TARANG_DATA pTarang, tmp, ptmp;
47 PMINI_ADAPTER Adapter = NULL;
48 struct sk_buff *pkt, *npkt;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070049
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010050 pTarang = (PPER_TARANG_DATA)filp->private_data;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070051
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010052 if (pTarang == NULL) {
53 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
54 "ptarang is null\n");
55 return 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070056 }
57
58 Adapter = pTarang->Adapter;
59
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010060 down(&Adapter->RxAppControlQueuelock);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070061
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010062 tmp = Adapter->pTarangs;
63 for (ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next) {
64 if (tmp == pTarang)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070065 break;
66 }
67
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010068 if (tmp) {
69 if (!ptmp)
70 Adapter->pTarangs = tmp->next;
71 else
72 ptmp->next = tmp->next;
73 } else {
74 up(&Adapter->RxAppControlQueuelock);
75 return 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070076 }
77
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010078 pkt = pTarang->RxAppControlHead;
79 while (pkt) {
80 npkt = pkt->next;
81 kfree_skb(pkt);
82 pkt = npkt;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070083 }
84
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010085 up(&Adapter->RxAppControlQueuelock);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070086
Kevin McKinney6c15e002011-08-15 22:07:41 -040087 /* Stop Queuing the control response Packets */
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010088 atomic_dec(&Adapter->ApplicationRunning);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070089
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010090 kfree(pTarang);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070091
92 /* remove this filp from the asynchronously notified filp's */
Javier Martinez Canillasa7d39762011-02-12 04:38:23 +010093 filp->private_data = NULL;
94 return 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070095}
96
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +010097static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size,
98 loff_t *f_pos)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070099{
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400100 PPER_TARANG_DATA pTarang = filp->private_data;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700101 PMINI_ADAPTER Adapter = pTarang->Adapter;
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100102 struct sk_buff *Packet = NULL;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400103 ssize_t PktLen = 0;
104 int wait_ret_val = 0;
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100105 unsigned long ret = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700106
107 wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue,
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100108 (pTarang->RxAppControlHead ||
109 Adapter->device_removed));
110 if ((wait_ret_val == -ERESTARTSYS)) {
111 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
112 "Exiting as i've been asked to exit!!!\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700113 return wait_ret_val;
114 }
115
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100116 if (Adapter->device_removed) {
117 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
118 "Device Removed... Killing the Apps...\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700119 return -ENODEV;
120 }
121
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100122 if (FALSE == Adapter->fw_download_done)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700123 return -EACCES;
124
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100125 down(&Adapter->RxAppControlQueuelock);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700126
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100127 if (pTarang->RxAppControlHead) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700128 Packet = pTarang->RxAppControlHead;
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100129 DEQUEUEPACKET(pTarang->RxAppControlHead,
130 pTarang->RxAppControlTail);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700131 pTarang->AppCtrlQueueLen--;
132 }
133
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100134 up(&Adapter->RxAppControlQueuelock);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700135
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100136 if (Packet) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700137 PktLen = Packet->len;
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100138 ret = copy_to_user(buf, Packet->data,
139 min_t(size_t, PktLen, size));
140 if (ret) {
Stephen Hemminger082e8892010-11-01 09:35:21 -0400141 dev_kfree_skb(Packet);
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100142 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
143 "Returning from copy to user failure\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700144 return -EFAULT;
145 }
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100146 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400147 "Read %zd Bytes From Adapter packet = %p by process %d!\n",
148 PktLen, Packet, current->pid);
Stephen Hemminger082e8892010-11-01 09:35:21 -0400149 dev_kfree_skb(Packet);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700150 }
151
Javier Martinez Canillas7227ba02011-02-12 04:38:24 +0100152 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<\n");
153 return PktLen;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700154}
155
Arnd Bergmann9f1c75a2010-09-30 10:24:11 +0200156static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700157{
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400158 PPER_TARANG_DATA pTarang = filp->private_data;
159 void __user *argp = (void __user *)arg;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400160 PMINI_ADAPTER Adapter = pTarang->Adapter;
161 INT Status = STATUS_FAILURE;
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400162 int timeout = 0;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400163 IOCTL_BUFFER IoBuffer;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500164 int bytes;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700165
Kevin McKinney6c15e002011-08-15 22:07:41 -0400166 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700167
Kevin McKinney6c15e002011-08-15 22:07:41 -0400168 if (_IOC_TYPE(cmd) != BCM_IOCTL)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700169 return -EFAULT;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400170 if (_IOC_DIR(cmd) & _IOC_READ)
Arnd Bergmann44a17eff2010-09-30 10:24:12 +0200171 Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700172 else if (_IOC_DIR(cmd) & _IOC_WRITE)
Kevin McKinney6c15e002011-08-15 22:07:41 -0400173 Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700174 else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE))
Kevin McKinney6c15e002011-08-15 22:07:41 -0400175 Status = STATUS_SUCCESS;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700176
Kevin McKinney6c15e002011-08-15 22:07:41 -0400177 if (Status)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700178 return -EFAULT;
179
Kevin McKinney6c15e002011-08-15 22:07:41 -0400180 if (Adapter->device_removed)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700181 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700182
Kevin McKinney6c15e002011-08-15 22:07:41 -0400183 if (FALSE == Adapter->fw_download_done) {
184 switch (cmd) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700185 case IOCTL_MAC_ADDR_REQ:
186 case IOCTL_LINK_REQ:
187 case IOCTL_CM_REQUEST:
188 case IOCTL_SS_INFO_REQ:
189 case IOCTL_SEND_CONTROL_MESSAGE:
190 case IOCTL_IDLE_REQ:
Kevin McKinney6c15e002011-08-15 22:07:41 -0400191 case IOCTL_BCM_GPIO_SET_REQUEST:
192 case IOCTL_BCM_GPIO_STATUS_REQUEST:
193 return -EACCES;
194 default:
195 break;
196 }
197 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700198
Kevin McKinney6c15e002011-08-15 22:07:41 -0400199 Status = vendorextnIoctl(Adapter, cmd, arg);
200 if (Status != CONTINUE_COMMON_PATH)
201 return Status;
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400202
Kevin McKinney6c15e002011-08-15 22:07:41 -0400203 switch (cmd) {
204 /* Rdms for Swin Idle... */
205 case IOCTL_BCM_REGISTER_READ_PRIVATE: {
206 RDM_BUFFER sRdmBuffer = {0};
207 PCHAR temp_buff;
208 UINT Bufflen;
Kevin McKinney2505aa62011-09-27 21:28:11 -0400209 u16 temp_value;
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400210
Kevin McKinney6c15e002011-08-15 22:07:41 -0400211 /* Copy Ioctl Buffer structure */
212 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
213 return -EFAULT;
214
215 if (IoBuffer.InputLength > sizeof(sRdmBuffer))
216 return -EINVAL;
217
218 if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
219 return -EFAULT;
220
Kevin McKinney0a2cc492011-09-26 22:03:59 -0400221 if (IoBuffer.OutputLength > USHRT_MAX ||
222 IoBuffer.OutputLength == 0) {
223 return -EINVAL;
224 }
225
Kevin McKinney2505aa62011-09-27 21:28:11 -0400226 Bufflen = IoBuffer.OutputLength;
227 temp_value = 4 - (Bufflen % 4);
228 Bufflen += temp_value % 4;
229
Kevin McKinney6c15e002011-08-15 22:07:41 -0400230 temp_buff = kmalloc(Bufflen, GFP_KERNEL);
231 if (!temp_buff)
232 return -ENOMEM;
233
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500234 bytes = rdmalt(Adapter, (UINT)sRdmBuffer.Register,
Kevin McKinney6c15e002011-08-15 22:07:41 -0400235 (PUINT)temp_buff, Bufflen);
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500236 if (bytes > 0) {
237 Status = STATUS_SUCCESS;
238 if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes))
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700239 Status = -EFAULT;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500240 } else {
241 Status = bytes;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400242 }
243
244 kfree(temp_buff);
245 break;
246 }
247
248 case IOCTL_BCM_REGISTER_WRITE_PRIVATE: {
249 WRM_BUFFER sWrmBuffer = {0};
250 UINT uiTempVar = 0;
251 /* Copy Ioctl Buffer structure */
252
253 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
254 return -EFAULT;
255
256 if (IoBuffer.InputLength > sizeof(sWrmBuffer))
257 return -EINVAL;
258
259 /* Get WrmBuffer structure */
260 if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
261 return -EFAULT;
262
263 uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
264 if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
265 ((uiTempVar == EEPROM_REJECT_REG_1) ||
266 (uiTempVar == EEPROM_REJECT_REG_2) ||
267 (uiTempVar == EEPROM_REJECT_REG_3) ||
268 (uiTempVar == EEPROM_REJECT_REG_4))) {
269
270 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
271 return -EFAULT;
272 }
273
274 Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register,
275 (PUINT)sWrmBuffer.Data, sizeof(ULONG));
276
277 if (Status == STATUS_SUCCESS) {
278 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
279 } else {
280 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
281 Status = -EFAULT;
282 }
283 break;
284 }
285
286 case IOCTL_BCM_REGISTER_READ:
287 case IOCTL_BCM_EEPROM_REGISTER_READ: {
288 RDM_BUFFER sRdmBuffer = {0};
289 PCHAR temp_buff = NULL;
290 UINT uiTempVar = 0;
291 if ((Adapter->IdleMode == TRUE) ||
292 (Adapter->bShutStatus == TRUE) ||
293 (Adapter->bPreparingForLowPowerMode == TRUE)) {
294
295 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n");
296 return -EACCES;
297 }
298
299 /* Copy Ioctl Buffer structure */
300 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
301 return -EFAULT;
302
303 if (IoBuffer.InputLength > sizeof(sRdmBuffer))
304 return -EINVAL;
305
306 if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
307 return -EFAULT;
308
Kevin McKinney51935d22011-11-08 22:33:35 -0500309 if (IoBuffer.OutputLength > USHRT_MAX ||
310 IoBuffer.OutputLength == 0) {
311 return -EINVAL;
312 }
313
Kevin McKinney6c15e002011-08-15 22:07:41 -0400314 temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL);
315 if (!temp_buff)
316 return STATUS_FAILURE;
317
318 if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) ||
319 ((ULONG)sRdmBuffer.Register & 0x3)) {
320
321 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n",
322 (int)sRdmBuffer.Register);
Kevin McKinney1dc63472011-08-15 22:12:15 -0400323
324 kfree(temp_buff);
Kevin McKinney6c15e002011-08-15 22:07:41 -0400325 return -EINVAL;
326 }
327
328 uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500329 bytes = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength);
Kevin McKinney6c15e002011-08-15 22:07:41 -0400330
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500331 if (bytes > 0) {
332 Status = STATUS_SUCCESS;
333 if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, bytes))
Kevin McKinney6c15e002011-08-15 22:07:41 -0400334 Status = -EFAULT;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500335 } else {
336 Status = bytes;
337 }
Kevin McKinney6c15e002011-08-15 22:07:41 -0400338
339 kfree(temp_buff);
340 break;
341 }
342 case IOCTL_BCM_REGISTER_WRITE:
343 case IOCTL_BCM_EEPROM_REGISTER_WRITE: {
344 WRM_BUFFER sWrmBuffer = {0};
345 UINT uiTempVar = 0;
346 if ((Adapter->IdleMode == TRUE) ||
347 (Adapter->bShutStatus == TRUE) ||
348 (Adapter->bPreparingForLowPowerMode == TRUE)) {
349
350 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n");
351 return -EACCES;
352 }
353
354 /* Copy Ioctl Buffer structure */
355 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
356 return -EFAULT;
357
358 if (IoBuffer.InputLength > sizeof(sWrmBuffer))
359 return -EINVAL;
360
361 /* Get WrmBuffer structure */
362 if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength))
363 return -EFAULT;
364
365 if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) ||
366 ((ULONG)sWrmBuffer.Register & 0x3)) {
367
368 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)sWrmBuffer.Register);
369 return -EINVAL;
370 }
371
372 uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK;
373 if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) &&
374 ((uiTempVar == EEPROM_REJECT_REG_1) ||
375 (uiTempVar == EEPROM_REJECT_REG_2) ||
376 (uiTempVar == EEPROM_REJECT_REG_3) ||
377 (uiTempVar == EEPROM_REJECT_REG_4)) &&
378 (cmd == IOCTL_BCM_REGISTER_WRITE)) {
379
380 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
381 return -EFAULT;
382 }
383
384 Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register,
385 (PUINT)sWrmBuffer.Data, sWrmBuffer.Length);
386
387 if (Status == STATUS_SUCCESS) {
388 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n");
389 } else {
390 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n");
391 Status = -EFAULT;
392 }
393 break;
394 }
395 case IOCTL_BCM_GPIO_SET_REQUEST: {
396 UCHAR ucResetValue[4];
397 UINT value = 0;
398 UINT uiBit = 0;
399 UINT uiOperation = 0;
400
401 GPIO_INFO gpio_info = {0};
402 if ((Adapter->IdleMode == TRUE) ||
403 (Adapter->bShutStatus == TRUE) ||
404 (Adapter->bPreparingForLowPowerMode == TRUE)) {
405
406 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode");
407 return -EACCES;
408 }
409
410 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
411 return -EFAULT;
412
413 if (IoBuffer.InputLength > sizeof(gpio_info))
414 return -EINVAL;
415
416 if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
417 return -EFAULT;
418
419 uiBit = gpio_info.uiGpioNumber;
420 uiOperation = gpio_info.uiGpioValue;
421 value = (1<<uiBit);
422
423 if (IsReqGpioIsLedInNVM(Adapter, value) == FALSE) {
424 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!", value);
425 Status = -EINVAL;
426 break;
427 }
428
429 /* Set - setting 1 */
430 if (uiOperation) {
431 /* Set the gpio output register */
432 Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, (PUINT)(&value), sizeof(UINT));
433
434 if (Status == STATUS_SUCCESS) {
435 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
436 } else {
437 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to set the %dth GPIO\n", uiBit);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700438 break;
439 }
Kevin McKinney6c15e002011-08-15 22:07:41 -0400440 } else {
441 /* Set the gpio output register */
442 Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)(&value), sizeof(UINT));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700443
Kevin McKinney6c15e002011-08-15 22:07:41 -0400444 if (Status == STATUS_SUCCESS) {
445 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n");
446 } else {
447 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to clear the %dth GPIO\n", uiBit);
448 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700449 }
Kevin McKinney6c15e002011-08-15 22:07:41 -0400450 }
451
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500452 bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
453 if (bytes < 0) {
454 Status = bytes;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400455 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
456 "GPIO_MODE_REGISTER read failed");
457 break;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500458 } else {
459 Status = STATUS_SUCCESS;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400460 }
461
462 /* Set the gpio mode register to output */
463 *(UINT *)ucResetValue |= (1<<uiBit);
464 Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER,
465 (PUINT)ucResetValue, sizeof(UINT));
466
467 if (Status == STATUS_SUCCESS) {
468 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO to output Mode\n");
469 } else {
470 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n");
471 break;
472 }
473 }
474 break;
475
476 case BCM_LED_THREAD_STATE_CHANGE_REQ: {
477 USER_THREAD_REQ threadReq = {0};
478 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "User made LED thread InActive");
479
480 if ((Adapter->IdleMode == TRUE) ||
481 (Adapter->bShutStatus == TRUE) ||
482 (Adapter->bPreparingForLowPowerMode == TRUE)) {
483
484 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode");
485 Status = -EACCES;
486 break;
487 }
488
489 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
490 return -EFAULT;
491
492 if (IoBuffer.InputLength > sizeof(threadReq))
493 return -EINVAL;
494
495 if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength))
496 return -EFAULT;
497
498 /* if LED thread is running(Actively or Inactively) set it state to make inactive */
499 if (Adapter->LEDInfo.led_thread_running) {
500 if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) {
501 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Activating thread req");
502 Adapter->DriverState = LED_THREAD_ACTIVE;
503 } else {
504 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DeActivating Thread req.....");
505 Adapter->DriverState = LED_THREAD_INACTIVE;
506 }
507
508 /* signal thread. */
509 wake_up(&Adapter->LEDInfo.notify_led_event);
510 }
511 }
512 break;
513
514 case IOCTL_BCM_GPIO_STATUS_REQUEST: {
515 ULONG uiBit = 0;
516 UCHAR ucRead[4];
517 GPIO_INFO gpio_info = {0};
518
519 if ((Adapter->IdleMode == TRUE) ||
520 (Adapter->bShutStatus == TRUE) ||
521 (Adapter->bPreparingForLowPowerMode == TRUE))
522 return -EACCES;
523
524 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
525 return -EFAULT;
526
527 if (IoBuffer.InputLength > sizeof(gpio_info))
528 return -EINVAL;
529
530 if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
531 return -EFAULT;
532
533 uiBit = gpio_info.uiGpioNumber;
534
535 /* Set the gpio output register */
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500536 bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER,
Kevin McKinney6c15e002011-08-15 22:07:41 -0400537 (PUINT)ucRead, sizeof(UINT));
538
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500539 if (bytes < 0) {
540 Status = bytes;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400541 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n");
542 return Status;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500543 } else {
544 Status = STATUS_SUCCESS;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400545 }
546 }
547 break;
548
549 case IOCTL_BCM_GPIO_MULTI_REQUEST: {
550 UCHAR ucResetValue[4];
551 GPIO_MULTI_INFO gpio_multi_info[MAX_IDX];
552 PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info;
553
554 memset(pgpio_multi_info, 0, MAX_IDX * sizeof(GPIO_MULTI_INFO));
555
556 if ((Adapter->IdleMode == TRUE) ||
557 (Adapter->bShutStatus == TRUE) ||
558 (Adapter->bPreparingForLowPowerMode == TRUE))
559 return -EINVAL;
560
561 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
562 return -EFAULT;
563
564 if (IoBuffer.InputLength > sizeof(gpio_multi_info))
565 return -EINVAL;
566
567 if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength))
568 return -EFAULT;
569
570 if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == FALSE) {
571 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
572 "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
573 pgpio_multi_info[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
574 Status = -EINVAL;
575 break;
576 }
577
578 /* Set the gpio output register */
579 if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) &
580 (pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) {
581 /* Set 1's in GPIO OUTPUT REGISTER */
582 *(UINT *)ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
583 pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
584 pgpio_multi_info[WIMAX_IDX].uiGPIOValue;
585
586 if (*(UINT *) ucResetValue)
587 Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG,
588 (PUINT)ucResetValue, sizeof(ULONG));
589
590 if (Status != STATUS_SUCCESS) {
591 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_SET_REG Failed.");
592 return Status;
593 }
594
595 /* Clear to 0's in GPIO OUTPUT REGISTER */
596 *(UINT *)ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask &
597 pgpio_multi_info[WIMAX_IDX].uiGPIOCommand &
598 (~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue)));
599
600 if (*(UINT *) ucResetValue)
601 Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue, sizeof(ULONG));
602
603 if (Status != STATUS_SUCCESS) {
604 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed.");
605 return Status;
606 }
607 }
608
609 if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) {
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500610 bytes = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
Kevin McKinney6c15e002011-08-15 22:07:41 -0400611
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500612 if (bytes < 0) {
613 Status = bytes;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400614 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed.");
615 return Status;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500616 } else {
617 Status = STATUS_SUCCESS;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400618 }
619
620 pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue &
621 pgpio_multi_info[WIMAX_IDX].uiGPIOMask);
622 }
623
624 Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength);
625 if (Status) {
626 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
627 "Failed while copying Content to IOBufer for user space err:%d", Status);
628 break;
629 }
630 }
631 break;
632
633 case IOCTL_BCM_GPIO_MODE_REQUEST: {
634 UCHAR ucResetValue[4];
635 GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX];
636 PGPIO_MULTI_MODE pgpio_multi_mode = (PGPIO_MULTI_MODE)gpio_multi_mode;
637
638 if ((Adapter->IdleMode == TRUE) ||
639 (Adapter->bShutStatus == TRUE) ||
640 (Adapter->bPreparingForLowPowerMode == TRUE))
641 return -EINVAL;
642
643 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
644 return -EFAULT;
645
646 if (IoBuffer.InputLength > sizeof(gpio_multi_mode))
647 return -EINVAL;
648
649 if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength))
650 return -EFAULT;
651
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500652 bytes = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT));
Kevin McKinney6c15e002011-08-15 22:07:41 -0400653
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500654 if (bytes < 0) {
655 Status = bytes;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400656 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed");
657 return Status;
Kevin McKinney41c7b7c2011-11-06 09:40:11 -0500658 } else {
659 Status = STATUS_SUCCESS;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400660 }
661
662 /* Validating the request */
663 if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == FALSE) {
664 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
665 "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",
666 pgpio_multi_mode[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap);
667 Status = -EINVAL;
668 break;
669 }
670
671 if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) {
672 /* write all OUT's (1's) */
673 *(UINT *) ucResetValue |= (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode &
674 pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
675
676 /* write all IN's (0's) */
677 *(UINT *) ucResetValue &= ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) &
678 pgpio_multi_mode[WIMAX_IDX].uiGPIOMask);
679
680 /* Currently implemented return the modes of all GPIO's
681 * else needs to bit AND with mask
682 */
683 pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
684
685 Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(ULONG));
686 if (Status == STATUS_SUCCESS) {
687 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
688 "WRM to GPIO_MODE_REGISTER Done");
689 } else {
690 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
691 "WRM to GPIO_MODE_REGISTER Failed");
692 Status = -EFAULT;
693 break;
694 }
695 } else {
696/* if uiGPIOMask is 0 then return mode register configuration */
697 pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue;
698 }
699
700 Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength);
701 if (Status) {
702 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
703 "Failed while copying Content to IOBufer for user space err:%d", Status);
704 break;
705 }
706 }
707 break;
708
709 case IOCTL_MAC_ADDR_REQ:
710 case IOCTL_LINK_REQ:
711 case IOCTL_CM_REQUEST:
712 case IOCTL_SS_INFO_REQ:
713 case IOCTL_SEND_CONTROL_MESSAGE:
714 case IOCTL_IDLE_REQ: {
715 PVOID pvBuffer = NULL;
716
717 /* Copy Ioctl Buffer structure */
718 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
719 return -EFAULT;
720
Kevin McKinney5ac5bd82011-09-18 18:34:46 -0400721 if (IoBuffer.InputLength < sizeof(struct link_request))
722 return -EINVAL;
723
Kevin McKinneye228b742011-09-18 18:34:47 -0400724 if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE)
725 return -EINVAL;
726
Kevin McKinney6c15e002011-08-15 22:07:41 -0400727 pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
728 if (!pvBuffer)
729 return -ENOMEM;
730
731 if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
732 Status = -EFAULT;
Stephen Hemminger082e8892010-11-01 09:35:21 -0400733 kfree(pvBuffer);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700734 break;
735 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700736
Kevin McKinney6c15e002011-08-15 22:07:41 -0400737 down(&Adapter->LowPowerModeSync);
738 Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue,
739 !Adapter->bPreparingForLowPowerMode,
740 (1 * HZ));
741 if (Status == -ERESTARTSYS)
742 goto cntrlEnd;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700743
Kevin McKinney6c15e002011-08-15 22:07:41 -0400744 if (Adapter->bPreparingForLowPowerMode) {
745 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
746 "Preparing Idle Mode is still True - Hence Rejecting control message\n");
747 Status = STATUS_FAILURE;
748 goto cntrlEnd;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700749 }
Kevin McKinney6c15e002011-08-15 22:07:41 -0400750 Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer);
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400751
Kevin McKinney6c15e002011-08-15 22:07:41 -0400752cntrlEnd:
753 up(&Adapter->LowPowerModeSync);
754 kfree(pvBuffer);
755 break;
756 }
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400757
Kevin McKinney6c15e002011-08-15 22:07:41 -0400758 case IOCTL_BCM_BUFFER_DOWNLOAD_START: {
Kevin McKinneyfef56752011-11-27 20:51:45 -0500759 if (down_trylock(&Adapter->NVMRdmWrmLock)) {
Kevin McKinney6c15e002011-08-15 22:07:41 -0400760 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
761 "IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
762 return -EACCES;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700763 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700764
Kevin McKinney6c15e002011-08-15 22:07:41 -0400765 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
766 "Starting the firmware download PID =0x%x!!!!\n", current->pid);
767
Kevin McKinney8fbebb02011-11-27 20:51:46 -0500768 if (down_trylock(&Adapter->fw_download_sema))
769 return -EBUSY;
770
771 Adapter->bBinDownloaded = FALSE;
772 Adapter->fw_download_process_pid = current->pid;
773 Adapter->bCfgDownloaded = FALSE;
774 Adapter->fw_download_done = FALSE;
775 netif_carrier_off(Adapter->dev);
776 netif_stop_queue(Adapter->dev);
777 Status = reset_card_proc(Adapter);
778 if (Status) {
779 pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name);
780 up(&Adapter->fw_download_sema);
781 up(&Adapter->NVMRdmWrmLock);
782 return Status;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400783 }
Kevin McKinney8fbebb02011-11-27 20:51:46 -0500784 mdelay(10);
Kevin McKinney6c15e002011-08-15 22:07:41 -0400785
786 up(&Adapter->NVMRdmWrmLock);
Kevin McKinney8fbebb02011-11-27 20:51:46 -0500787 return Status;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400788 }
789
790 case IOCTL_BCM_BUFFER_DOWNLOAD: {
791 FIRMWARE_INFO *psFwInfo = NULL;
792 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid);
Stephen Hemmingerada692b2010-11-01 09:26:47 -0400793
Kevin McKinney77121d52011-11-22 20:25:55 -0500794 if (!down_trylock(&Adapter->fw_download_sema)) {
Kevin McKinney6c15e002011-08-15 22:07:41 -0400795 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
Kevin McKinney77121d52011-11-22 20:25:55 -0500796 "Invalid way to download buffer. Use Start and then call this!!!\n");
Kevin McKinneyabe33fc2011-11-22 20:25:56 -0500797 up(&Adapter->fw_download_sema);
Kevin McKinney77121d52011-11-22 20:25:55 -0500798 Status = -EINVAL;
Kevin McKinney8fbebb02011-11-27 20:51:46 -0500799 return Status;
Kevin McKinney77121d52011-11-22 20:25:55 -0500800 }
Kevin McKinney6c15e002011-08-15 22:07:41 -0400801
Kevin McKinney77121d52011-11-22 20:25:55 -0500802 /* Copy Ioctl Buffer structure */
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500803 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
804 up(&Adapter->fw_download_sema);
Kevin McKinney77121d52011-11-22 20:25:55 -0500805 return -EFAULT;
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500806 }
Kevin McKinney77121d52011-11-22 20:25:55 -0500807
808 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
809 "Length for FW DLD is : %lx\n", IoBuffer.InputLength);
810
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500811 if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) {
812 up(&Adapter->fw_download_sema);
Kevin McKinney77121d52011-11-22 20:25:55 -0500813 return -EINVAL;
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500814 }
Kevin McKinney77121d52011-11-22 20:25:55 -0500815
816 psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL);
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500817 if (!psFwInfo) {
818 up(&Adapter->fw_download_sema);
Kevin McKinney77121d52011-11-22 20:25:55 -0500819 return -ENOMEM;
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500820 }
Kevin McKinney77121d52011-11-22 20:25:55 -0500821
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500822 if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
823 up(&Adapter->fw_download_sema);
Kevin McKinney77121d52011-11-22 20:25:55 -0500824 return -EFAULT;
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500825 }
Kevin McKinney77121d52011-11-22 20:25:55 -0500826
827 if (!psFwInfo->pvMappedFirmwareAddress ||
828 (psFwInfo->u32FirmwareLength == 0)) {
829
830 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n",
831 psFwInfo->u32FirmwareLength);
Kevin McKinneyd9f26a62011-11-22 20:25:57 -0500832 up(&Adapter->fw_download_sema);
Kevin McKinney77121d52011-11-22 20:25:55 -0500833 Status = -EINVAL;
Kevin McKinney8fbebb02011-11-27 20:51:46 -0500834 return Status;
Kevin McKinney77121d52011-11-22 20:25:55 -0500835 }
836
837 Status = bcm_ioctl_fw_download(Adapter, psFwInfo);
838
839 if (Status != STATUS_SUCCESS) {
840 if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR)
841 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n");
842 else
843 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n");
844
845 /* up(&Adapter->fw_download_sema); */
846
847 if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
848 Adapter->DriverState = DRIVER_INIT;
849 Adapter->LEDInfo.bLedInitDone = FALSE;
850 wake_up(&Adapter->LEDInfo.notify_led_event);
851 }
852 }
Kevin McKinney6c15e002011-08-15 22:07:41 -0400853
854 if (Status != STATUS_SUCCESS)
855 up(&Adapter->fw_download_sema);
856
857 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n");
858 kfree(psFwInfo);
Kevin McKinney8fbebb02011-11-27 20:51:46 -0500859 return Status;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400860 }
861
862 case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: {
Kevin McKinney19a177e2011-11-27 20:51:47 -0500863 if (!down_trylock(&Adapter->fw_download_sema)) {
864 up(&Adapter->fw_download_sema);
865 return -EINVAL;
866 }
867
Kevin McKinneyfef56752011-11-27 20:51:45 -0500868 if (down_trylock(&Adapter->NVMRdmWrmLock)) {
Kevin McKinney6c15e002011-08-15 22:07:41 -0400869 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
870 "FW download blocked as EEPROM Read/Write is in progress\n");
871 up(&Adapter->fw_download_sema);
872 return -EACCES;
873 }
874
Kevin McKinney8fbebb02011-11-27 20:51:46 -0500875 Adapter->bBinDownloaded = TRUE;
876 Adapter->bCfgDownloaded = TRUE;
877 atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
878 Adapter->CurrNumRecvDescs = 0;
879 Adapter->downloadDDR = 0;
880
881 /* setting the Mips to Run */
882 Status = run_card_proc(Adapter);
883
884 if (Status) {
885 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n");
886 up(&Adapter->fw_download_sema);
887 up(&Adapter->NVMRdmWrmLock);
888 return Status;
889 } else {
890 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG,
891 DBG_LVL_ALL, "Firm Download Over...\n");
892 }
893
894 mdelay(10);
895
896 /* Wait for MailBox Interrupt */
897 if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter))
898 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n");
899
900 timeout = 5*HZ;
901 Adapter->waiting_to_fw_download_done = FALSE;
902 wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue,
903 Adapter->waiting_to_fw_download_done, timeout);
904 Adapter->fw_download_process_pid = INVALID_PID;
905 Adapter->fw_download_done = TRUE;
906 atomic_set(&Adapter->CurrNumFreeTxDesc, 0);
907 Adapter->CurrNumRecvDescs = 0;
908 Adapter->PrevNumRecvDescs = 0;
909 atomic_set(&Adapter->cntrlpktCnt, 0);
910 Adapter->LinkUpStatus = 0;
911 Adapter->LinkStatus = 0;
912
913 if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
914 Adapter->DriverState = FW_DOWNLOAD_DONE;
915 wake_up(&Adapter->LEDInfo.notify_led_event);
916 }
917
918 if (!timeout)
919 Status = -ENODEV;
920
Kevin McKinney6c15e002011-08-15 22:07:41 -0400921 up(&Adapter->fw_download_sema);
922 up(&Adapter->NVMRdmWrmLock);
Kevin McKinney8fbebb02011-11-27 20:51:46 -0500923 return Status;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400924 }
925
926 case IOCTL_BE_BUCKET_SIZE:
927 Status = 0;
928 if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg))
929 Status = -EFAULT;
930 break;
931
932 case IOCTL_RTPS_BUCKET_SIZE:
933 Status = 0;
934 if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg))
935 Status = -EFAULT;
936 break;
937
938 case IOCTL_CHIP_RESET: {
939 INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock);
940 if (NVMAccess) {
941 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n");
942 return -EACCES;
943 }
944
945 down(&Adapter->RxAppControlQueuelock);
946 Status = reset_card_proc(Adapter);
947 flushAllAppQ();
948 up(&Adapter->RxAppControlQueuelock);
949 up(&Adapter->NVMRdmWrmLock);
950 ResetCounters(Adapter);
951 break;
952 }
953
954 case IOCTL_QOS_THRESHOLD: {
955 USHORT uiLoopIndex;
956
957 Status = 0;
958 for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) {
959 if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold,
960 (unsigned long __user *)arg)) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700961 Status = -EFAULT;
962 break;
963 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700964 }
965 break;
Kevin McKinney6c15e002011-08-15 22:07:41 -0400966 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700967
Kevin McKinney6c15e002011-08-15 22:07:41 -0400968 case IOCTL_DUMP_PACKET_INFO:
969 DumpPackInfo(Adapter);
970 DumpPhsRules(&Adapter->stBCMPhsContext);
971 Status = STATUS_SUCCESS;
972 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700973
Kevin McKinney6c15e002011-08-15 22:07:41 -0400974 case IOCTL_GET_PACK_INFO:
975 if (copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES))
976 return -EFAULT;
977 Status = STATUS_SUCCESS;
978 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700979
Kevin McKinney6c15e002011-08-15 22:07:41 -0400980 case IOCTL_BCM_SWITCH_TRANSFER_MODE: {
981 UINT uiData = 0;
982 if (copy_from_user(&uiData, argp, sizeof(UINT)))
983 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700984
Kevin McKinney6c15e002011-08-15 22:07:41 -0400985 if (uiData) {
986 /* Allow All Packets */
987 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n");
988 Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE;
989 } else {
990 /* Allow IP only Packets */
991 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n");
992 Adapter->TransferMode = IP_PACKET_ONLY_MODE;
993 }
994 Status = STATUS_SUCCESS;
995 break;
996 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700997
Kevin McKinney6c15e002011-08-15 22:07:41 -0400998 case IOCTL_BCM_GET_DRIVER_VERSION: {
999 /* Copy Ioctl Buffer structure */
1000 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1001 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001002
Kevin McKinney6c15e002011-08-15 22:07:41 -04001003 if (copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength))
1004 return -EFAULT;
1005 Status = STATUS_SUCCESS;
1006 break;
1007 }
1008
1009 case IOCTL_BCM_GET_CURRENT_STATUS: {
1010 LINK_STATE link_state;
1011
1012 /* Copy Ioctl Buffer structure */
1013 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
1014 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n");
1015 Status = -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001016 break;
1017 }
1018
Kevin McKinney6c15e002011-08-15 22:07:41 -04001019 if (IoBuffer.OutputLength != sizeof(link_state)) {
1020 Status = -EINVAL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001021 break;
Kevin McKinney6c15e002011-08-15 22:07:41 -04001022 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001023
Kevin McKinney6c15e002011-08-15 22:07:41 -04001024 memset(&link_state, 0, sizeof(link_state));
1025 link_state.bIdleMode = Adapter->IdleMode;
1026 link_state.bShutdownMode = Adapter->bShutStatus;
1027 link_state.ucLinkStatus = Adapter->LinkStatus;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001028
Kevin McKinney6c15e002011-08-15 22:07:41 -04001029 if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) {
1030 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n");
1031 Status = -EFAULT;
1032 break;
1033 }
1034 Status = STATUS_SUCCESS;
1035 break;
1036 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001037
Kevin McKinney6c15e002011-08-15 22:07:41 -04001038 case IOCTL_BCM_SET_MAC_TRACING: {
1039 UINT tracing_flag;
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001040
Kevin McKinney6c15e002011-08-15 22:07:41 -04001041 /* copy ioctl Buffer structure */
1042 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1043 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001044
Kevin McKinney6c15e002011-08-15 22:07:41 -04001045 if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT)))
1046 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001047
Kevin McKinney6c15e002011-08-15 22:07:41 -04001048 if (tracing_flag)
1049 Adapter->pTarangs->MacTracingEnabled = TRUE;
1050 else
1051 Adapter->pTarangs->MacTracingEnabled = FALSE;
1052 break;
1053 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001054
Kevin McKinney6c15e002011-08-15 22:07:41 -04001055 case IOCTL_BCM_GET_DSX_INDICATION: {
1056 ULONG ulSFId = 0;
1057 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1058 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001059
Kevin McKinney6c15e002011-08-15 22:07:41 -04001060 if (IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) {
1061 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
1062 "Mismatch req: %lx needed is =0x%zx!!!",
1063 IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt));
1064 return -EINVAL;
1065 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001066
Kevin McKinney6c15e002011-08-15 22:07:41 -04001067 if (copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId)))
1068 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001069
Kevin McKinney6c15e002011-08-15 22:07:41 -04001070 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId);
1071 get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer);
1072 Status = STATUS_SUCCESS;
1073 }
1074 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001075
Kevin McKinney6c15e002011-08-15 22:07:41 -04001076 case IOCTL_BCM_GET_HOST_MIBS: {
1077 PVOID temp_buff;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001078
Kevin McKinney6c15e002011-08-15 22:07:41 -04001079 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1080 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001081
Kevin McKinney6c15e002011-08-15 22:07:41 -04001082 if (IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) {
1083 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
1084 "Length Check failed %lu %zd\n",
1085 IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS));
1086 return -EINVAL;
1087 }
1088
1089 /* FIXME: HOST_STATS are too big for kmalloc (122048)! */
1090 temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL);
1091 if (!temp_buff)
1092 return STATUS_FAILURE;
1093
1094 Status = ProcessGetHostMibs(Adapter, temp_buff);
1095 GetDroppedAppCntrlPktMibs(temp_buff, pTarang);
1096
1097 if (Status != STATUS_FAILURE)
1098 if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS)))
1099 Status = -EFAULT;
1100
1101 kfree(temp_buff);
1102 break;
1103 }
1104
1105 case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE:
1106 if ((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) {
1107 Adapter->usIdleModePattern = ABORT_IDLE_MODE;
1108 Adapter->bWakeUpDevice = TRUE;
1109 wake_up(&Adapter->process_rx_cntrlpkt);
1110 }
1111
1112 Status = STATUS_SUCCESS;
1113 break;
1114
1115 case IOCTL_BCM_BULK_WRM: {
1116 PBULKWRM_BUFFER pBulkBuffer;
1117 UINT uiTempVar = 0;
1118 PCHAR pvBuffer = NULL;
1119
1120 if ((Adapter->IdleMode == TRUE) ||
1121 (Adapter->bShutStatus == TRUE) ||
1122 (Adapter->bPreparingForLowPowerMode == TRUE)) {
1123
1124 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n");
1125 Status = -EACCES;
1126 break;
1127 }
1128
1129 /* Copy Ioctl Buffer structure */
1130 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1131 return -EFAULT;
1132
1133 /* FIXME: restrict length */
1134 pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL);
1135 if (!pvBuffer)
1136 return -ENOMEM;
1137
1138 /* Get WrmBuffer structure */
1139 if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) {
1140 kfree(pvBuffer);
1141 Status = -EFAULT;
1142 break;
1143 }
1144
1145 pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer;
1146
1147 if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 ||
1148 ((ULONG)pBulkBuffer->Register & 0x3)) {
1149 kfree(pvBuffer);
1150 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register);
1151 Status = -EINVAL;
1152 break;
1153 }
1154
1155 uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK;
1156 if (!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) &&
1157 ((uiTempVar == EEPROM_REJECT_REG_1) ||
1158 (uiTempVar == EEPROM_REJECT_REG_2) ||
1159 (uiTempVar == EEPROM_REJECT_REG_3) ||
1160 (uiTempVar == EEPROM_REJECT_REG_4)) &&
1161 (cmd == IOCTL_BCM_REGISTER_WRITE)) {
1162
1163 kfree(pvBuffer);
1164 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n");
1165 Status = -EFAULT;
1166 break;
1167 }
1168
1169 if (pBulkBuffer->SwapEndian == FALSE)
1170 Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
1171 else
1172 Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG));
1173
1174 if (Status != STATUS_SUCCESS)
1175 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n");
1176
1177 kfree(pvBuffer);
1178 break;
1179 }
1180
1181 case IOCTL_BCM_GET_NVM_SIZE:
1182 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1183 return -EFAULT;
1184
1185 if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) {
1186 if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT)))
1187 return -EFAULT;
1188 }
1189
1190 Status = STATUS_SUCCESS;
1191 break;
1192
1193 case IOCTL_BCM_CAL_INIT: {
1194 UINT uiSectorSize = 0 ;
1195 if (Adapter->eNVMType == NVM_FLASH) {
1196 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001197 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001198
Kevin McKinney6c15e002011-08-15 22:07:41 -04001199 if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT)))
1200 return -EFAULT;
1201
1202 if ((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) {
1203 if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize,
1204 sizeof(UINT)))
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001205 return -EFAULT;
Kevin McKinney6c15e002011-08-15 22:07:41 -04001206 } else {
1207 if (IsFlash2x(Adapter)) {
1208 if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, sizeof(UINT)))
Dan Carpenterbf58bd62010-10-08 14:53:48 +02001209 return -EFAULT;
Kevin McKinney6c15e002011-08-15 22:07:41 -04001210 } else {
1211 if ((TRUE == Adapter->bShutStatus) || (TRUE == Adapter->IdleMode)) {
1212 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is in Idle/Shutdown Mode\n");
1213 return -EACCES;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001214 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001215
Kevin McKinney6c15e002011-08-15 22:07:41 -04001216 Adapter->uiSectorSize = uiSectorSize;
1217 BcmUpdateSectorSize(Adapter, Adapter->uiSectorSize);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001218 }
1219 }
Kevin McKinney6c15e002011-08-15 22:07:41 -04001220 Status = STATUS_SUCCESS;
1221 } else {
1222 Status = STATUS_FAILURE;
1223 }
1224 }
1225 break;
1226
1227 case IOCTL_BCM_SET_DEBUG:
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001228#ifdef DEBUG
Kevin McKinney6c15e002011-08-15 22:07:41 -04001229 {
1230 USER_BCM_DBG_STATE sUserDebugState;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001231
Kevin McKinney6c15e002011-08-15 22:07:41 -04001232 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n");
1233 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1234 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001235
Kevin McKinney6c15e002011-08-15 22:07:41 -04001236 if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE)))
1237 return -EFAULT;
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001238
Kevin McKinney6c15e002011-08-15 22:07:41 -04001239 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ",
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001240 sUserDebugState.OnOff, sUserDebugState.Type);
Kevin McKinney6c15e002011-08-15 22:07:41 -04001241 /* sUserDebugState.Subtype <<= 1; */
1242 sUserDebugState.Subtype = 1 << sUserDebugState.Subtype;
1243 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001244
Kevin McKinney6c15e002011-08-15 22:07:41 -04001245 /* Update new 'DebugState' in the Adapter */
1246 Adapter->stDebugState.type |= sUserDebugState.Type;
1247 /* Subtype: A bitmap of 32 bits for Subtype per Type.
1248 * Valid indexes in 'subtype' array: 1,2,4,8
1249 * corresponding to valid Type values. Hence we can use the 'Type' field
1250 * as the index value, ignoring the array entries 0,3,5,6,7 !
1251 */
1252 if (sUserDebugState.OnOff)
1253 Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype;
1254 else
1255 Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001256
Kevin McKinney6c15e002011-08-15 22:07:41 -04001257 BCM_SHOW_DEBUG_BITMAP(Adapter);
1258 }
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001259#endif
Kevin McKinney6c15e002011-08-15 22:07:41 -04001260 break;
1261
1262 case IOCTL_BCM_NVM_READ:
1263 case IOCTL_BCM_NVM_WRITE: {
1264 NVM_READWRITE stNVMReadWrite;
1265 PUCHAR pReadData = NULL;
1266 ULONG ulDSDMagicNumInUsrBuff = 0;
1267 struct timeval tv0, tv1;
1268 memset(&tv0, 0, sizeof(struct timeval));
1269 memset(&tv1, 0, sizeof(struct timeval));
1270 if ((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) {
1271 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n");
1272 Status = -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001273 break;
Kevin McKinney6c15e002011-08-15 22:07:41 -04001274 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001275
Kevin McKinney6c15e002011-08-15 22:07:41 -04001276 if (IsFlash2x(Adapter)) {
1277 if ((Adapter->eActiveDSD != DSD0) &&
1278 (Adapter->eActiveDSD != DSD1) &&
1279 (Adapter->eActiveDSD != DSD2)) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001280
Kevin McKinney6c15e002011-08-15 22:07:41 -04001281 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No DSD is active..hence NVM Command is blocked");
1282 return STATUS_FAILURE ;
1283 }
1284 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001285
Kevin McKinney6c15e002011-08-15 22:07:41 -04001286 /* Copy Ioctl Buffer structure */
1287 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1288 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001289
Kevin McKinney6c15e002011-08-15 22:07:41 -04001290 if (copy_from_user(&stNVMReadWrite,
1291 (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer,
1292 sizeof(NVM_READWRITE)))
1293 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001294
Kevin McKinney6c15e002011-08-15 22:07:41 -04001295 /*
1296 * Deny the access if the offset crosses the cal area limit.
1297 */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001298
Kevin McKinney6c15e002011-08-15 22:07:41 -04001299 if ((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) {
1300 /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */
1301 Status = STATUS_FAILURE;
1302 break;
1303 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001304
Kevin McKinney6c15e002011-08-15 22:07:41 -04001305 pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL);
1306 if (!pReadData)
1307 return -ENOMEM;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001308
Kevin McKinney6c15e002011-08-15 22:07:41 -04001309 if (copy_from_user(pReadData, stNVMReadWrite.pBuffer, stNVMReadWrite.uiNumBytes)) {
1310 Status = -EFAULT;
1311 kfree(pReadData);
1312 break;
1313 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001314
Kevin McKinney6c15e002011-08-15 22:07:41 -04001315 do_gettimeofday(&tv0);
1316 if (IOCTL_BCM_NVM_READ == cmd) {
1317 down(&Adapter->NVMRdmWrmLock);
1318
1319 if ((Adapter->IdleMode == TRUE) ||
1320 (Adapter->bShutStatus == TRUE) ||
1321 (Adapter->bPreparingForLowPowerMode == TRUE)) {
1322
1323 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
1324 up(&Adapter->NVMRdmWrmLock);
1325 kfree(pReadData);
1326 return -EACCES;
1327 }
1328
1329 Status = BeceemNVMRead(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes);
1330 up(&Adapter->NVMRdmWrmLock);
1331
1332 if (Status != STATUS_SUCCESS) {
1333 kfree(pReadData);
1334 return Status;
1335 }
1336
1337 if (copy_to_user(stNVMReadWrite.pBuffer, pReadData, stNVMReadWrite.uiNumBytes)) {
1338 kfree(pReadData);
1339 Status = -EFAULT;
1340 }
1341 } else {
1342 down(&Adapter->NVMRdmWrmLock);
1343
1344 if ((Adapter->IdleMode == TRUE) ||
1345 (Adapter->bShutStatus == TRUE) ||
1346 (Adapter->bPreparingForLowPowerMode == TRUE)) {
1347
1348 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
1349 up(&Adapter->NVMRdmWrmLock);
1350 kfree(pReadData);
1351 return -EACCES;
1352 }
1353
1354 Adapter->bHeaderChangeAllowed = TRUE;
1355 if (IsFlash2x(Adapter)) {
1356 /*
1357 * New Requirement:-
1358 * DSD section updation will be allowed in two case:-
1359 * 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull
1360 * 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is
1361 * corrupted then user space program first modify the DSD header with valid DSD sig so
1362 * that this as well as further write may be worthwhile.
1363 *
1364 * This restriction has been put assuming that if DSD sig is corrupted, DSD
1365 * data won't be considered valid.
1366 */
1367
1368 Status = BcmFlash2xCorruptSig(Adapter, Adapter->eActiveDSD);
1369 if (Status != STATUS_SUCCESS) {
1370 if (((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize) ||
1371 (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) {
1372
1373 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001374 up(&Adapter->NVMRdmWrmLock);
Stephen Hemminger082e8892010-11-01 09:35:21 -04001375 kfree(pReadData);
Kevin McKinney6c15e002011-08-15 22:07:41 -04001376 return Status;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001377 }
1378
Kevin McKinney6c15e002011-08-15 22:07:41 -04001379 ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE));
1380 if (ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) {
1381 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input..");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001382 up(&Adapter->NVMRdmWrmLock);
Stephen Hemminger082e8892010-11-01 09:35:21 -04001383 kfree(pReadData);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001384 return Status;
1385 }
1386 }
Kevin McKinney6c15e002011-08-15 22:07:41 -04001387 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001388
Kevin McKinney6c15e002011-08-15 22:07:41 -04001389 Status = BeceemNVMWrite(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify);
1390 if (IsFlash2x(Adapter))
1391 BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001392
Kevin McKinney6c15e002011-08-15 22:07:41 -04001393 Adapter->bHeaderChangeAllowed = FALSE;
1394
1395 up(&Adapter->NVMRdmWrmLock);
1396
1397 if (Status != STATUS_SUCCESS) {
Stephen Hemminger082e8892010-11-01 09:35:21 -04001398 kfree(pReadData);
Kevin McKinney6c15e002011-08-15 22:07:41 -04001399 return Status;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001400 }
Kevin McKinney6c15e002011-08-15 22:07:41 -04001401 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001402
Kevin McKinney6c15e002011-08-15 22:07:41 -04001403 do_gettimeofday(&tv1);
1404 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n", (tv1.tv_sec - tv0.tv_sec)*1000 + (tv1.tv_usec - tv0.tv_usec)/1000);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001405
Kevin McKinney6c15e002011-08-15 22:07:41 -04001406 kfree(pReadData);
1407 Status = STATUS_SUCCESS;
1408 }
1409 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001410
Kevin McKinney6c15e002011-08-15 22:07:41 -04001411 case IOCTL_BCM_FLASH2X_SECTION_READ: {
1412 FLASH2X_READWRITE sFlash2xRead = {0};
1413 PUCHAR pReadBuff = NULL ;
1414 UINT NOB = 0;
1415 UINT BuffSize = 0;
1416 UINT ReadBytes = 0;
1417 UINT ReadOffset = 0;
1418 void __user *OutPutBuff;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001419
Kevin McKinney6c15e002011-08-15 22:07:41 -04001420 if (IsFlash2x(Adapter) != TRUE) {
1421 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
1422 return -EINVAL;
1423 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001424
Kevin McKinney6c15e002011-08-15 22:07:41 -04001425 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called");
1426 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1427 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001428
Kevin McKinney6c15e002011-08-15 22:07:41 -04001429 /* Reading FLASH 2.x READ structure */
1430 if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
1431 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001432
Kevin McKinney6c15e002011-08-15 22:07:41 -04001433 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section);
1434 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%x", sFlash2xRead.offset);
1435 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xRead.numOfBytes);
1436 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xRead.bVerify);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001437
Kevin McKinney6c15e002011-08-15 22:07:41 -04001438 /* This was internal to driver for raw read. now it has ben exposed to user space app. */
1439 if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == FALSE)
1440 return STATUS_FAILURE;
1441
1442 NOB = sFlash2xRead.numOfBytes;
1443 if (NOB > Adapter->uiSectorSize)
1444 BuffSize = Adapter->uiSectorSize;
1445 else
1446 BuffSize = NOB;
1447
1448 ReadOffset = sFlash2xRead.offset ;
1449 OutPutBuff = IoBuffer.OutputBuffer;
1450 pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL);
1451
1452 if (pReadBuff == NULL) {
1453 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
1454 return -ENOMEM;
1455 }
1456 down(&Adapter->NVMRdmWrmLock);
1457
1458 if ((Adapter->IdleMode == TRUE) ||
1459 (Adapter->bShutStatus == TRUE) ||
1460 (Adapter->bPreparingForLowPowerMode == TRUE)) {
1461
1462 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
1463 up(&Adapter->NVMRdmWrmLock);
1464 kfree(pReadBuff);
1465 return -EACCES;
1466 }
1467
1468 while (NOB) {
1469 if (NOB > Adapter->uiSectorSize)
1470 ReadBytes = Adapter->uiSectorSize;
1471 else
1472 ReadBytes = NOB;
1473
1474 /* Reading the data from Flash 2.x */
1475 Status = BcmFlash2xBulkRead(Adapter, (PUINT)pReadBuff, sFlash2xRead.Section, ReadOffset, ReadBytes);
1476 if (Status) {
1477 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Flash 2x read err with Status :%d", Status);
1478 break;
1479 }
1480
1481 BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
1482
1483 Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
1484 if (Status) {
1485 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy to use failed with status :%d", Status);
1486 break;
1487 }
1488 NOB = NOB - ReadBytes;
1489 if (NOB) {
1490 ReadOffset = ReadOffset + ReadBytes;
1491 OutPutBuff = OutPutBuff + ReadBytes ;
1492 }
1493 }
1494
1495 up(&Adapter->NVMRdmWrmLock);
1496 kfree(pReadBuff);
1497 }
1498 break;
1499
1500 case IOCTL_BCM_FLASH2X_SECTION_WRITE: {
1501 FLASH2X_READWRITE sFlash2xWrite = {0};
1502 PUCHAR pWriteBuff;
1503 void __user *InputAddr;
1504 UINT NOB = 0;
1505 UINT BuffSize = 0;
1506 UINT WriteOffset = 0;
1507 UINT WriteBytes = 0;
1508
1509 if (IsFlash2x(Adapter) != TRUE) {
1510 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
1511 return -EINVAL;
1512 }
1513
1514 /* First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite */
1515 Adapter->bAllDSDWriteAllow = FALSE;
1516
1517 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called");
1518
1519 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1520 return -EFAULT;
1521
1522 /* Reading FLASH 2.x READ structure */
1523 if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)))
1524 return -EFAULT;
1525
1526 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section);
1527 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%d", sFlash2xWrite.offset);
1528 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xWrite.numOfBytes);
1529 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xWrite.bVerify);
1530
1531 if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && (sFlash2xWrite.Section != VSA2)) {
1532 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Only VSA write is allowed");
1533 return -EINVAL;
1534 }
1535
1536 if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == FALSE)
1537 return STATUS_FAILURE;
1538
1539 InputAddr = sFlash2xWrite.pDataBuff;
1540 WriteOffset = sFlash2xWrite.offset;
1541 NOB = sFlash2xWrite.numOfBytes;
1542
1543 if (NOB > Adapter->uiSectorSize)
1544 BuffSize = Adapter->uiSectorSize;
1545 else
1546 BuffSize = NOB ;
1547
1548 pWriteBuff = kmalloc(BuffSize, GFP_KERNEL);
1549
1550 if (pWriteBuff == NULL)
1551 return -ENOMEM;
1552
1553 /* extracting the remainder of the given offset. */
1554 WriteBytes = Adapter->uiSectorSize;
1555 if (WriteOffset % Adapter->uiSectorSize)
1556 WriteBytes = Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize);
1557
1558 if (NOB < WriteBytes)
1559 WriteBytes = NOB;
1560
1561 down(&Adapter->NVMRdmWrmLock);
1562
1563 if ((Adapter->IdleMode == TRUE) ||
1564 (Adapter->bShutStatus == TRUE) ||
1565 (Adapter->bPreparingForLowPowerMode == TRUE)) {
1566
1567 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
1568 up(&Adapter->NVMRdmWrmLock);
1569 kfree(pWriteBuff);
1570 return -EACCES;
1571 }
1572
1573 BcmFlash2xCorruptSig(Adapter, sFlash2xWrite.Section);
1574 do {
1575 Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes);
1576 if (Status) {
1577 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to user failed with status :%d", Status);
1578 break;
1579 }
1580 BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes);
1581
1582 /* Writing the data from Flash 2.x */
1583 Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pWriteBuff, sFlash2xWrite.Section, WriteOffset, WriteBytes, sFlash2xWrite.bVerify);
1584
1585 if (Status) {
1586 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
1587 break;
1588 }
1589
1590 NOB = NOB - WriteBytes;
1591 if (NOB) {
1592 WriteOffset = WriteOffset + WriteBytes;
1593 InputAddr = InputAddr + WriteBytes;
1594 if (NOB > Adapter->uiSectorSize)
1595 WriteBytes = Adapter->uiSectorSize;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001596 else
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001597 WriteBytes = NOB;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001598 }
Kevin McKinney6c15e002011-08-15 22:07:41 -04001599 } while (NOB > 0);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001600
Kevin McKinney6c15e002011-08-15 22:07:41 -04001601 BcmFlash2xWriteSig(Adapter, sFlash2xWrite.Section);
1602 up(&Adapter->NVMRdmWrmLock);
1603 kfree(pWriteBuff);
1604 }
1605 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001606
Kevin McKinney6c15e002011-08-15 22:07:41 -04001607 case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP: {
1608 PFLASH2X_BITMAP psFlash2xBitMap;
1609 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001610
Kevin McKinney6c15e002011-08-15 22:07:41 -04001611 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1612 return -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001613
Kevin McKinney6c15e002011-08-15 22:07:41 -04001614 if (IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP))
1615 return -EINVAL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001616
Kevin McKinney6c15e002011-08-15 22:07:41 -04001617 psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL);
1618 if (psFlash2xBitMap == NULL) {
1619 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available");
1620 return -ENOMEM;
1621 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001622
Kevin McKinney6c15e002011-08-15 22:07:41 -04001623 /* Reading the Flash Sectio Bit map */
1624 down(&Adapter->NVMRdmWrmLock);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001625
Kevin McKinney6c15e002011-08-15 22:07:41 -04001626 if ((Adapter->IdleMode == TRUE) ||
1627 (Adapter->bShutStatus == TRUE) ||
1628 (Adapter->bPreparingForLowPowerMode == TRUE)) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001629
Kevin McKinney6c15e002011-08-15 22:07:41 -04001630 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
1631 up(&Adapter->NVMRdmWrmLock);
1632 kfree(psFlash2xBitMap);
1633 return -EACCES;
1634 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001635
Kevin McKinney6c15e002011-08-15 22:07:41 -04001636 BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap);
1637 up(&Adapter->NVMRdmWrmLock);
1638 if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP)))
1639 Status = -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001640
Kevin McKinney6c15e002011-08-15 22:07:41 -04001641 kfree(psFlash2xBitMap);
1642 }
1643 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001644
Kevin McKinney6c15e002011-08-15 22:07:41 -04001645 case IOCTL_BCM_SET_ACTIVE_SECTION: {
1646 FLASH2X_SECTION_VAL eFlash2xSectionVal = 0;
1647 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001648
Kevin McKinney6c15e002011-08-15 22:07:41 -04001649 if (IsFlash2x(Adapter) != TRUE) {
1650 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
1651 return -EINVAL;
1652 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001653
Kevin McKinney6c15e002011-08-15 22:07:41 -04001654 Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
1655 if (Status) {
1656 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
1657 return Status;
1658 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001659
Kevin McKinney6c15e002011-08-15 22:07:41 -04001660 Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
1661 if (Status) {
1662 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
1663 return Status;
1664 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001665
Kevin McKinney6c15e002011-08-15 22:07:41 -04001666 down(&Adapter->NVMRdmWrmLock);
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001667
Kevin McKinney6c15e002011-08-15 22:07:41 -04001668 if ((Adapter->IdleMode == TRUE) ||
1669 (Adapter->bShutStatus == TRUE) ||
1670 (Adapter->bPreparingForLowPowerMode == TRUE)) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001671
Kevin McKinney6c15e002011-08-15 22:07:41 -04001672 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
1673 up(&Adapter->NVMRdmWrmLock);
1674 return -EACCES;
1675 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001676
Kevin McKinney6c15e002011-08-15 22:07:41 -04001677 Status = BcmSetActiveSection(Adapter, eFlash2xSectionVal);
1678 if (Status)
1679 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Failed to make it's priority Highest. Status %d", Status);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001680
Kevin McKinney6c15e002011-08-15 22:07:41 -04001681 up(&Adapter->NVMRdmWrmLock);
1682 }
1683 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001684
Kevin McKinney6c15e002011-08-15 22:07:41 -04001685 case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION: {
1686 /* Right Now we are taking care of only DSD */
1687 Adapter->bAllDSDWriteAllow = FALSE;
1688 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called");
1689 Status = STATUS_SUCCESS;
1690 }
1691 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001692
Kevin McKinney6c15e002011-08-15 22:07:41 -04001693 case IOCTL_BCM_COPY_SECTION: {
1694 FLASH2X_COPY_SECTION sCopySectStrut = {0};
1695 Status = STATUS_SUCCESS;
1696 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001697
Kevin McKinney6c15e002011-08-15 22:07:41 -04001698 Adapter->bAllDSDWriteAllow = FALSE;
1699 if (IsFlash2x(Adapter) != TRUE) {
1700 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
1701 return -EINVAL;
1702 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001703
Kevin McKinney6c15e002011-08-15 22:07:41 -04001704 Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
1705 if (Status) {
1706 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status);
1707 return Status;
1708 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001709
Kevin McKinney6c15e002011-08-15 22:07:41 -04001710 Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION));
1711 if (Status) {
1712 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status);
1713 return Status;
1714 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001715
Kevin McKinney6c15e002011-08-15 22:07:41 -04001716 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection);
1717 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection);
1718 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset);
1719 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001720
Kevin McKinney6c15e002011-08-15 22:07:41 -04001721 if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == FALSE) {
1722 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection);
1723 return -EINVAL;
1724 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001725
Kevin McKinney6c15e002011-08-15 22:07:41 -04001726 if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == FALSE) {
1727 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection);
1728 return -EINVAL;
1729 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001730
Kevin McKinney6c15e002011-08-15 22:07:41 -04001731 if (sCopySectStrut.SrcSection == sCopySectStrut.DstSection) {
1732 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source and Destination section should be different");
1733 return -EINVAL;
1734 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001735
Kevin McKinney6c15e002011-08-15 22:07:41 -04001736 down(&Adapter->NVMRdmWrmLock);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001737
Kevin McKinney6c15e002011-08-15 22:07:41 -04001738 if ((Adapter->IdleMode == TRUE) ||
1739 (Adapter->bShutStatus == TRUE) ||
1740 (Adapter->bPreparingForLowPowerMode == TRUE)) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001741
Kevin McKinney6c15e002011-08-15 22:07:41 -04001742 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
1743 up(&Adapter->NVMRdmWrmLock);
1744 return -EACCES;
1745 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001746
Kevin McKinney6c15e002011-08-15 22:07:41 -04001747 if (sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) {
1748 if (IsNonCDLessDevice(Adapter)) {
1749 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is Non-CDLess hence won't have ISO !!");
1750 Status = -EINVAL;
1751 } else if (sCopySectStrut.numOfBytes == 0) {
1752 Status = BcmCopyISO(Adapter, sCopySectStrut);
1753 } else {
1754 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Partial Copy of ISO section is not Allowed..");
1755 Status = STATUS_FAILURE;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001756 }
Kevin McKinney6c15e002011-08-15 22:07:41 -04001757 up(&Adapter->NVMRdmWrmLock);
1758 return Status;
1759 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001760
Kevin McKinney6c15e002011-08-15 22:07:41 -04001761 Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection,
1762 sCopySectStrut.DstSection, sCopySectStrut.offset, sCopySectStrut.numOfBytes);
1763 up(&Adapter->NVMRdmWrmLock);
1764 }
1765 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001766
Kevin McKinney6c15e002011-08-15 22:07:41 -04001767 case IOCTL_BCM_GET_FLASH_CS_INFO: {
1768 Status = STATUS_SUCCESS;
1769 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001770
Kevin McKinney6c15e002011-08-15 22:07:41 -04001771 Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
1772 if (Status) {
1773 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
1774 break;
1775 }
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001776
Kevin McKinney6c15e002011-08-15 22:07:41 -04001777 if (Adapter->eNVMType != NVM_FLASH) {
1778 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Connected device does not have flash");
1779 Status = -EINVAL;
1780 break;
1781 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001782
Kevin McKinney6c15e002011-08-15 22:07:41 -04001783 if (IsFlash2x(Adapter) == TRUE) {
1784 if (IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO))
1785 return -EINVAL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001786
Kevin McKinney6c15e002011-08-15 22:07:41 -04001787 if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO)))
1788 return -EFAULT;
1789 } else {
1790 if (IoBuffer.OutputLength < sizeof(FLASH_CS_INFO))
1791 return -EINVAL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001792
Kevin McKinney6c15e002011-08-15 22:07:41 -04001793 if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO)))
1794 return -EFAULT;
1795 }
1796 }
1797 break;
1798
1799 case IOCTL_BCM_SELECT_DSD: {
1800 UINT SectOfset = 0;
1801 FLASH2X_SECTION_VAL eFlash2xSectionVal;
1802 eFlash2xSectionVal = NO_SECTION_VAL;
1803 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called");
1804
1805 if (IsFlash2x(Adapter) != TRUE) {
1806 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map");
1807 return -EINVAL;
1808 }
1809
1810 Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
1811 if (Status) {
1812 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed");
1813 return Status;
1814 }
1815 Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT));
1816 if (Status) {
1817 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed");
1818 return Status;
1819 }
1820
1821 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read Section :%d", eFlash2xSectionVal);
1822 if ((eFlash2xSectionVal != DSD0) &&
1823 (eFlash2xSectionVal != DSD1) &&
1824 (eFlash2xSectionVal != DSD2)) {
1825
1826 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Passed section<%x> is not DSD section", eFlash2xSectionVal);
1827 return STATUS_FAILURE;
1828 }
1829
1830 SectOfset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal);
1831 if (SectOfset == INVALID_OFFSET) {
1832 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal);
1833 return -EINVAL;
1834 }
1835
1836 Adapter->bAllDSDWriteAllow = TRUE;
1837 Adapter->ulFlashCalStart = SectOfset;
1838 Adapter->eActiveDSD = eFlash2xSectionVal;
1839 }
1840 Status = STATUS_SUCCESS;
1841 break;
1842
1843 case IOCTL_BCM_NVM_RAW_READ: {
1844 NVM_READWRITE stNVMRead;
1845 INT NOB ;
1846 INT BuffSize ;
1847 INT ReadOffset = 0;
1848 UINT ReadBytes = 0 ;
1849 PUCHAR pReadBuff;
1850 void __user *OutPutBuff;
1851
1852 if (Adapter->eNVMType != NVM_FLASH) {
1853 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NVM TYPE is not Flash");
1854 return -EINVAL;
1855 }
1856
1857 /* Copy Ioctl Buffer structure */
1858 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) {
1859 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n");
1860 Status = -EFAULT;
1861 break;
1862 }
1863
1864 if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(NVM_READWRITE)))
1865 return -EFAULT;
1866
1867 NOB = stNVMRead.uiNumBytes;
1868 /* In Raw-Read max Buff size : 64MB */
1869
1870 if (NOB > DEFAULT_BUFF_SIZE)
1871 BuffSize = DEFAULT_BUFF_SIZE;
1872 else
1873 BuffSize = NOB;
1874
1875 ReadOffset = stNVMRead.uiOffset;
1876 OutPutBuff = stNVMRead.pBuffer;
1877
1878 pReadBuff = kzalloc(BuffSize , GFP_KERNEL);
1879 if (pReadBuff == NULL) {
1880 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure");
1881 Status = -ENOMEM;
1882 break;
1883 }
1884 down(&Adapter->NVMRdmWrmLock);
1885
1886 if ((Adapter->IdleMode == TRUE) ||
1887 (Adapter->bShutStatus == TRUE) ||
1888 (Adapter->bPreparingForLowPowerMode == TRUE)) {
1889
1890 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n");
1891 kfree(pReadBuff);
1892 up(&Adapter->NVMRdmWrmLock);
1893 return -EACCES;
1894 }
1895
1896 Adapter->bFlashRawRead = TRUE;
1897
1898 while (NOB) {
1899 if (NOB > DEFAULT_BUFF_SIZE)
1900 ReadBytes = DEFAULT_BUFF_SIZE;
1901 else
1902 ReadBytes = NOB;
1903
1904 /* Reading the data from Flash 2.x */
1905 Status = BeceemNVMRead(Adapter, (PUINT)pReadBuff, ReadOffset, ReadBytes);
1906 if (Status) {
1907 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status);
1908 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001909 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001910
Kevin McKinney6c15e002011-08-15 22:07:41 -04001911 BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes);
Stephen Hemmingerada692b2010-11-01 09:26:47 -04001912
Kevin McKinney6c15e002011-08-15 22:07:41 -04001913 Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes);
1914 if (Status) {
1915 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to use failed with status :%d", Status);
1916 break;
1917 }
1918 NOB = NOB - ReadBytes;
1919 if (NOB) {
1920 ReadOffset = ReadOffset + ReadBytes;
1921 OutPutBuff = OutPutBuff + ReadBytes;
1922 }
1923 }
1924 Adapter->bFlashRawRead = FALSE;
1925 up(&Adapter->NVMRdmWrmLock);
1926 kfree(pReadBuff);
1927 break;
1928 }
1929
1930 case IOCTL_BCM_CNTRLMSG_MASK: {
1931 ULONG RxCntrlMsgBitMask = 0;
1932
1933 /* Copy Ioctl Buffer structure */
1934 Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER));
1935 if (Status) {
1936 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space");
1937 Status = -EFAULT;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001938 break;
Kevin McKinney6c15e002011-08-15 22:07:41 -04001939 }
1940
1941 if (IoBuffer.InputLength != sizeof(unsigned long)) {
1942 Status = -EINVAL;
1943 break;
1944 }
1945
1946 Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength);
1947 if (Status) {
1948 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of control bit mask failed from user space");
1949 Status = -EFAULT;
1950 break;
1951 }
1952 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
1953 pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask;
1954 }
1955 break;
1956
1957 case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: {
1958 DEVICE_DRIVER_INFO DevInfo;
1959
1960 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
1961
1962 DevInfo.MaxRDMBufferSize = BUFFER_4K;
1963 DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
1964 DevInfo.u32RxAlignmentCorrection = 0;
1965 DevInfo.u32NVMType = Adapter->eNVMType;
1966 DevInfo.u32InterfaceType = BCM_USB;
1967
1968 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1969 return -EFAULT;
1970
1971 if (IoBuffer.OutputLength < sizeof(DevInfo))
1972 return -EINVAL;
1973
1974 if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo)))
1975 return -EFAULT;
1976 }
1977 break;
1978
1979 case IOCTL_BCM_TIME_SINCE_NET_ENTRY: {
1980 ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0};
1981
1982 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called");
1983
1984 if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)))
1985 return -EFAULT;
1986
1987 if (IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED))
1988 return -EINVAL;
1989
1990 stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry;
1991
1992 if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED)))
1993 return -EFAULT;
1994 }
1995 break;
1996
1997 case IOCTL_CLOSE_NOTIFICATION:
1998 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_CLOSE_NOTIFICATION");
1999 break;
2000
2001 default:
2002 pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd);
2003 Status = STATUS_FAILURE;
2004 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002005 }
2006 return Status;
2007}
2008
2009
Javier Martinez Canillas78acd582011-02-12 04:38:25 +01002010static const struct file_operations bcm_fops = {
Arnd Bergmann9f1c75a2010-09-30 10:24:11 +02002011 .owner = THIS_MODULE,
2012 .open = bcm_char_open,
2013 .release = bcm_char_release,
2014 .read = bcm_char_read,
2015 .unlocked_ioctl = bcm_char_ioctl,
Arnd Bergmannd16044cf2010-09-30 10:24:07 +02002016 .llseek = no_llseek,
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002017};
2018
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002019int register_control_device_interface(PMINI_ADAPTER Adapter)
2020{
Stephen Hemminger9e0a3162010-11-01 10:17:54 -04002021
Javier Martinez Canillas78acd582011-02-12 04:38:25 +01002022 if (Adapter->major > 0)
Stephen Hemminger9e0a3162010-11-01 10:17:54 -04002023 return Adapter->major;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002024
Stephen Hemminger9e0a3162010-11-01 10:17:54 -04002025 Adapter->major = register_chrdev(0, DEV_NAME, &bcm_fops);
Javier Martinez Canillas78acd582011-02-12 04:38:25 +01002026 if (Adapter->major < 0) {
Stephen Hemminger9e0a3162010-11-01 10:17:54 -04002027 pr_err(DRV_NAME ": could not created character device\n");
2028 return Adapter->major;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002029 }
Stephen Hemminger9e0a3162010-11-01 10:17:54 -04002030
Javier Martinez Canillas78acd582011-02-12 04:38:25 +01002031 Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL,
Kevin McKinney6c15e002011-08-15 22:07:41 -04002032 MKDEV(Adapter->major, 0),
2033 Adapter, DEV_NAME);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002034
Javier Martinez Canillas78acd582011-02-12 04:38:25 +01002035 if (IS_ERR(Adapter->pstCreatedClassDevice)) {
Stephen Hemminger9e0a3162010-11-01 10:17:54 -04002036 pr_err(DRV_NAME ": class device create failed\n");
2037 unregister_chrdev(Adapter->major, DEV_NAME);
2038 return PTR_ERR(Adapter->pstCreatedClassDevice);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002039 }
Javier Martinez Canillas78acd582011-02-12 04:38:25 +01002040
Stephen Hemminger9e0a3162010-11-01 10:17:54 -04002041 return 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002042}
2043
2044void unregister_control_device_interface(PMINI_ADAPTER Adapter)
2045{
Javier Martinez Canillas78acd582011-02-12 04:38:25 +01002046 if (Adapter->major > 0) {
2047 device_destroy(bcm_class, MKDEV(Adapter->major, 0));
Stephen Hemminger9e0a3162010-11-01 10:17:54 -04002048 unregister_chrdev(Adapter->major, DEV_NAME);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002049 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07002050}
Kevin McKinney6c15e002011-08-15 22:07:41 -04002051