~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise-security

« back to all changes in this revision

Viewing changes to drivers/staging/westbridge/astoria/block/cyasblkdev_block.c

  • Committer: Package Import Robot
  • Author(s): Paolo Pisati, Paolo Pisati
  • Date: 2011-12-06 15:56:07 UTC
  • Revision ID: package-import@ubuntu.com-20111206155607-pcf44kv5fmhk564f
Tags: 3.2.0-1401.1
[ Paolo Pisati ]

* Rebased on top of Ubuntu-3.2.0-3.8
* Tilt-tracking @ ef2487af4bb15bdd0689631774b5a5e3a59f74e2
* Delete debian.ti-omap4/control, it shoudln't be tracked
* Fix architecture spelling (s/armel/armhf/)
* [Config] Update configs following 3.2 import
* [Config] Fix compilation: disable CODA and ARCH_OMAP3
* [Config] Fix compilation: disable Ethernet Faraday
* Update series to precise

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* cyanblkdev_block.c - West Bridge Linux Block Driver source file
2
 
## ===========================
3
 
## Copyright (C) 2010  Cypress Semiconductor
4
 
##
5
 
## This program is free software; you can redistribute it and/or
6
 
## modify it under the terms of the GNU General Public License
7
 
## as published by the Free Software Foundation; either version 2
8
 
## of the License, or (at your option) any later version.
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., 51 Franklin Street, Fifth Floor
18
 
## Boston, MA  02110-1301, USA.
19
 
## ===========================
20
 
*/
21
 
 
22
 
/*
23
 
 * Linux block driver implementation for Cypress West Bridge.
24
 
 * Based on the mmc block driver implementation by Andrew Christian
25
 
 * for the linux 2.6.26 kernel.
26
 
 * mmc_block.c, 5/28/2002
27
 
 */
28
 
 
29
 
/*
30
 
 * Block driver for media (i.e., flash cards)
31
 
 *
32
 
 * Copyright 2002 Hewlett-Packard Company
33
 
 *
34
 
 * Use consistent with the GNU GPL is permitted,
35
 
 * provided that this copyright notice is
36
 
 * preserved in its entirety in all copies and derived works.
37
 
 *
38
 
 * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
39
 
 * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
40
 
 * FITNESS FOR ANY PARTICULAR PURPOSE.
41
 
 *
42
 
 * Many thanks to Alessandro Rubini and Jonathan Corbet!
43
 
 *
44
 
 * Author:  Andrew Christian
45
 
 *                28 May 2002
46
 
 */
47
 
 
48
 
#include <linux/moduleparam.h>
49
 
#include <linux/module.h>
50
 
#include <linux/init.h>
51
 
#include <linux/slab.h>
52
 
#include <linux/sched.h>
53
 
#include <linux/kernel.h>
54
 
#include <linux/fs.h>
55
 
#include <linux/errno.h>
56
 
#include <linux/hdreg.h>
57
 
#include <linux/kdev_t.h>
58
 
#include <linux/blkdev.h>
59
 
 
60
 
#include <asm/system.h>
61
 
#include <linux/uaccess.h>
62
 
 
63
 
#include <linux/scatterlist.h>
64
 
#include <linux/time.h>
65
 
#include <linux/signal.h>
66
 
#include <linux/delay.h>
67
 
 
68
 
#include "cyasblkdev_queue.h"
69
 
 
70
 
#define CYASBLKDEV_SHIFT        0 /* Only a single partition. */
71
 
#define CYASBLKDEV_MAX_REQ_LEN  (256)
72
 
#define CYASBLKDEV_NUM_MINORS   (256 >> CYASBLKDEV_SHIFT)
73
 
#define CY_AS_TEST_NUM_BLOCKS   (64)
74
 
#define CYASBLKDEV_MINOR_0 1
75
 
#define CYASBLKDEV_MINOR_1 2
76
 
#define CYASBLKDEV_MINOR_2 3
77
 
 
78
 
static int major;
79
 
module_param(major, int, 0444);
80
 
MODULE_PARM_DESC(major,
81
 
        "specify the major device number for cyasblkdev block driver");
82
 
 
83
 
/* parameters passed from the user space */
84
 
static int vfat_search;
85
 
module_param(vfat_search, bool, S_IRUGO | S_IWUSR);
86
 
MODULE_PARM_DESC(vfat_search,
87
 
        "dynamically find the location of the first sector");
88
 
 
89
 
static int private_partition_bus = -1;
90
 
module_param(private_partition_bus, int, S_IRUGO | S_IWUSR);
91
 
MODULE_PARM_DESC(private_partition_bus,
92
 
        "bus number for private partition");
93
 
 
94
 
static int private_partition_size = -1;
95
 
module_param(private_partition_size, int, S_IRUGO | S_IWUSR);
96
 
MODULE_PARM_DESC(private_partition_size,
97
 
        "size of the private partition");
98
 
 
99
 
/*
100
 
 * There is one cyasblkdev_blk_data per slot.
101
 
 */
102
 
struct cyasblkdev_blk_data {
103
 
        spinlock_t        lock;
104
 
        int media_count[2];
105
 
        const struct block_device_operations *blkops;
106
 
        unsigned int    usage;
107
 
        unsigned int    suspended;
108
 
 
109
 
        /* handle to the west bridge device this handle, typdefed as *void  */
110
 
        cy_as_device_handle             dev_handle;
111
 
 
112
 
        /* our custom structure, in addition to request queue,
113
 
         * adds lock & semaphore items*/
114
 
        struct cyasblkdev_queue queue;
115
 
 
116
 
        /* 16 entries is enough given max request size
117
 
         * 16 * 4K (64 K per request)*/
118
 
        struct scatterlist        sg[16];
119
 
 
120
 
        /* non-zero enables printk of executed reqests */
121
 
        unsigned int    dbgprn_flags;
122
 
 
123
 
        /*gen_disk for private, system disk */
124
 
        struct gendisk  *system_disk;
125
 
        cy_as_media_type   system_disk_type;
126
 
        cy_bool                  system_disk_read_only;
127
 
        cy_bool                  system_disk_bus_num;
128
 
 
129
 
        /* sector size for the medium */
130
 
        unsigned int    system_disk_blk_size;
131
 
        unsigned int    system_disk_first_sector;
132
 
        unsigned int    system_disk_unit_no;
133
 
 
134
 
        /*gen_disk for bus 0 */
135
 
        struct gendisk  *user_disk_0;
136
 
        cy_as_media_type   user_disk_0_type;
137
 
        cy_bool                  user_disk_0_read_only;
138
 
        cy_bool                  user_disk_0_bus_num;
139
 
 
140
 
        /* sector size for the medium */
141
 
        unsigned int    user_disk_0_blk_size;
142
 
        unsigned int    user_disk_0_first_sector;
143
 
        unsigned int    user_disk_0_unit_no;
144
 
 
145
 
        /*gen_disk for bus 1 */
146
 
        struct gendisk  *user_disk_1;
147
 
        cy_as_media_type   user_disk_1_type;
148
 
        cy_bool                  user_disk_1_read_only;
149
 
        cy_bool                  user_disk_1_bus_num;
150
 
 
151
 
        /* sector size for the medium */
152
 
        unsigned int    user_disk_1_blk_size;
153
 
        unsigned int    user_disk_1_first_sector;
154
 
        unsigned int    user_disk_1_unit_no;
155
 
};
156
 
 
157
 
/* pointer to west bridge block data device superstructure */
158
 
static struct cyasblkdev_blk_data *gl_bd;
159
 
 
160
 
static DEFINE_SEMAPHORE(open_lock);
161
 
 
162
 
/* local forwardd declarationss  */
163
 
static cy_as_device_handle *cyas_dev_handle;
164
 
static void cyasblkdev_blk_deinit(struct cyasblkdev_blk_data *bd);
165
 
 
166
 
/*change debug print options */
167
 
 #define DBGPRN_RD_RQ      (1 < 0)
168
 
 #define DBGPRN_WR_RQ           (1 < 1)
169
 
 #define DBGPRN_RQ_END    (1 < 2)
170
 
 
171
 
int blkdev_ctl_dbgprn(
172
 
                                                int prn_flags
173
 
                                                )
174
 
{
175
 
        int cur_options = gl_bd->dbgprn_flags;
176
 
 
177
 
        DBGPRN_FUNC_NAME;
178
 
 
179
 
        /* set new debug print options */
180
 
        gl_bd->dbgprn_flags = prn_flags;
181
 
 
182
 
        /* return previous */
183
 
        return cur_options;
184
 
}
185
 
EXPORT_SYMBOL(blkdev_ctl_dbgprn);
186
 
 
187
 
static struct cyasblkdev_blk_data *cyasblkdev_blk_get(
188
 
                                                        struct gendisk *disk
189
 
                                                        )
190
 
{
191
 
        struct cyasblkdev_blk_data *bd;
192
 
 
193
 
        DBGPRN_FUNC_NAME;
194
 
 
195
 
        down(&open_lock);
196
 
 
197
 
        bd = disk->private_data;
198
 
 
199
 
        if (bd && (bd->usage == 0))
200
 
                bd = NULL;
201
 
 
202
 
        if (bd) {
203
 
                bd->usage++;
204
 
                #ifndef NBDEBUG
205
 
                cy_as_hal_print_message(
206
 
                        "cyasblkdev_blk_get: usage = %d\n", bd->usage);
207
 
                #endif
208
 
        }
209
 
        up(&open_lock);
210
 
 
211
 
        return bd;
212
 
}
213
 
 
214
 
