OpenCores
URL https://opencores.org/ocsvn/sata_controller_core/sata_controller_core/trunk

Subversion Repositories sata_controller_core

[/] [sata_controller_core/] [trunk/] [sata2_driver_v1_00_a/] [sata_drv.c] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 bhuang2
/*
2
 * sata-drv.c
3
 *
4
 * Linux block device driver for Ashwin Mendon's SATA controller.
5
 *
6
 * Author: Bin Huang  <bin.arthur@gmail.com>
7
 *
8
 * 2012 (c) Reconfigurable Computing System Lab at University of North
9
 * Carolina at Charlotte. This file is licensed under
10
 * the terms of the GNU General Public License version 2. This program
11
 * is licensed "as is" without any warranty of any kind, whether express
12
 * or implied. The code originally comes from the book "Linux Device
13
 * Drivers" by Alessandro Rubini and Jonathan Corbet, published
14
 * by O'Reilly & Associates.
15
 */
16
 
17
#include <linux/module.h>
18
#include <linux/moduleparam.h>
19
#include <linux/init.h>
20
#include <linux/sched.h>
21
#include <linux/kernel.h>       /* printk() */
22
#include <linux/slab.h>         /* kmalloc() */
23
#include <linux/fs.h>           /* everything... */
24
#include <linux/errno.h>        /* error codes */
25
#include <linux/types.h>        /* size_t */
26
#include <linux/fcntl.h>        /* O_ACCMODE */
27
#include <linux/hdreg.h>        /* HDIO_GETGEO */
28
#include <linux/kdev_t.h>
29
#include <linux/vmalloc.h>
30
#include <linux/genhd.h>
31
#include <linux/blkdev.h>
32
#include <linux/buffer_head.h>  /* invalidate_bdev */
33
#include <linux/bio.h>
34
#include <linux/delay.h>        /* udelay() */
35
#include "sata_drv.h"
36
 
37
MODULE_LICENSE("Dual BSD/GPL");
38
 
39
static int sata_major = 0;
40
module_param(sata_major, int, 0);
41
static int hardsect_size = HARDSECT_SIZE;
42
module_param(hardsect_size, int, 0);
43
static int nsectors = N_SECTORS;        /* How big the drive is */
44
module_param(nsectors, int, 0);
45
static int ndevices = 1;
46
module_param(ndevices, int, 0);
47
 
48
/*
49
 * The different "request modes" we can use.
50
 */
51
enum {
52
        RM_SIMPLE  = 0,  /* The extra-simple request function */
53
        RM_FULL    = 1, /* The full-blown version */
54
        RM_NOQUEUE = 2, /* Use make_request */
55
};
56
static int request_mode = RM_NOQUEUE;
57
module_param(request_mode, int, 0);
58
 
59
static struct sata_dev *Devices = NULL;
60
 
61
 
62
void read_sectors(struct sata_dev *dev, int sector_addr, int sector_count, unsigned int dma_phy_addr);
63
void write_sectors(struct sata_dev *dev, int sector_addr, int sector_count, unsigned int dma_phy_addr);
64
 
65
void read_sectors(struct sata_dev *dev, int sector_addr, int sector_count, unsigned int dma_phy_addr)
66
{
67
 
68
        // DDR Read Space Start Address 
69
        dev->scp->npi_wr_addr_reg = dma_phy_addr;
70
        // Clear SATA Control Register 
71
        dev->scp->ctrl_reg = REG_CLEAR;
72
 
73
        // Input Sector Address, Count and Command to Sata Core
74
        dev->scp->sector_addr_reg = sector_addr;
75
        dev->scp->sector_count_reg = sector_count;
76
        dev->scp->cmd_reg = (READ_CMD);
77
        // Trigger SATA Core
78
        dev->scp->ctrl_reg = (NEW_CMD);
79
 
80
        // Wait for Command Completion 
81
        while ((dev->scp->status_reg & SATA_CORE_DONE) != SATA_CORE_DONE);
82
 
83
        //Time to Read Sectors from Disk 
84
#ifdef CONFIG_RCS_SATA_DEBUG
85
        printk("Number of clock cycles to complete this read: %d\n",dev->scp->sector_timer_reg);
86
#endif
87
 
88
        while ((dev->scp->status_reg & NPI_DONE) != NPI_DONE);
89
}
90
 
91
 