static void cyasblkdev_blk_put(
215
 
                        struct cyasblkdev_blk_data *bd
216
 
                        )
217
 
{
218
 
        DBGPRN_FUNC_NAME;
219
 
 
220
 
        down(&open_lock);
221
 
 
222
 
        if (bd) {
223
 
                bd->usage--;
224
 
                #ifndef WESTBRIDGE_NDEBUG
225
 
                cy_as_hal_print_message(
226
 
                        " cyasblkdev_blk_put , bd->usage= %d\n", bd->usage);
227
 
                #endif
228
 
        } else  {
229
 
                #ifndef WESTBRIDGE_NDEBUG
230
 
                cy_as_hal_print_message(
231
 
                        "cyasblkdev: blk_put(bd) on bd = NULL!: usage = %d\n",
232
 
                        bd->usage);
233
 
                #endif
234
 
                up(&open_lock);
235
 
                return;
236
 
        }
237
 
 
238
 
        if (bd->usage == 0) {
239
 
                put_disk(bd->user_disk_0);
240
 
                put_disk(bd->user_disk_1);
241
 
                put_disk(bd->system_disk);
242
 
                cyasblkdev_cleanup_queue(&bd->queue);
243
 
 
244
 
                if (CY_AS_ERROR_SUCCESS !=
245
 
                        cy_as_storage_release(bd->dev_handle, 0, 0, 0, 0)) {
246
 
                        #ifndef WESTBRIDGE_NDEBUG
247
 
                        cy_as_hal_print_message(
248
 
                                "cyasblkdev: cannot release bus 0\n");
249
 
                        #endif
250
 
                }
251
 
 
252
 
                if (CY_AS_ERROR_SUCCESS !=
253
 
                        cy_as_storage_release(bd->dev_handle, 1, 0, 0, 0)) {
254
 
                        #ifndef WESTBRIDGE_NDEBUG
255
 
                        cy_as_hal_print_message(
256
 
                                "cyasblkdev: cannot release bus 1\n");
257
 
                        #endif
258
 
                }
259
 
 
260
 
                if (CY_AS_ERROR_SUCCESS !=
261
 
                        cy_as_storage_stop(bd->dev_handle, 0, 0)) {
262
 
                        #ifndef WESTBRIDGE_NDEBUG
263
 
                        cy_as_hal_print_message(
264
 
                                "cyasblkdev: cannot stop storage stack\n");
265
 
                        #endif
266
 
                }
267
 
 
268
 
        #ifdef __CY_ASTORIA_SCM_KERNEL_HAL__
269
 
                /* If the SCM Kernel HAL is being used, disable the use
270
 
                 * of scatter/gather lists at the end of block driver usage.
271
 
                 */
272
 
                cy_as_hal_disable_scatter_list(cyasdevice_gethaltag());
273
 
        #endif
274
 
 
275
 
                /*ptr to global struct cyasblkdev_blk_data */
276
 
                gl_bd = NULL;
277
 
                kfree(bd);
278
 
        }
279
 
 
280
 
        #ifndef WESTBRIDGE_NDEBUG
281
 
        cy_as_hal_print_message(
282
 
                "cyasblkdev (blk_put): usage = %d\n",
283
 
                bd->usage);
284
 
        #endif
285
 
        up(&open_lock);
286
 
}
287
 
 
288
 
static int cyasblkdev_blk_open(
289
 
                                        struct block_device *bdev,
290
 
                                        fmode_t mode
291
 
                                        )
292
 
{
293
 
        struct cyasblkdev_blk_data *bd = cyasblkdev_blk_get(bdev->bd_disk);
294
 
        int ret = -ENXIO;
295
 
 
296
 
        DBGPRN_FUNC_NAME;
297
 
 
298
 
        if (bd) {
299
 
                if (bd->usage == 2)
300
 
                        check_disk_change(bdev);
301
 
 
302
 
                ret = 0;
303
 
 
304
 
                if (bdev->bd_disk == bd->user_disk_0) {
305
 
                        if ((mode & FMODE_WRITE) && bd->user_disk_0_read_only) {
306
 
                                #ifndef WESTBRIDGE_NDEBUG
307
 
                                cy_as_hal_print_message(
308
 
                                        "device marked as readonly "
309
 
                                        "and write requested\n");
310
 
                                #endif
311
 
 
312
 
                                cyasblkdev_blk_put(bd);
313
 
                                ret = -EROFS;
314
 
                        }
315
 
                } else if (bdev->bd_disk == bd->user_disk_1) {
316
 
                        if ((mode & FMODE_WRITE) && bd->user_disk_1_read_only) {
317
 
                                #ifndef WESTBRIDGE_NDEBUG
318
 
                                cy_as_hal_print_message(
319
 
                                        "device marked as readonly "
320
 
                                        "and write requested\n");
321
 
                                #endif
322
 
 
323
 
                                cyasblkdev_blk_put(bd);
324
 
                                ret = -EROFS;
325
 
                        }
326
 
                } else if (bdev->bd_disk == bd->system_disk) {
327
 
                        if ((mode & FMODE_WRITE) && bd->system_disk_read_only) {
328
 
                                #ifndef WESTBRIDGE_NDEBUG
329
 
                                cy_as_hal_print_message(
330
 
                                        "device marked as readonly "
331
 
                                        "and write requested\n");
332
 
                                #endif
333
 
 
334
 
                                cyasblkdev_blk_put(bd);
335
 
                                ret = -EROFS;
336
 
                        }
337
 
                }
338
 
        }
339
 
 
340
 
        return ret;
341
 
}
342
 
 
343
 
static int cyasblkdev_blk_release(
344
 
                                        struct gendisk *disk,
345
 
                                        fmode_t mode
346
 
                                        )
347
 
{
348
 
        struct cyasblkdev_blk_data *bd = disk->private_data;
349
 
 
350
 
        DBGPRN_FUNC_NAME;
351
 
 
352
 
        cyasblkdev_blk_put(bd);
353
 
        return 0;
354
 
}
355
 
 
356
 
static int cyasblkdev_blk_ioctl(
357
 
                        struct block_device *bdev,
358
 
                        fmode_t mode,
359
 
                        unsigned int cmd,
360
 
                        unsigned long arg
361
 
                        )
362
 
{
363
 
        DBGPRN_FUNC_NAME;
364
 
 
365
 
        if (cmd == HDIO_GETGEO) {
366
 
                /*for now  we only process geometry IOCTL*/
367
 
                struct hd_geometry geo;
368
 
 
369
 
                memset(&geo, 0, sizeof(struct hd_geometry));
370
 
 
371
 
                geo.cylinders   = get_capacity(bdev->bd_disk) / (4 * 16);
372
 
                geo.heads       = 4;
373
 
                geo.sectors     = 16;
374
 
                geo.start       = get_start_sect(bdev);
375
 
 
376
 
                /* copy to user space */
377
 
                return copy_to_user((void __user *)arg, &geo, sizeof(geo))
378
 
                        ? -EFAULT : 0;
379
 
        }
380
 
 
381
 
        return -ENOTTY;
382
 
}
383
 
 
384
 
/* check_events block_device opp
385
 
 * this one is called by kernel to confirm if the media really changed
386
 
 * as we indicated by issuing check_disk_change() call */
387
 
unsigned int cyasblkdev_check_events(struct gendisk *gd, unsigned int clearing)
388
 
{
389
 
        struct cyasblkdev_blk_data *bd;
390
 
 
391
 
        #ifndef WESTBRIDGE_NDEBUG
392
 
        cy_as_hal_print_message("cyasblkdev_media_changed() is called\n");
393
 
        #endif
394
 
 
395
 
        if (gd)
396
 
                bd = gd->private_data;
397
 
        else {
398
 
                #ifndef WESTBRIDGE_NDEBUG
399
 
                cy_as_hal_print_message(
400
 
                        "cyasblkdev_media_changed() is called, "
401
 
                        "but gd is null\n");
402
 
                #endif
403
 
        }
404
 
 
405
 
        /* return media change state - DISK_EVENT_MEDIA_CHANGE yes, 0 no */
406
 
        return 0;
407
 
}
408
 
 
409
 
/*  this one called by kernel to give us a chence
410
 
 * to prep the new media before it starts to rescaning
411
 
 * of the newlly inserted SD media */
412
 
int cyasblkdev_revalidate_disk(struct gendisk *gd)
413
 
{
414
 
        /*int (*revalidate_disk) (struct gendisk *); */
415
 
 
416
 
        #ifndef WESTBRIDGE_NDEBUG
417
 
        if (gd)
418
 
                cy_as_hal_print_message(
419
 
                        "cyasblkdev_revalidate_disk() is called, "
420
 
                        "(gl_bd->usage:%d)\n", gl_bd->usage);
421
 
        #endif
422
 
 
423
 
        /* 0 means ok, kern can go ahead with partition rescan */
424
 
        return 0;
425
 
}
426
 
 
427
 
 
428
 
/*standard block device driver interface */
429
 
static struct block_device_operations cyasblkdev_bdops = {
430
 
        .open                   = cyasblkdev_blk_open,
431
 
        .release                = cyasblkdev_blk_release,
432
 
        .ioctl                  = cyasblkdev_blk_ioctl,
433
 
        /* .getgeo              = cyasblkdev_blk_getgeo, */
434
 
        /* added to support media removal( real and simulated) media */
435
 
        .check_events           = cyasblkdev_check_events,
436
 
        /* added to support media removal( real and simulated) media */
437
 
        .revalidate_disk = cyasblkdev_revalidate_disk,
438
 
        .owner                  = THIS_MODULE,
439
 
};
440
 
 
441
 
/* west bridge block device prep request function */
442
 
static int cyasblkdev_blk_prep_rq(
443
 
                                        struct cyasblkdev_queue *bq,
444
 
                                        struct request *req
445
 
                                        )
446
 
{
447
 
        struct cyasblkdev_blk_data *bd = bq->data;
448
 
        int stat = BLKPREP_OK;
449
 
 
450
 
        DBGPRN_FUNC_NAME;
451
 
 
452
 
        /* If we have no device, we haven't finished initialising. */
453
 
        if (!bd || !bd->dev_handle) {
454
 
                #ifndef WESTBRIDGE_NDEBUG
455
 
                cy_as_hal_print_message(KERN_ERR
456
 
                        "cyasblkdev %s: killing request - no device/host\n",
457
 
                        req->rq_disk->disk_name);
458
 
                #endif
459
 
                stat = BLKPREP_KILL;
460
 
        }
461
 
 
462
 
        if (bd->suspended) {
463
 
                blk_plug_device(bd->queue.queue);
464
 
                stat = BLKPREP_DEFER;
465
 
        }
466
 
 
467
 
        /* Check for excessive requests.*/
468
 
        if (blk_rq_pos(req) + blk_rq_sectors(req) > get_capacity(req->rq_disk)) {
469
 
                cy_as_hal_print_message("cyasblkdev: bad request address\n");
470
 
                stat = BLKPREP_KILL;
471
 
        }
472
 
 
473
 
        return stat;
474
 
}
475
 
 
476
 
/*west bridge storage async api on_completed callback */
477
 
static void cyasblkdev_issuecallback(
478
 
        /* Handle to the device completing the storage operation */
479
 
        cy_as_device_handle handle,
480
 
        /* The media type completing the operation */
481
 
        cy_as_media_type type,
482
 
        /* The device completing the operation */
483
 
        uint32_t device,
484
 
        /* The unit completing the operation */
485
 
        uint32_t unit,
486
 
        /* The block number of the completed operation */
487
 
        uint32_t block_number,
488
 
        /* The type of operation */
489
 
        cy_as_oper_type op,
490
 
        /* The error status */
491
 
        cy_as_return_status_t status
492
 
        )
493
 
{
494
 
        int retry_cnt = 0;
495
 
        DBGPRN_FUNC_NAME;
496
 
 
497
 
        if (status != CY_AS_ERROR_SUCCESS) {
498
 
                #ifndef WESTBRIDGE_NDEBUG
499
 
                cy_as_hal_print_message(
500
 
                  "%s: async r/w: op:%d failed with error %d at address %d\n",
501
 
                        __func__, op, status, block_number);
502
 
                #endif
503
 
        }
504
 
 
505
 
        #ifndef WESTBRIDGE_NDEBUG
506
 
        cy_as_hal_print_message(
507
 
                "%s calling blk_end_request from issue_callback "
508
 
                "req=0x%x, status=0x%x, nr_sectors=0x%x\n",
509
 
                __func__, (unsigned int) gl_bd->queue.req, status,
510
 
                (unsigned int) blk_rq_sectors(gl_bd->queue.req));
511
 
        #endif
512
 
 
513
 
        /* note: blk_end_request w/o __ prefix should
514
 
         * not require spinlocks on the queue*/
515
 
        while (blk_end_request(gl_bd->queue.req,
516
 
        status, blk_rq_sectors(gl_bd->queue.req)*512)) {
517
 
                retry_cnt++;
518
 
        }
519
 
 
520
 
        #ifndef WESTBRIDGE_NDEBUG
521
 
        cy_as_hal_print_message(
522
 
                "%s blkdev_callback: ended rq on %d sectors, "
523
 
                "with err:%d, n:%d times\n", __func__,
524
 
                (int)blk_rq_sectors(gl_bd->queue.req), status,
525
 
                retry_cnt
526
 
        );
527
 
        #endif
528
 
 
529
 
        spin_lock_irq(&gl_bd->lock);
530
 
 
531
 
        /*elevate next request, if there is one*/
532
 
        if (!blk_queue_plugged(gl_bd->queue.queue)) {
533
 
                /* queue is not plugged */
534
 
                gl_bd->queue.req = blk_fetch_request(gl_bd->queue.queue);
535
 
                #ifndef WESTBRIDGE_NDEBUG
536
 
                cy_as_hal_print_message("%s blkdev_callback: "
537
 
                "blk_fetch_request():%p\n",
538
 
                        __func__, gl_bd->queue.req);
539
 
                #endif
540
 
        }
541
 
 
542
 
        if (gl_bd->queue.req) {
543
 
                spin_unlock_irq(&gl_bd->lock);
544
 
 
545
 
                #ifndef WESTBRIDGE_NDEBUG
546
 
                cy_as_hal_print_message("%s blkdev_callback: about to "
547
 
                "call issue_fn:%p\n", __func__, gl_bd->queue.req);
548
 
                #endif
549
 
 
550
 
                gl_bd->queue.issue_fn(&gl_bd->queue, gl_bd->queue.req);
551
 
        } else {
552
 
                spin_unlock_irq(&gl_bd->lock);
553
 
        }
554
 
}
555
 
 
556
 
/* issue astoria blkdev request (issue_fn) */
557
 
static int cyasblkdev_blk_issue_rq(
558
 
                                        struct cyasblkdev_queue *bq,
559
 
                                        struct request *req
560
 
                                        )
561
 
{
562
 
        struct cyasblkdev_blk_data *bd = bq->data;
563
 
        int index = 0;
564
 
        int ret = CY_AS_ERROR_SUCCESS;
565
 
        uint32_t req_sector = 0;
566
 
        uint32_t req_nr_sectors = 0;
567
 
        int bus_num = 0;
568
 
        int lcl_unit_no = 0;
569
 
 
570
 
        DBGPRN_FUNC_NAME;
571
 
 
572
 
        /*
573
 
         * will construct a scatterlist for the given request;
574
 
         * the return value is the number of actually used
575
 
         * entries in the resulting list. Then, this scatterlist
576
 
         * can be used for the actual DMA prep operation.
577
 
         */
578
 
        spin_lock_irq(&bd->lock);
579
 
        index = blk_rq_map_sg(bq->queue, req, bd->sg);
580
 
 
581
 
        if (req->rq_disk == bd->user_disk_0) {
582
 
                bus_num = bd->user_disk_0_bus_num;
583
 
                req_sector = blk_rq_pos(req) + gl_bd->user_disk_0_first_sector;
584
 
                req_nr_sectors = blk_rq_sectors(req);
585
 
                lcl_unit_no = gl_bd->user_disk_0_unit_no;
586
 
 
587
 
                #ifndef WESTBRIDGE_NDEBUG
588
 
                cy_as_hal_print_message("%s: request made to disk 0 "
589
 
                        "for sector=%d, num_sectors=%d, unit_no=%d\n",
590
 
                        __func__, req_sector, (int) blk_rq_sectors(req),
591
 
                        lcl_unit_no);
592
 
                #endif
593
 
        } else if (req->rq_disk == bd->user_disk_1) {
594
 
                bus_num = bd->user_disk_1_bus_num;
595
 
                req_sector = blk_rq_pos(req) + gl_bd->user_disk_1_first_sector;
596
 
                /*SECT_NUM_TRANSLATE(blk_rq_sectors(req));*/
597
 
                req_nr_sectors = blk_rq_sectors(req);
598
 
                lcl_unit_no = gl_bd->user_disk_1_unit_no;
599
 
 
600
 
                #ifndef WESTBRIDGE_NDEBUG
601
 
                cy_as_hal_print_message("%s: request made to disk 1 for "
602
 
                        "sector=%d, num_sectors=%d, unit_no=%d\n", __func__,
603
 
                        req_sector, (int) blk_rq_sectors(req), lcl_unit_no);
604
 
                #endif
605
 
        } else if (req->rq_disk == bd->system_disk) {
606
 
                bus_num = bd->system_disk_bus_num;
607
 
                req_sector = blk_rq_pos(req) + gl_bd->system_disk_first_sector;
608
 
                req_nr_sectors = blk_rq_sectors(req);
609
 
                lcl_unit_no = gl_bd->system_disk_unit_no;
610
 
 
611
 
                #ifndef WESTBRIDGE_NDEBUG
612
 
                cy_as_hal_print_message("%s: request made to system disk "
613
 
                        "for sector=%d, num_sectors=%d, unit_no=%d\n", __func__,
614
 
                        req_sector, (int) blk_rq_sectors(req), lcl_unit_no);
615
 
                #endif
616
 
        }
617
 
        #ifndef WESTBRIDGE_NDEBUG
618
 
        else {
619
 
                cy_as_hal_print_message(
620
 
                        "%s: invalid disk used for request\n", __func__);
621
 
        }
622
 
        #endif
623
 
 
624
 
        spin_unlock_irq(&bd->lock);
625
 
 
626
 
        if (rq_data_dir(req) == READ) {
627
 
                #ifndef WESTBRIDGE_NDEBUG
628
 
                cy_as_hal_print_message("%s: calling readasync() "
629
 
                        "req_sector=0x%x, req_nr_sectors=0x%x, bd->sg:%x\n\n",
630
 
                        __func__, req_sector, req_nr_sectors, (uint32_t)bd->sg);
631
 
                #endif
632
 
 
633
 
                ret = cy_as_storage_read_async(bd->dev_handle, bus_num, 0,
634
 
                        lcl_unit_no, req_sector, bd->sg, req_nr_sectors,
635
 
                        (cy_as_storage_callback)cyasblkdev_issuecallback);
636
 
 
637
 
                if (ret != CY_AS_ERROR_SUCCESS) {
638
 
                        #ifndef WESTBRIDGE_NDEBUG
639
 
                        cy_as_hal_print_message("%s:readasync() error %d at "
640
 
                                "address %ld, unit no %d\n", __func__, ret,
641
 
                                blk_rq_pos(req), lcl_unit_no);
642
 
                        cy_as_hal_print_message("%s:ending i/o request "
643
 
                                "on reg:%x\n", __func__, (uint32_t)req);
644
 
                        #endif
645
 
 
646
 
                        while (blk_end_request(req,
647
 
                                (ret == CY_AS_ERROR_SUCCESS),
648
 
                                req_nr_sectors*512))
649
 
                                ;
650
 
 
651
 
                        bq->req = NULL;
652
 
                }
653
 
        } else {
654
 
                ret = cy_as_storage_write_async(bd->dev_handle, bus_num, 0,
655
 
                        lcl_unit_no, req_sector, bd->sg, req_nr_sectors,
656
 
                        (cy_as_storage_callback)cyasblkdev_issuecallback);
657
 
 
658
 
                if (ret != CY_AS_ERROR_SUCCESS) {
659
 
                        #ifndef WESTBRIDGE_NDEBUG
660
 
                        cy_as_hal_print_message("%s: write failed with "
661
 
                        "error %d at address %ld, unit no %d\n",
662
 
                        __func__, ret, blk_rq_pos(req), lcl_unit_no);
663
 
                        #endif
664
 
 
665
 
                        /*end IO op on this request(does both
666
 
                         * end_that_request_... _first & _last) */
667
 
                        while (blk_end_request(req,
668
 
                                (ret == CY_AS_ERROR_SUCCESS),
669
 
                                req_nr_sectors*512))
670
 
                                ;
671
 
 
672
 
                        bq->req = NULL;
673
 
                }
674
 
        }
675
 
 
676
 
        return ret;
677
 
}
678
 
 
679
 