92
void write_sectors(struct sata_dev *dev, int sector_addr, int sector_count, unsigned int dma_phy_addr)
93
{
94
        // DDR Write Space Start Address 
95
        dev->scp->npi_rd_addr_reg = dma_phy_addr;
96
        // Clear SATA Control Register 
97
        dev->scp->ctrl_reg = REG_CLEAR;
98
 
99
        // Input Sector Address, Count, DATA and Command to Sata Core
100
        dev->scp->sector_addr_reg = sector_addr;
101
        dev->scp->sector_count_reg = sector_count;
102
        //scp->wr_data_reg     = write_data;
103
        dev->scp->cmd_reg = (WRITE_CMD);
104
        // Trigger SATA Core
105
        dev->scp->ctrl_reg = (NEW_CMD);
106
        // Wait for Command Completion 
107
 
108
        while ((dev->scp->status_reg & SATA_CORE_DONE) != SATA_CORE_DONE);
109
 
110
        //Time to Write Sectors from Disk 
111
#ifdef CONFIG_RCS_SATA_DEBUG
112
        printk("Number of clock cycles to complete this write: %d\n",dev->scp->sector_timer_reg);
113
#endif
114
}
115
 
116
 
117
/*
118
 * Handle an I/O request.
119
 */
120
static void sata_transfer(struct sata_dev *dev, unsigned long sector,
121
                unsigned long nsect, char *buffer, int write)
122
{
123
        unsigned long offset = sector*KERNEL_SECTOR_SIZE;
124
        unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
125
 
126
        if ((offset + nbytes) > dev->size) {
127
                printk (KERN_INFO "Beyond-end write (%ld %ld)\n", offset, nbytes);
128
                return;
129
        }
130
        if (write){
131
#ifdef CONFIG_RCS_SATA_DEBUG
132
                printk (KERN_INFO "Write request to: \n");
133
                printk (KERN_INFO "sector = %lu, nsect = %lu, buf_phy_addr = 0x%08lx ... \n ", sector, nsect, virt_to_phys(buffer));
134
#endif
135
 
136
                write_sectors(dev, sector, nsect, virt_to_phys(buffer));
137
 
138
#ifdef CONFIG_RCS_SATA_DEBUG
139
                printk (KERN_INFO "Write done.\n");
140
#endif
141
        }
142
        else{
143
#ifdef CONFIG_RCS_SATA_DEBUG
144
                printk (KERN_INFO "Read request to: \n");
145
                printk (KERN_INFO "sector = %lu, nsect = %lu, buf_phy_addr = 0x%08lx ... \n", sector, nsect, virt_to_phys(buffer));
146
#endif
147
 
148
                read_sectors(dev, sector, nsect, virt_to_phys(buffer));
149
 
150
#ifdef CONFIG_RCS_SATA_DEBUG
151
                printk (KERN_INFO "Read done\n");
152
#endif
153
        }
154
}
155
 
156
 
157
static void sata_request(struct request_queue *q)
158
{
159
        struct request *req;
160
 
161
        req = blk_fetch_request(q);
162
        while (req != NULL) {
163
                struct sata_dev *dev = req->rq_disk->private_data;
164
                if (req == NULL || (req->cmd_type != REQ_TYPE_FS)) {
165
                        printk (KERN_NOTICE "Skip non-CMD request\n");
166
                        __blk_end_request_all(req, -EIO);
167
                        continue;
168
                }
169
                sata_transfer(dev, blk_rq_pos(req), blk_rq_cur_sectors(req),
170
                                req->buffer, rq_data_dir(req));
171
                if ( ! __blk_end_request_cur(req, 0) ) {
172
                        req = blk_fetch_request(q);
173
                }
174
        }
175
}
176
 
177
 
178
/*
179
 * Transfer a single BIO.
180
 */
181
static int sata_xfer_bio(struct sata_dev *dev, struct bio *bio)
182
{
183
        int i;
184
        struct bio_vec *bvec;
185
        sector_t sector = bio->bi_sector;
186
 
187
        void *mem;
188
 
189
        // Do each segment independently. 
190
        bio_for_each_segment(bvec, bio, i) {
191
                char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);
192
 
193
                mem = kmap(bvec->bv_page);
194
                kunmap(bvec->bv_page);
195
 
196
                sata_transfer(dev, sector, bio_cur_bytes(bio) >> SECTOR_SHIFT,
197
                                buffer, bio_data_dir(bio) == WRITE);
198
                sector += bio_cur_bytes(bio) >> SECTOR_SHIFT;
199
                __bio_kunmap_atomic(bio, KM_USER0);
200
        }