static unsigned long
680
 
dev_use[CYASBLKDEV_NUM_MINORS / (8 * sizeof(unsigned long))];
681
 
 
682
 
 
683
 
/* storage event callback (note: called in astoria isr context) */
684
 
static void cyasblkdev_storage_callback(
685
 
                                        cy_as_device_handle dev_h,
686
 
                                        cy_as_bus_number_t bus,
687
 
                                        uint32_t device,
688
 
                                        cy_as_storage_event evtype,
689
 
                                        void *evdata
690
 
                                        )
691
 
{
692
 
        #ifndef WESTBRIDGE_NDEBUG
693
 
        cy_as_hal_print_message("%s: bus:%d, device:%d, evtype:%d, "
694
 
        "evdata:%p\n ", __func__, bus, device, evtype, evdata);
695
 
        #endif
696
 
 
697
 
        switch (evtype) {
698
 
        case cy_as_storage_processor:
699
 
                break;
700
 
 
701
 
        case cy_as_storage_removed:
702
 
                break;
703
 
 
704
 
        case cy_as_storage_inserted:
705
 
                break;
706
 
 
707
 
        default:
708
 
                break;
709
 
        }
710
 
}
711
 
 
712
 
#define SECTORS_TO_SCAN 4096
713
 
 
714
 
uint32_t cyasblkdev_get_vfat_offset(int bus_num, int unit_no)
715
 
{
716
 
        /*
717
 
         * for sd media, vfat partition boot record is not always
718
 
         * located at sector it greatly depends on the system and
719
 
         * software that was used to format the sd however, linux
720
 
         * fs layer always expects it at sector 0, this function
721
 
         * finds the offset and then uses it in all media r/w
722
 
         * operations
723
 
         */
724
 
        int sect_no, stat;
725
 
        uint8_t *sect_buf;
726
 
        bool br_found = false;
727
 
 
728
 
        DBGPRN_FUNC_NAME;
729
 
 
730
 
        sect_buf = kmalloc(1024, GFP_KERNEL);
731
 
 
732
 
        /* since HAL layer always uses sg lists instead of the
733
 
         * buffer (for hw dmas) we need to initialize the sg list
734
 
         * for local buffer*/
735
 
        sg_init_one(gl_bd->sg, sect_buf, 512);
736
 
 
737
 
        /*
738
 
        * Check MPR partition table 1st, then try to scan through
739
 
        * 1st 384 sectors until BR signature(intel JMP istruction
740
 
        * code and ,0x55AA) is found
741
 
        */
742
 
        #ifndef WESTBRIDGE_NDEBUG
743
 
          cy_as_hal_print_message(
744
 
                "%s scanning media for vfat partition...\n", __func__);
745
 
        #endif
746
 
 
747
 
        for (sect_no = 0; sect_no < SECTORS_TO_SCAN; sect_no++) {
748
 
                #ifndef WESTBRIDGE_NDEBUG
749
 
                cy_as_hal_print_message("%s before cyasstorageread "
750
 
                        "gl_bd->sg addr=0x%x\n", __func__,
751
 
                        (unsigned int) gl_bd->sg);
752
 
                #endif
753
 
 
754
 
                stat = cy_as_storage_read(
755
 
                        /* Handle to the device of interest */
756
 
                        gl_bd->dev_handle,
757
 
                        /* The bus to access */
758
 
                        bus_num,
759
 
                        /* The device to access */
760
 
                        0,
761
 
                        /* The unit to access */
762
 
                        unit_no,
763
 
                        /* absolute sector number */
764
 
                        sect_no,
765
 
                        /* sg structure */
766
 
                        gl_bd->sg,
767
 
                        /* The number of blocks to be read */
768
 
                        1
769
 
                );
770
 
 
771
 
                /* try only sectors with boot signature */
772
 
                if ((sect_buf[510] == 0x55) && (sect_buf[511] == 0xaa)) {
773
 
                        /* vfat boot record may also be located at
774
 
                         * sector 0, check it first  */
775
 
                        if (sect_buf[0] == 0xEB) {
776
 
                                #ifndef WESTBRIDGE_NDEBUG
777
 
                                cy_as_hal_print_message(
778
 
                                        "%s vfat partition found "
779
 
                                        "at sector:%d\n",
780
 
                                        __func__, sect_no);
781
 
                                #endif
782
 
 
783
 
                                br_found = true;
784
 
                                   break;
785
 
                        }
786
 
                }
787
 
 
788
 
                if (stat != 0) {
789
 
                        #ifndef WESTBRIDGE_NDEBUG
790
 
                        cy_as_hal_print_message("%s sector scan error\n",
791
 
                                __func__);
792
 
                        #endif
793
 
                        break;
794
 
                }
795
 
        }
796
 
 
797
 
        kfree(sect_buf);
798
 
 
799
 
        if (br_found) {
800
 
                return sect_no;
801
 
        } else {
802
 
                #ifndef WESTBRIDGE_NDEBUG
803
 
                cy_as_hal_print_message(
804
 
                        "%s vfat partition is not found, using 0 offset\n",
805
 
                        __func__);
806
 
                #endif
807
 
                return 0;
808
 
        }
809
 
}
810
 
 
811
 
cy_as_storage_query_device_data dev_data = {0};
812
 
 
813
 
static int cyasblkdev_add_disks(int bus_num,
814
 
        struct cyasblkdev_blk_data *bd,
815
 
        int total_media_count,
816
 
        int devidx)
817
 