201
        return 0; // Always "succeed" 
202
}
203
 
204
 
205
/*
206
 * The direct make request version.
207
 */
208
static int sata_make_request(struct request_queue *q, struct bio *bio)
209
{
210
        struct sata_dev *dev = q->queuedata;
211
        int status;
212
 
213
        status = sata_xfer_bio(dev, bio);
214
        bio_endio(bio, status);
215
        return 0;
216
}
217
 
218
 
219
/*
220
 * Open and close.
221
 */
222
 
223
static int sata_open(struct block_device *bdev, fmode_t mode)
224
{
225
        struct sata_dev *dev = bdev->bd_disk->private_data;
226
        unsigned long flags;
227
 
228
        spin_lock_irqsave(&dev->lock, flags);
229
        dev->users++;
230
        spin_unlock_irqrestore(&dev->lock, flags);
231
 
232
        check_disk_change(bdev);
233
        return 0;
234
}
235
 
236
 
237
static int sata_release(struct gendisk *disk, fmode_t mode)
238
{
239
        struct sata_dev *dev = disk->private_data;
240
 
241
        spin_lock(&dev->lock);
242
        dev->users--;
243
 
244
        spin_unlock(&dev->lock);
245
 
246
        return 0;
247
}
248
 
249
 
250
/*
251
 * The HDIO_GETGEO ioctl is handled in blkdev_ioctl.
252
 */
253
int sata_getgeo (struct block_device *bdev, struct hd_geometry *geo)
254
{
255
        long size;
256
        struct sata_dev *dev = bdev->bd_disk->private_data;
257
 
258
        printk(KERN_INFO "SATA block device driver command : HDIO_GETGEO .\n");
259
        size = dev->size*(hardsect_size/KERNEL_SECTOR_SIZE);
260
        geo->cylinders = (size & ~0x3f) >> 6;
261
        geo->heads = 4;
262
        geo->sectors = 16;
263
        geo->start = 0;
264
        return 0;
265
 
266
}
267
 
268
 
269
/*
270
 * The device operations structure.
271
 */
272
static struct block_device_operations sata_ops =
273
{
274
        .owner           = THIS_MODULE,
275
        .open            = sata_open,
276
        .release         = sata_release,
277
        .getgeo          = sata_getgeo
278
};
279
 
280
 
281
/*
282
 * Set up our internal device.
283
 */
284
static int setup_device(struct sata_dev *dev, int which)
285
{
286
        int retval = 0;
287
        int try_setup_link = 0;
288
 
289
        /*
290
         * Initialize data structure.
291
         */
292
        memset (dev, 0, sizeof (struct sata_dev));
293
        dev->size = nsectors*hardsect_size;
294
 
295
        /*
296
         * Remap I/O for SATA controller.
297
         */
298
 
299
        if( !request_mem_region(SATA_CFG_BASE, SATA_CFG_REMAP_SIZE, DRIVER_NAME)){
300
                printk(KERN_ERR "Request for SATA configuration memory region failed!\n");
301
                dev->scp = 0;
302
                retval = -1;
303
                goto fail;
304
        }
305
        else {
306
                dev->scp = (SATA_core_t *) ioremap_nocache(SATA_CFG_BASE, SATA_CFG_REMAP_SIZE);
307
                if (dev->scp == 0) {
308
                        printk(KERN_ERR
309
                               "%s: Couldn't ioremap memory at 0x%08X\n",
310
                               DRIVER_NAME, SATA_CFG_BASE);
311
                        iounmap(dev->scp);
312
                        retval = -EFAULT;
313
                        goto fail;
314
                }
315
                else {
316
#ifdef CONFIG_RCS_SATA_DEBUG
317
                        printk(KERN_INFO "Remap Returned Virtual Address: %x\n",(unsigned int)dev->scp);
318
#endif
319
                }
320
        }
321
 
322
        dev->scp->ctrl_reg = REG_CLEAR;
323
        dev->scp->cmd_reg  = REG_CLEAR;
324
 
325
        while ((dev->scp->status_reg & SATA_LINK_READY) != SATA_LINK_READY)
326
        {
327
                dev->scp->ctrl_reg = SW_RESET;
328
                dev->scp->ctrl_reg = REG_CLEAR;
329
 
330
                try_setup_link++;
331
 
332
                udelay(100000);
333
 
334
                //It is very disk specific. For the OCZ SSD, it takes a few resets for the link 
335
                //to come up but on the Micron SSD or on the Western Digital HD, it comes up 
336
                //after the first reset. 
337
                if (try_setup_link == 100) {
338
#ifdef CONFIG_RCS_SATA_DEBUG
339
                        printk(KERN_INFO "SATA Link is not ready yet.\n");
340
#endif
341
                        retval = -ENODEV;
342
                        goto fail;
343
                }
344
        }
345
 
346
        spin_lock_init(&dev->lock);
347
 
348
        /*
349
         * The I/O queue, depending on whether we are using our own
350
         * make_request function or not.
351
         */
352
        switch (request_mode) {
353
            case RM_NOQUEUE:
354
                dev->queue = blk_alloc_queue(GFP_KERNEL);
355
                if (dev->queue == NULL)
356
                        goto fail;
357
                blk_queue_make_request(dev->queue, sata_make_request);
358
                break;
359
 
360
            case RM_SIMPLE:
361
                dev->queue = blk_init_queue(sata_request, &dev->lock);
362
                if (dev->queue == NULL)
363
                {
364
                        retval = -ENODEV;
365
                        goto fail;
366
                }
367
                break;
368
 
369
            default:
370
                printk(KERN_NOTICE "Bad request mode %d, using simple\n", request_mode);
371
        }
372
        blk_queue_logical_block_size(dev->queue, hardsect_size);
373
        dev->queue->queuedata = dev;
374
 
375
        /*
376
         * And the gendisk structure.
377
         */
378
        dev->gd = alloc_disk(SATA_MINORS);
379
        if (! dev->gd) {
380
                printk (KERN_INFO "alloc_disk failure\n");
381
                retval = -ENODEV;
382
                goto fail;
383
        }
384
        printk (KERN_INFO "alloc_disk success\n");
385
        dev->gd->major = sata_major;
386
        dev->gd->first_minor = which*SATA_MINORS;
387
        dev->gd->fops = &sata_ops;
388
        dev->gd->queue = dev->queue;
389
        dev->gd->private_data = dev;
390
        snprintf (dev->gd->disk_name, 32, "sata%c", which + 'a');
391
        set_capacity(dev->gd, nsectors*(hardsect_size/KERNEL_SECTOR_SIZE));
392
        add_disk(dev->gd);
393
 
394
        return 0;               /* success */
395
 
396
fail:
397
        printk(KERN_INFO "Fail to setup SATA block device.\n");
398
        printk("SATA controller status: 0x%08x\n", dev->scp->status_reg);
399
        return retval;
400
}
401
 
402
 
403
static int __init sata_init(void)
404
{
405
        int i;
406
        int retval = 0;
407
 
408
        /*
409
         * Get registered.
410
         */
411
        printk(KERN_INFO "Block device driver for sata controller\n");
412
        sata_major = register_blkdev(sata_major, "sata");
413
        if (sata_major <= 0) {
414
                printk(KERN_WARNING "sata: unable to get major number\n");
415
                return -EBUSY;
416
        }
417
 
418
        /*
419
         * Allocate the device array, and initialize each one.
420
         */
421
        Devices = kmalloc(ndevices*sizeof (struct sata_dev), GFP_KERNEL);
422
        if (Devices == NULL)
423
                goto out_unregister;
424
        for (i = 0; i < ndevices; i++){
425
                retval = setup_device(Devices + i, i);
426
        }
427
        return retval;
428
 
429
  out_unregister:
430
        unregister_blkdev(sata_major, "sata");
431
        return -ENOMEM;
432
}
433
 
434
 
435
static void sata_exit(void)
436
{
437
        int i;
438
 
439
        for (i = 0; i < ndevices; i++) {
440
                struct sata_dev *dev = Devices + i;
441
 
442
                if (dev->gd) {
443
                        del_gendisk(dev->gd);
444
                        put_disk(dev->gd);
445
                }
446
                if (dev->queue) {
447
                        if (request_mode == RM_NOQUEUE)
448
                                blk_put_queue(dev->queue);
449
                        else
450
                                blk_cleanup_queue(dev->queue);
451
                }
452
        }
453
        unregister_blkdev(sata_major, "sata");
454
        kfree(Devices);
455
}
456
 
457
module_init(sata_init);
458
module_exit(sata_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.