{
818
 
        int ret = 0;
819
 
        uint64_t disk_cap;
820
 
        int lcl_unit_no;
821
 
        cy_as_storage_query_unit_data unit_data = {0};
822
 
 
823
 
        #ifndef WESTBRIDGE_NDEBUG
824
 
                cy_as_hal_print_message("%s:query device: "
825
 
                "type:%d, removable:%d, writable:%d, "
826
 
                "blksize %d, units:%d, locked:%d, "
827
 
                "erase_sz:%d\n",
828
 
                __func__,
829
 
                dev_data.desc_p.type,
830
 
                dev_data.desc_p.removable,
831
 
                dev_data.desc_p.writeable,
832
 
                dev_data.desc_p.block_size,
833
 
                dev_data.desc_p.number_units,
834
 
                dev_data.desc_p.locked,
835
 
                dev_data.desc_p.erase_unit_size
836
 
                );
837
 
        #endif
838
 
 
839
 
        /*  make sure that device is not locked  */
840
 
        if (dev_data.desc_p.locked) {
841
 
                #ifndef WESTBRIDGE_NDEBUG
842
 
                cy_as_hal_print_message(
843
 
                        "%s: device is locked\n", __func__);
844
 
                #endif
845
 
                ret = cy_as_storage_release(
846
 
                        bd->dev_handle, bus_num, 0, 0, 0);
847
 
                if (ret != CY_AS_ERROR_SUCCESS) {
848
 
                        #ifndef WESTBRIDGE_NDEBUG
849
 
                        cy_as_hal_print_message("%s cannot release"
850
 
                                " storage\n", __func__);
851
 
                        #endif
852
 
                        goto out;
853
 
                }
854
 
                goto out;
855
 
        }
856
 
 
857
 
        unit_data.device = 0;
858
 
        unit_data.unit   = 0;
859
 
        unit_data.bus    = bus_num;
860
 
        ret = cy_as_storage_query_unit(bd->dev_handle,
861
 
                &unit_data, 0, 0);
862
 
        if (ret != CY_AS_ERROR_SUCCESS) {
863
 
                #ifndef WESTBRIDGE_NDEBUG
864
 
                cy_as_hal_print_message("%s: cannot query "
865
 
                        "%d device unit - reason code %d\n",
866
 
                        __func__, bus_num, ret);
867
 
                #endif
868
 
                goto out;
869
 
        }
870
 
 
871
 
        if (private_partition_bus == bus_num) {
872
 
                if (private_partition_size > 0) {
873
 
                        ret = cy_as_storage_create_p_partition(
874
 
                                bd->dev_handle, bus_num, 0,
875
 
                                private_partition_size, 0, 0);
876
 
                        if ((ret != CY_AS_ERROR_SUCCESS) &&
877
 
                        (ret != CY_AS_ERROR_ALREADY_PARTITIONED)) {
878
 
                        #ifndef WESTBRIDGE_NDEBUG
879
 
                                cy_as_hal_print_message("%s: cy_as_storage_"
880
 
                                "create_p_partition after size > 0 check "
881
 
                                "failed with error code %d\n",
882
 
                                __func__, ret);
883
 
                        #endif
884
 
 
885
 
                                disk_cap = (uint64_t)
886
 
                                        (unit_data.desc_p.unit_size);
887
 
                                lcl_unit_no = 0;
888
 
 
889
 
                        } else if (ret == CY_AS_ERROR_ALREADY_PARTITIONED) {
890
 
                                #ifndef WESTBRIDGE_NDEBUG
891
 
                                cy_as_hal_print_message(
892
 
                                "%s: cy_as_storage_create_p_partition "
893
 
                                "indicates memory already partitioned\n",
894
 
                                __func__);
895
 
                                #endif
896
 
 
897
 
                                /*check to see that partition
898
 
                                 * matches size */
899
 
                                if (unit_data.desc_p.unit_size !=
900
 
                                        private_partition_size) {
901
 
                                        ret = cy_as_storage_remove_p_partition(
902
 
                                                bd->dev_handle,
903
 
                                                bus_num, 0, 0, 0);
904
 
                                        if (ret == CY_AS_ERROR_SUCCESS) {
905
 
                                                ret = cy_as_storage_create_p_partition(
906
 
                                                        bd->dev_handle, bus_num, 0,
907
 
                                                        private_partition_size, 0, 0);
908
 
                                                if (ret == CY_AS_ERROR_SUCCESS) {
909
 
                                                        unit_data.bus = bus_num;
910
 
                                                        unit_data.device = 0;
911
 
                                                        unit_data.unit = 1;
912
 
                                                } else {
913
 
                                                        #ifndef WESTBRIDGE_NDEBUG
914
 
                                                        cy_as_hal_print_message(
915
 
                                                        "%s: cy_as_storage_create_p_partition "
916
 
                                                        "after removal unexpectedly failed "
917
 
                                                        "with error %d\n", __func__, ret);
918
 
                                                        #endif
919
 
 
920
 
                                                        /* need to requery bus
921
 
                                                         * seeing as delete
922
 
                                                         * successful and create
923
 
                                                         * failed we have changed
924
 
                                                         * the disk properties */
925
 
                                                        unit_data.bus   = bus_num;
926
 
                                                        unit_data.device = 0;
927
 
                                                        unit_data.unit   = 0;
928
 
                                                }
929
 
 
930
 
                                                ret = cy_as_storage_query_unit(
931
 
                                                bd->dev_handle,
932
 
                                                &unit_data, 0, 0);
933
 
                                                if (ret != CY_AS_ERROR_SUCCESS) {
934
 
                                                        #ifndef WESTBRIDGE_NDEBUG
935
 
                                                        cy_as_hal_print_message(
936
 
                                                        "%s: cannot query %d "
937
 
                                                        "device unit - reason code %d\n",
938
 
                                                        __func__, bus_num, ret);
939
 
                                                        #endif
940
 
                                                        goto out;
941
 
                                                } else {
942
 
                                                        disk_cap = (uint64_t)
943
 
                                                                (unit_data.desc_p.unit_size);
944
 
                                                        lcl_unit_no =
945
 
                                                                unit_data.unit;
946
 
                                                }
947
 
                                        } else {
948
 
                                        #ifndef WESTBRIDGE_NDEBUG
949
 
                                        cy_as_hal_print_message(
950
 
                                        "%s: cy_as_storage_remove_p_partition "
951
 
                                        "failed with error %d\n",
952
 
                                        __func__, ret);
953
 
                                        #endif
954
 
 
955
 
                                                unit_data.bus = bus_num;
956
 
                                                unit_data.device = 0;
957
 
                                                unit_data.unit = 1;
958
 
 
959
 
                                                ret = cy_as_storage_query_unit(
960
 
                                                        bd->dev_handle, &unit_data, 0, 0);
961
 
                                                if (ret != CY_AS_ERROR_SUCCESS) {
962
 
                                                #ifndef WESTBRIDGE_NDEBUG
963
 
                                                        cy_as_hal_print_message(
964
 
                                                        "%s: cannot query %d "
965
 
                                                        "device unit - reason "
966
 
                                                        "code %d\n", __func__,
967
 
                                                        bus_num, ret);
968
 
                                                #endif
969
 
                                                        goto out;
970
 
                                                }
971
 
 
972
 
                                                disk_cap = (uint64_t)
973
 
                                                        (unit_data.desc_p.unit_size);
974
 
                                                lcl_unit_no =
975
 
                                                        unit_data.unit;
976
 
                                        }
977
 
                                } else {
978
 
                                        #ifndef WESTBRIDGE_NDEBUG
979
 
                                        cy_as_hal_print_message("%s: partition "
980
 
                                                "exists and sizes equal\n",
981
 
                                                __func__);
982
 
                                        #endif
983
 
 
984
 
                                        /*partition already existed,
985
 
                                         * need to query second unit*/
986
 
                                        unit_data.bus = bus_num;
987
 
                                        unit_data.device = 0;
988
 
                                        unit_data.unit = 1;
989
 
 
990
 
                                        ret = cy_as_storage_query_unit(
991
 
                                                bd->dev_handle, &unit_data, 0, 0);
992
 
                                        if (ret != CY_AS_ERROR_SUCCESS) {
993
 
                                        #ifndef WESTBRIDGE_NDEBUG
994
 
                                                cy_as_hal_print_message(
995
 
                                                        "%s: cannot query %d "
996
 
                                                        "device unit "
997
 
                                                        "- reason code %d\n",
998
 
                                                        __func__, bus_num, ret);
999
 
                                        #endif
1000
 
                                                goto out;
1001
 
                                        } else {
1002
 
                                                disk_cap = (uint64_t)
1003
 
                                                (unit_data.desc_p.unit_size);
1004
 
                                                lcl_unit_no = unit_data.unit;
1005
 
                                        }
1006
 
                                }
1007
 
                        } else {
1008
 
                                #ifndef WESTBRIDGE_NDEBUG
1009
 
                                cy_as_hal_print_message(
1010
 
                                "%s: cy_as_storage_create_p_partition "
1011
 
                                "created successfully\n", __func__);
1012
 
                                #endif
1013
 
 
1014
 
                                disk_cap = (uint64_t)
1015
 
                                (unit_data.desc_p.unit_size -
1016
 
                                private_partition_size);
1017
 
 
1018
 
                                lcl_unit_no = 1;
1019
 
                        }
1020
 
                }
1021
 
                #ifndef WESTBRIDGE_NDEBUG
1022
 
                else {
1023
 
                        cy_as_hal_print_message(
1024
 
                        "%s: invalid partition_size%d\n", __func__,
1025
 
                        private_partition_size);
1026
 
 
1027
 
                        disk_cap = (uint64_t)
1028
 
                                (unit_data.desc_p.unit_size);
1029
 
                        lcl_unit_no = 0;
1030
 
                }
1031
 
                #endif
1032
 
        } else {
1033
 
                disk_cap = (uint64_t)
1034
 
                        (unit_data.desc_p.unit_size);
1035
 
                lcl_unit_no = 0;
1036
 
        }
1037
 
 
1038
 
        if ((bus_num == 0) ||
1039
 
                (total_media_count == 1)) {
1040
 
                sprintf(bd->user_disk_0->disk_name,
1041
 
                        "cyasblkdevblk%d", devidx);
1042
 
 
1043
 
                #ifndef WESTBRIDGE_NDEBUG
1044
 
                cy_as_hal_print_message(
1045
 
                        "%s: disk unit_sz:%lu blk_sz:%d, "
1046
 
                        "start_blk:%lu, capacity:%llu\n",
1047
 
                        __func__, (unsigned long)
1048
 
                        unit_data.desc_p.unit_size,
1049
 
                        unit_data.desc_p.block_size,
1050
 
                        (unsigned long)
1051
 
                        unit_data.desc_p.start_block,
1052
 
                        (uint64_t)disk_cap
1053
 
                );
1054
 
                #endif
1055
 
 
1056
 
                #ifndef WESTBRIDGE_NDEBUG
1057
 
                cy_as_hal_print_message("%s: setting gendisk disk "
1058
 
                        "capacity to %d\n", __func__, (int) disk_cap);
1059
 
                #endif
1060
 
 
1061
 
                /* initializing bd->queue */
1062
 
                #ifndef WESTBRIDGE_NDEBUG
1063
 
                cy_as_hal_print_message("%s: init bd->queue\n",
1064
 
                        __func__);
1065
 
                #endif
1066
 
 
1067
 
                /* this will create a
1068
 
                 * queue kernel thread */
1069
 
                cyasblkdev_init_queue(
1070
 
                        &bd->queue, &bd->lock);
1071
 
 
1072
 
                bd->queue.prep_fn = cyasblkdev_blk_prep_rq;
1073
 
                bd->queue.issue_fn = cyasblkdev_blk_issue_rq;
1074
 
                bd->queue.data = bd;
1075
 
 
1076
 
                /*blk_size should always
1077
 
                 * be a multiple of 512,
1078
 
                 * set to the max to ensure
1079
 
                 * that all accesses aligned
1080
 
                 * to the greatest multiple,
1081
 
                 * can adjust request to
1082
 
                 * smaller block sizes
1083
 
                 * dynamically*/
1084
 
 
1085
 
                bd->user_disk_0_read_only = !dev_data.desc_p.writeable;
1086
 
                bd->user_disk_0_blk_size = dev_data.desc_p.block_size;
1087
 
                bd->user_disk_0_type = dev_data.desc_p.type;
1088
 
                bd->user_disk_0_bus_num = bus_num;
1089
 
                bd->user_disk_0->major = major;
1090
 
                bd->user_disk_0->first_minor = devidx << CYASBLKDEV_SHIFT;
1091
 
                bd->user_disk_0->minors = 8;
1092
 
                bd->user_disk_0->fops = &cyasblkdev_bdops;
1093
 
                bd->user_disk_0->events = DISK_EVENT_MEDIA_CHANGE;
1094
 
                bd->user_disk_0->private_data = bd;
1095
 
                bd->user_disk_0->queue = bd->queue.queue;
1096
 
                bd->dbgprn_flags = DBGPRN_RD_RQ;
1097
 
                bd->user_disk_0_unit_no = lcl_unit_no;
1098
 
 
1099
 
                blk_queue_logical_block_size(bd->queue.queue,
1100
 
                        bd->user_disk_0_blk_size);
1101
 
 
1102
 
                set_capacity(bd->user_disk_0,
1103
 
                        disk_cap);
1104
 
 
1105
 
                #ifndef WESTBRIDGE_NDEBUG
1106
 
                cy_as_hal_print_message(
1107
 
                        "%s: returned from set_capacity %d\n",
1108
 
                        __func__, (int) disk_cap);
1109
 
                #endif
1110
 
 
1111
 
                /* need to start search from
1112
 
                 * public partition beginning */
1113
 
                if (vfat_search) {
1114
 
                        bd->user_disk_0_first_sector =
1115
 
                                cyasblkdev_get_vfat_offset(
1116
 
                                        bd->user_disk_0_bus_num,
1117
 
                                        bd->user_disk_0_unit_no);
1118
 
                } else {
1119
 
                        bd->user_disk_0_first_sector = 0;
1120
 
                }
1121
 
 
1122
 
                #ifndef WESTBRIDGE_NDEBUG
1123
 
                cy_as_hal_print_message(
1124
 
                        "%s: set user_disk_0_first "
1125
 
                        "sector to %d\n", __func__,
1126
 
                         bd->user_disk_0_first_sector);
1127
 
                cy_as_hal_print_message(
1128
 
                        "%s: add_disk: disk->major=0x%x\n",
1129
 
                        __func__,
1130
 
                        bd->user_disk_0->major);
1131
 
                cy_as_hal_print_message(
1132
 
                        "%s: add_disk: "
1133
 
                        "disk->first_minor=0x%x\n", __func__,
1134
 
                        bd->user_disk_0->first_minor);
1135
 
                cy_as_hal_print_message(
1136
 
                        "%s: add_disk: "
1137
 
                        "disk->minors=0x%x\n", __func__,
1138
 
                        bd->user_disk_0->minors);
1139
 
                cy_as_hal_print_message(
1140
 
                        "%s: add_disk: "
1141
 
                        "disk->disk_name=%s\n",
1142
 
                        __func__,
1143
 
                        bd->user_disk_0->disk_name);
1144
 
                cy_as_hal_print_message(
1145
 
                        "%s: add_disk: "
1146
 
                        "disk->part_tbl=0x%x\n", __func__,
1147
 
                        (unsigned int)
1148
 
                        bd->user_disk_0->part_tbl);
1149
 
                cy_as_hal_print_message(
1150
 
                        "%s: add_disk: "
1151
 
                        "disk->queue=0x%x\n", __func__,
1152
 
                        (unsigned int)
1153
 
                        bd->user_disk_0->queue);
1154
 
                cy_as_hal_print_message(
1155
 
                        "%s: add_disk: "
1156
 
                        "disk->flags=0x%x\n",
1157
 
                        __func__, (unsigned int)
1158
 
                        bd->user_disk_0->flags);
1159
 
                cy_as_hal_print_message(
1160
 
                        "%s: add_disk: "
1161
 
                        "disk->driverfs_dev=0x%x\n",
1162
 
                        __func__, (unsigned int)
1163
 
                        bd->user_disk_0->driverfs_dev);
1164
 
                cy_as_hal_print_message(
1165
 
                        "%s: add_disk: "
1166
 
                        "disk->slave_dir=0x%x\n",
1167
 
                        __func__, (unsigned int)
1168
 
                        bd->user_disk_0->slave_dir);
1169
 
                cy_as_hal_print_message(
1170
 
                        "%s: add_disk: "
1171
 
                        "disk->random=0x%x\n",
1172
 
                        __func__, (unsigned int)
1173
 
                        bd->user_disk_0->random);
1174
 
                cy_as_hal_print_message(
1175
 
                        "%s: add_disk: "
1176
 
                        "disk->node_id=0x%x\n",
1177
 
                        __func__, (unsigned int)
1178
 
                        bd->user_disk_0->node_id);
1179
 
 
1180
 
                #endif
1181
 
 
1182
 
                add_disk(bd->user_disk_0);
1183
 
 
1184
 
        } else if ((bus_num == 1) &&
1185
 
                (total_media_count == 2)) {
1186
 
                bd->user_disk_1_read_only = !dev_data.desc_p.writeable;
1187
 
                bd->user_disk_1_blk_size = dev_data.desc_p.block_size;
1188
 
                bd->user_disk_1_type = dev_data.desc_p.type;
1189
 
                bd->user_disk_1_bus_num = bus_num;
1190
 
                bd->user_disk_1->major  = major;
1191
 
                bd->user_disk_1->first_minor = (devidx + 1) << CYASBLKDEV_SHIFT;
1192
 
                bd->user_disk_1->minors = 8;
1193
 
                bd->user_disk_1->fops = &cyasblkdev_bdops;
1194
 
                bd->user_disk_1->events = DISK_EVENT_MEDIA_CHANGE;
1195
 
                bd->user_disk_1->private_data = bd;
1196
 
                bd->user_disk_1->queue = bd->queue.queue;
1197
 
                bd->dbgprn_flags = DBGPRN_RD_RQ;
1198
 
                bd->user_disk_1_unit_no = lcl_unit_no;
1199
 
 
1200
 
                sprintf(bd->user_disk_1->disk_name,
1201
 
                        "cyasblkdevblk%d", (devidx + 1));
1202
 
 
1203
 
                #ifndef WESTBRIDGE_NDEBUG
1204
 
                cy_as_hal_print_message(
1205
 
                        "%s: disk unit_sz:%lu "
1206
 
                        "blk_sz:%d, "
1207
 
                        "start_blk:%lu, "
1208
 
                        "capacity:%llu\n",
1209
 
                        __func__,
1210
 
                        (unsigned long)
1211
 
                        unit_data.desc_p.unit_size,
1212
 
                        unit_data.desc_p.block_size,
1213
 
                        (unsigned long)
1214
 
                        unit_data.desc_p.start_block,
1215
 
                        (uint64_t)disk_cap
1216
 
                );
1217
 
                #endif
1218
 
 
1219
 
                /*blk_size should always be a
1220
 
                 * multiple of 512, set to the max
1221
 
                 * to ensure that all accesses
1222
 
                 * aligned to the greatest multiple,
1223
 
                 * can adjust request to smaller
1224
 
                 * block sizes dynamically*/
1225
 
                if (bd->user_disk_0_blk_size >
1226
 
                bd->user_disk_1_blk_size) {
1227
 
                        blk_queue_logical_block_size(bd->queue.queue,
1228
 
                                bd->user_disk_0_blk_size);
1229
 
                        #ifndef WESTBRIDGE_NDEBUG
1230
 
                        cy_as_hal_print_message(
1231
 
                        "%s: set hard sect_sz:%d\n",
1232
 
                        __func__,
1233
 
                        bd->user_disk_0_blk_size);
1234
 
                        #endif
1235
 
                } else {
1236
 
                        blk_queue_logical_block_size(bd->queue.queue,
1237
 
                                bd->user_disk_1_blk_size);
1238
 
                        #ifndef WESTBRIDGE_NDEBUG
1239
 
                        cy_as_hal_print_message(
1240
 
                        "%s: set hard sect_sz:%d\n",
1241
 
                        __func__,
1242
 
                        bd->user_disk_1_blk_size);
1243
 
                        #endif
1244
 
                }
1245
 
 
1246
 
                set_capacity(bd->user_disk_1, disk_cap);
1247
 
                if (vfat_search) {
1248
 
                        bd->user_disk_1_first_sector =
1249
 
                                cyasblkdev_get_vfat_offset(
1250
 
                                        bd->user_disk_1_bus_num,
1251
 
                                        bd->user_disk_1_unit_no);
1252
 
                } else {
1253
 
                        bd->user_disk_1_first_sector
1254
 
                                = 0;
1255
 
                }
1256
 
 
1257
 
                add_disk(bd->user_disk_1);
1258
 
        }
1259
 
 
1260
 
        if (lcl_unit_no > 0) {
1261
 
                if (bd->system_disk == NULL) {
1262
 
                        bd->system_disk =
1263
 
                                alloc_disk(8);
1264
 
 
1265
 
                        if (bd->system_disk == NULL) {
1266
 
                                kfree(bd);
1267
 
                                bd = ERR_PTR(-ENOMEM);
1268
 
                                return bd;
1269
 
                        }
1270
 
                        disk_cap = (uint64_t)
1271
 
                                (private_partition_size);
1272
 
 
1273
 
                        /* set properties of
1274
 
                         * system disk */
1275
 
                        bd->system_disk_read_only = !dev_data.desc_p.writeable;
1276
 
                        bd->system_disk_blk_size = dev_data.desc_p.block_size;
1277
 
                        bd->system_disk_bus_num = bus_num;
1278
 
                        bd->system_disk->major = major;
1279
 
                        bd->system_disk->first_minor =
1280
 
                                (devidx + 2) << CYASBLKDEV_SHIFT;
1281
 
                        bd->system_disk->minors = 8;
1282
 
                        bd->system_disk->fops = &cyasblkdev_bdops;
1283
 
                        bd->system_disk->events = DISK_EVENT_MEDIA_CHANGE;
1284
 
                        bd->system_disk->private_data = bd;
1285
 
                        bd->system_disk->queue = bd->queue.queue;
1286
 
                        /* don't search for vfat
1287
 
                         * with system disk */
1288
 
                        bd->system_disk_first_sector = 0;
1289
 
                        sprintf(
1290
 
                                bd->system_disk->disk_name,
1291
 
                                "cyasblkdevblk%d", (devidx + 2));
1292
 
 
1293
 
                        set_capacity(bd->system_disk,
1294
 
                                disk_cap);
1295
 
 
1296
 
                        add_disk(bd->system_disk);
1297
 
                }
1298
 
                #ifndef WESTBRIDGE_NDEBUG
1299
 
                else {
1300
 
                        cy_as_hal_print_message(
1301
 
                                "%s: system disk already allocated %d\n",
1302
 
                                __func__, bus_num);
1303
 
                }
1304
 
                #endif
1305
 
        }
1306
 
out:
1307
 
        return ret;
1308
 
}
1309
 
 
1310
 
static struct cyasblkdev_blk_data *cyasblkdev_blk_alloc(void)
1311
 
{
1312
 
        struct cyasblkdev_blk_data *bd;
1313
 
        int ret = 0;
1314
 
        cy_as_return_status_t stat = -1;
1315
 
        int bus_num = 0;
1316
 
        int total_media_count = 0;
1317
 
        int devidx = 0;
1318
 
        DBGPRN_FUNC_NAME;
1319
 
 
1320
 
        total_media_count = 0;
1321
 
        devidx = find_first_zero_bit(dev_use, CYASBLKDEV_NUM_MINORS);
1322
 
        if (devidx >= CYASBLKDEV_NUM_MINORS)
1323
 
                return ERR_PTR(-ENOSPC);
1324
 
 
1325
 
        __set_bit(devidx, dev_use);
1326
 
        __set_bit(devidx + 1, dev_use);
1327
 
 
1328
 
        bd = kzalloc(sizeof(struct cyasblkdev_blk_data), GFP_KERNEL);
1329
 
        if (bd) {
1330
 
                gl_bd = bd;
1331
 
 
1332
 
                spin_lock_init(&bd->lock);
1333
 
                bd->usage = 1;
1334
 
 
1335
 
                /* setup the block_dev_ops pointer*/
1336
 
                bd->blkops = &cyasblkdev_bdops;
1337
 
 
1338
 
                /* Get the device handle */
1339
 
                bd->dev_handle = cyasdevice_getdevhandle();
1340
 
                if (0 == bd->dev_handle) {
1341
 
                        #ifndef WESTBRIDGE_NDEBUG
1342
 
                        cy_as_hal_print_message(
1343
 
                                "%s: get device failed\n", __func__);
1344
 
                        #endif
1345
 
                        ret = ENODEV;
1346
 
                        goto out;
1347
 
                }
1348
 
 
1349
 
                #ifndef WESTBRIDGE_NDEBUG
1350
 
                cy_as_hal_print_message("%s west bridge device handle:%x\n",
1351
 
                        __func__, (uint32_t)bd->dev_handle);
1352
 
                #endif
1353
 
 
1354
 
                /* start the storage api and get a handle to the
1355
 
                 * device we are interested in. */
1356
 
 
1357
 
                /* Error code to use if the conditions are not satisfied. */
1358
 
                ret = ENOMEDIUM;
1359
 
 
1360
 
                stat = cy_as_misc_release_resource(bd->dev_handle, cy_as_bus_0);
1361
 
                if ((stat != CY_AS_ERROR_SUCCESS) &&
1362
 
                (stat != CY_AS_ERROR_RESOURCE_NOT_OWNED)) {
1363
 
                        #ifndef WESTBRIDGE_NDEBUG
1364
 
                        cy_as_hal_print_message("%s: cannot release "
1365
 
                                "resource bus 0 - reason code %d\n",
1366
 
                                __func__, stat);
1367
 
                        #endif
1368
 
                }
1369
 
 
1370
 
                stat = cy_as_misc_release_resource(bd->dev_handle, cy_as_bus_1);
1371
 
                if ((stat != CY_AS_ERROR_SUCCESS) &&
1372
 
                (stat != CY_AS_ERROR_RESOURCE_NOT_OWNED)) {
1373
 
                        #ifndef WESTBRIDGE_NDEBUG
1374
 
                        cy_as_hal_print_message("%s: cannot release "
1375
 
                                "resource bus 0 - reason code %d\n",
1376
 
                                __func__, stat);
1377
 
                        #endif
1378
 
                }
1379
 
 
1380
 
                /* start storage stack*/
1381
 
                stat = cy_as_storage_start(bd->dev_handle, 0, 0x101);
1382
 
                if (stat != CY_AS_ERROR_SUCCESS) {
1383
 
                        #ifndef WESTBRIDGE_NDEBUG
1384
 
                        cy_as_hal_print_message("%s: cannot start storage "
1385
 
                                "stack - reason code %d\n", __func__, stat);
1386
 
                        #endif
1387
 
                        goto out;
1388
 
                }
1389
 
 
1390
 
                #ifndef WESTBRIDGE_NDEBUG
1391
 
                cy_as_hal_print_message("%s: storage started:%d ok\n",
1392
 
                        __func__, stat);
1393
 
                #endif
1394
 
 
1395
 
                stat = cy_as_storage_register_callback(bd->dev_handle,
1396
 
                        cyasblkdev_storage_callback);
1397
 
                if (stat != CY_AS_ERROR_SUCCESS) {
1398
 
                        #ifndef WESTBRIDGE_NDEBUG
1399
 
                        cy_as_hal_print_message("%s: cannot register callback "
1400
 
                                "- reason code %d\n", __func__, stat);
1401
 
                        #endif
1402
 
                        goto out;
1403
 
                }
1404
 
 
1405
 
                for (bus_num = 0; bus_num < 2; bus_num++) {
1406
 
                        stat = cy_as_storage_query_bus(bd->dev_handle,
1407
 
                                bus_num, &bd->media_count[bus_num],  0, 0);
1408
 
                        if (stat == CY_AS_ERROR_SUCCESS) {
1409
 
                                total_media_count = total_media_count +
1410
 
                                        bd->media_count[bus_num];
1411
 
                        } else {
1412
 
                                #ifndef WESTBRIDGE_NDEBUG
1413
 
                                cy_as_hal_print_message("%s: cannot query %d, "
1414
 
                                        "reason code: %d\n",
1415
 
                                        __func__, bus_num, stat);
1416
 
                                #endif
1417
 
                                goto out;
1418
 
                        }
1419
 
                }
1420
 
 
1421
 
                if (total_media_count == 0) {
1422
 
                        #ifndef WESTBRIDGE_NDEBUG
1423
 
                        cy_as_hal_print_message(
1424
 
                                "%s: no storage media was found\n", __func__);
1425
 
                        #endif
1426
 
                        goto out;
1427
 
                } else if (total_media_count >= 1) {
1428
 
                        if (bd->user_disk_0 == NULL) {
1429
 
 
1430
 
                                bd->user_disk_0 =
1431
 
                                        alloc_disk(8);
1432
 
                                if (bd->user_disk_0 == NULL) {
1433
 
                                        kfree(bd);
1434
 
                                        bd = ERR_PTR(-ENOMEM);
1435
 
                                        return bd;
1436
 
                                }
1437
 
                        }
1438
 
                        #ifndef WESTBRIDGE_NDEBUG
1439
 
                        else {
1440
 
                                cy_as_hal_print_message("%s: no available "
1441
 
                                        "gen_disk for disk 0, "
1442
 
                                        "physically inconsistent\n", __func__);
1443
 
                        }
1444
 
                        #endif
1445
 
                }
1446
 
 
1447
 
                if (total_media_count == 2) {
1448
 
                        if (bd->user_disk_1 == NULL) {
1449
 
                                bd->user_disk_1 =
1450
 
                                        alloc_disk(8);
1451
 
                                if (bd->user_disk_1 == NULL) {
1452
 
                                        kfree(bd);
1453
 
                                        bd = ERR_PTR(-ENOMEM);
1454
 
                                        return bd;
1455
 
                                }
1456
 
                        }
1457
 
                        #ifndef WESTBRIDGE_NDEBUG
1458
 
                        else {
1459
 
                                cy_as_hal_print_message("%s: no available "
1460
 
                                        "gen_disk for media, "
1461
 
                                        "physically inconsistent\n", __func__);
1462
 
                        }
1463
 
                        #endif
1464
 
                }
1465
 
                #ifndef WESTBRIDGE_NDEBUG
1466
 
                else if (total_media_count > 2) {
1467
 
                        cy_as_hal_print_message("%s: count corrupted = 0x%d\n",
1468
 
                                __func__, total_media_count);
1469
 
                }
1470
 
                #endif
1471
 
 
1472
 
                #ifndef WESTBRIDGE_NDEBUG
1473
 
                cy_as_hal_print_message("%s: %d device(s) found\n",
1474
 
                        __func__, total_media_count);
1475
 
                #endif
1476
 
 
1477
 
                for (bus_num = 0; bus_num <= 1; bus_num++) {
1478
 
                        /*claim storage for cpu */
1479
 
                        stat = cy_as_storage_claim(bd->dev_handle,
1480
 
                                bus_num, 0, 0, 0);
1481
 
                        if (stat != CY_AS_ERROR_SUCCESS) {
1482
 
                                cy_as_hal_print_message("%s: cannot claim "
1483
 
                                        "%d bus - reason code %d\n",
1484
 
                                        __func__, bus_num, stat);
1485
 
                                goto out;
1486
 
                        }
1487
 
 
1488
 
                        dev_data.bus = bus_num;
1489
 
                        dev_data.device = 0;
1490
 
 
1491
 
                        stat = cy_as_storage_query_device(bd->dev_handle,
1492
 
                                &dev_data, 0, 0);
1493
 
                        if (stat == CY_AS_ERROR_SUCCESS) {
1494
 
                                cyasblkdev_add_disks(bus_num, bd,
1495
 
                                        total_media_count, devidx);
1496
 
                        } else if (stat == CY_AS_ERROR_NO_SUCH_DEVICE) {
1497
 
                                #ifndef WESTBRIDGE_NDEBUG
1498
 
                                cy_as_hal_print_message(
1499
 
                                        "%s: no device on bus %d\n",
1500
 
                                        __func__, bus_num);
1501
 
                                #endif
1502
 
                        } else {
1503
 
                                #ifndef WESTBRIDGE_NDEBUG
1504
 
                                cy_as_hal_print_message(
1505
 
                                        "%s: cannot query %d device "
1506
 
                                        "- reason code %d\n",
1507
 
                                        __func__, bus_num, stat);
1508
 
                                #endif
1509
 
                                goto out;
1510
 
                        }
1511
 
                } /* end for (bus_num = 0; bus_num <= 1; bus_num++)*/
1512
 
 
1513
 
                return bd;
1514
 
        }
1515
 
out:
1516
 
        #ifndef WESTBRIDGE_NDEBUG
1517
 
        cy_as_hal_print_message(
1518
 
                "%s: bd failed to initialize\n", __func__);
1519
 
        #endif
1520
 
 
1521
 
        kfree(bd);
1522
 
        bd = ERR_PTR(-ret);
1523
 
        return bd;
1524
 
}
1525
 
 
1526
 
 
1527
 
/*init west bridge block device */
1528
 
static int cyasblkdev_blk_initialize(void)
1529
 
{
1530
 
        struct cyasblkdev_blk_data *bd;
1531
 
        int res;
1532
 
 
1533
 
        DBGPRN_FUNC_NAME;
1534
 
 
1535
 
        res = register_blkdev(major, "cyasblkdev");
1536
 
 
1537
 
        if (res < 0) {
1538
 
                #ifndef WESTBRIDGE_NDEBUG
1539
 
                cy_as_hal_print_message(KERN_WARNING
1540
 
                        "%s unable to get major %d for cyasblkdev media: %d\n",
1541
 
                        __func__, major, res);
1542
 
                #endif
1543
 
                return res;
1544
 
        }
1545
 
 
1546
 
        if (major == 0)
1547
 
                major = res;
1548
 
 
1549
 
        #ifndef WESTBRIDGE_NDEBUG
1550
 
        cy_as_hal_print_message(
1551
 
                "%s cyasblkdev registered with major number: %d\n",
1552
 
                __func__, major);
1553
 
        #endif
1554
 
 
1555
 
        bd = cyasblkdev_blk_alloc();
1556
 
        if (IS_ERR(bd))
1557
 
                return PTR_ERR(bd);
1558
 
 
1559
 
        return 0;
1560
 
}
1561
 
 
1562
 
/* start block device */
1563
 
static int __init cyasblkdev_blk_init(void)
1564
 
{
1565
 
        int res = -ENOMEM;
1566
 
 
1567
 
        DBGPRN_FUNC_NAME;
1568
 
 
1569
 
        /* get the cyasdev handle for future use*/
1570
 
        cyas_dev_handle = cyasdevice_getdevhandle();
1571
 
 
1572
 
        if  (cyasblkdev_blk_initialize() == 0)
1573
 
                return 0;
1574
 
 
1575
 
        #ifndef WESTBRIDGE_NDEBUG
1576
 
        cy_as_hal_print_message("cyasblkdev init error:%d\n", res);
1577
 
        #endif
1578
 
        return res;
1579
 
}
1580
 
 
1581
 
 
1582
 
static void cyasblkdev_blk_deinit(struct cyasblkdev_blk_data *bd)
1583
 
{
1584
 
        DBGPRN_FUNC_NAME;
1585
 
 
1586
 
        if (bd) {
1587
 
                int devidx;
1588
 
 
1589
 
                if (bd->user_disk_0 != NULL) {
1590
 
                        del_gendisk(bd->user_disk_0);
1591
 
                        devidx = bd->user_disk_0->first_minor
1592
 
                                >> CYASBLKDEV_SHIFT;
1593
 
                        __clear_bit(devidx, dev_use);
1594
 
                }
1595
 
 
1596
 
                if (bd->user_disk_1 != NULL) {
1597
 
                        del_gendisk(bd->user_disk_1);
1598
 
                        devidx = bd->user_disk_1->first_minor
1599
 
                                >> CYASBLKDEV_SHIFT;
1600
 
                        __clear_bit(devidx, dev_use);
1601
 
                }
1602
 
 
1603
 
                if (bd->system_disk != NULL) {
1604
 
                        del_gendisk(bd->system_disk);
1605
 
                        devidx = bd->system_disk->first_minor
1606
 
                                >> CYASBLKDEV_SHIFT;
1607
 
                        __clear_bit(devidx, dev_use);
1608
 
                }
1609
 
 
1610
 
                cyasblkdev_blk_put(bd);
1611
 
        }
1612
 
}
1613
 
 
1614
 
/* block device exit */
1615
 
static void __exit cyasblkdev_blk_exit(void)
1616
 
{
1617
 
        DBGPRN_FUNC_NAME;
1618
 
 
1619
 
        cyasblkdev_blk_deinit(gl_bd);
1620
 
        unregister_blkdev(major, "cyasblkdev");
1621
 
 
1622
 
}
1623
 
 
1624
 
module_init(cyasblkdev_blk_init);
1625
 
module_exit(cyasblkdev_blk_exit);
1626
 
 
1627
 
MODULE_LICENSE("GPL");
1628
 
MODULE_DESCRIPTION("antioch (cyasblkdev) block device driver");
1629
 
MODULE_AUTHOR("cypress semiconductor");
1630
 
 
1631
 
/*[]*/