Annotation of Gnu-Mach/linux/dev/drivers/block/ahci.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *  Copyright (C) 2013 Free Software Foundation
        !             3:  *
        !             4:  * This program is free software ; you can redistribute it and/or modify
        !             5:  * it under the terms of the GNU General Public License as published by
        !             6:  * the Free Software Foundation ; either version 2 of the License, or
        !             7:  * (at your option) any later version.
        !             8:  *
        !             9:  * This program is distributed in the hope that it will be useful,
        !            10:  * but WITHOUT ANY WARRANTY ; without even the implied warranty of
        !            11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
        !            12:  * GNU General Public License for more details.
        !            13:  *
        !            14:  * You should have received a copy of the GNU General Public License
        !            15:  * along with the program ; if not, write to the Free Software
        !            16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            17:  */
        !            18: 
        !            19: #include <ahci.h>
        !            20: #include <kern/assert.h>
        !            21: #include <linux/kernel.h>
        !            22: #include <linux/types.h>
        !            23: #include <linux/pci.h>
        !            24: #include <linux/fs.h>
        !            25: #include <linux/bios32.h>
        !            26: #include <linux/major.h>
        !            27: #include <linux/hdreg.h>
        !            28: #include <linux/genhd.h>
        !            29: #include <asm/io.h>
        !            30: 
        !            31: #define MAJOR_NR SCSI_DISK_MAJOR
        !            32: #include <linux/blk.h>
        !            33: 
        !            34: /* Standard AHCI BAR for mmio */
        !            35: #define AHCI_PCI_BAR 5
        !            36: 
        !            37: /* minor: 2 bits for device number, 6 bits for partition number. */
        !            38: 
        !            39: #define MAX_PORTS 4
        !            40: #define PARTN_BITS 6
        !            41: #define PARTN_MASK ((1<<PARTN_BITS)-1)
        !            42: 
        !            43: /* We need to use one DMA scatter element per physical page.
        !            44:  * ll_rw_block creates at most 8 buffer heads */
        !            45: /* See MAX_BUF */
        !            46: #define PRDTL_SIZE 8
        !            47: 
        !            48: #define WAIT_MAX (1*HZ) /* Wait at most 1s for requests completion */
        !            49: 
        !            50: /* AHCI standard structures */
        !            51: 
        !            52: struct ahci_prdt {
        !            53:        u32 dba;                        /* Data base address */
        !            54:        u32 dbau;                       /* upper 32bit */
        !            55:        u32 rsv0;                       /* Reserved */
        !            56: 
        !            57:        u32 dbc;                        /* Byte count bits 0-21,
        !            58:                                         * bit31 interrupt on completion. */
        !            59: };
        !            60: 
        !            61: struct ahci_cmd_tbl {
        !            62:        u8 cfis[64];
        !            63:        u8 acmd[16];
        !            64:        u8 rsv[48];
        !            65: 
        !            66:        struct ahci_prdt prdtl[PRDTL_SIZE];
        !            67: };
        !            68: 
        !            69: struct ahci_command {
        !            70:        u32 opts;                       /* Command options */
        !            71: 
        !            72:        u32 prdbc;                      /* Physical Region Descriptor byte count */
        !            73: 
        !            74:        u32 ctba;                       /* Command Table Descriptor Base Address */
        !            75:        u32 ctbau;                      /* upper 32bit */
        !            76: 
        !            77:        u32 rsv1[4];                    /* Reserved */
        !            78: };
        !            79: 
        !            80: struct ahci_fis_dma {
        !            81:        u8 fis_type;
        !            82:        u8 flags;
        !            83:        u8 rsved[2];
        !            84:        u64 id;
        !            85:        u32 rsvd;
        !            86:        u32 offset;
        !            87:        u32 count;
        !            88:        u32 resvd;
        !            89: };
        !            90: 
        !            91: struct ahci_fis_pio {
        !            92:        u8 fis_type;
        !            93:        u8 flags;
        !            94:        u8 status;
        !            95:        u8 error;
        !            96: 
        !            97:        u8 lba0;
        !            98:        u8 lba1;
        !            99:        u8 lba2;
        !           100:        u8 device;
        !           101: 
        !           102:        u8 lba3;
        !           103:        u8 lba4;
        !           104:        u8 lba5;
        !           105:        u8 rsv2;
        !           106: 
        !           107:        u8 countl;
        !           108:        u8 counth;
        !           109:        u8 rsv3;
        !           110:        u8 e_status;
        !           111: 
        !           112:        u16 tc; /* Transfer Count */
        !           113:        u8 rsv4[2];
        !           114: };
        !           115: 
        !           116: struct ahci_fis_d2h {
        !           117:        u8 fis_type;
        !           118:        u8 flags;
        !           119:        u8 status;
        !           120:        u8 error;
        !           121: 
        !           122:        u8 lba0;
        !           123:        u8 lba1;
        !           124:        u8 lba2;
        !           125:        u8 device;
        !           126: 
        !           127:        u8 lba3;
        !           128:        u8 lba4;
        !           129:        u8 lba5;
        !           130:        u8 rsv2;
        !           131: 
        !           132:        u8 countl;
        !           133:        u8 counth;
        !           134:        u8 rsv3[2];
        !           135: 
        !           136:        u8 rsv4[4];
        !           137: };
        !           138: 
        !           139: struct ahci_fis_dev {
        !           140:        u8 rsvd[8];
        !           141: };
        !           142: 
        !           143: struct ahci_fis_h2d {
        !           144:        u8 fis_type;
        !           145:        u8 flags;
        !           146:        u8 command;
        !           147:        u8 featurel;
        !           148: 
        !           149:        u8 lba0;
        !           150:        u8 lba1;
        !           151:        u8 lba2;
        !           152:        u8 device;
        !           153: 
        !           154:        u8 lba3;
        !           155:        u8 lba4;
        !           156:        u8 lba5;
        !           157:        u8 featureh;
        !           158: 
        !           159:        u8 countl;
        !           160:        u8 counth;
        !           161:        u8 icc;
        !           162:        u8 control;
        !           163: 
        !           164:        u8 rsv1[4];
        !           165: };
        !           166: 
        !           167: struct ahci_fis_data {
        !           168:        u8 fis_type;
        !           169:        u8 flags;
        !           170:        u8 rsv1[2];
        !           171:        u32 data1[];
        !           172: };
        !           173: 
        !           174: struct ahci_fis {
        !           175:        struct ahci_fis_dma dma_fis;
        !           176:        u8 pad0[4];
        !           177: 
        !           178:        struct ahci_fis_pio pio_fis;
        !           179:        u8 pad1[12];
        !           180: 
        !           181:        struct ahci_fis_d2h d2h_fis;
        !           182:        u8 pad2[4];
        !           183: 
        !           184:        struct ahci_fis_dev dev_fis;
        !           185: 
        !           186:        u8 ufis[64];
        !           187: 
        !           188:        u8 rsv[0x100 - 0xa0];
        !           189: };
        !           190: 
        !           191: struct ahci_port {
        !           192:        u32 clb;                        /* Command List Base address */
        !           193:        u32 clbu;                       /* upper 32bit */
        !           194:        u32 fb;                         /* FIS Base */
        !           195:        u32 fbu;                        /* upper 32bit */
        !           196:        u32 is;                         /* Interrupt Status */
        !           197:        u32 ie;                         /* Interrupt Enable */
        !           198:        u32 cmd;                        /* Command and Status */
        !           199:        u32 rsv0;                       /* Reserved */
        !           200:        u32 tfd;                        /* Task File Data */
        !           201:        u32 sig;                        /* Signature */
        !           202:        u32 ssts;                       /* SATA Status */
        !           203:        u32 sctl;                       /* SATA Control */
        !           204:        u32 serr;                       /* SATA Error */
        !           205:        u32 sact;                       /* SATA Active */
        !           206:        u32 ci;                         /* Command Issue */
        !           207:        u32 sntf;                       /* SATA Notification */
        !           208:        u32 fbs;                        /* FIS-based switch control */
        !           209:        u8 rsv1[0x70 - 0x44];           /* Reserved */
        !           210:        u8 vendor[0x80 - 0x70];         /* Vendor-specific */
        !           211: };
        !           212: 
        !           213: struct ahci_host {
        !           214:        u32 cap;                        /* Host capabilities */
        !           215:        u32 ghc;                        /* Global Host Control */
        !           216:        u32 is;                         /* Interrupt Status */
        !           217:        u32 pi;                         /* Port Implemented */
        !           218:        u32 v;                          /* Version */
        !           219:        u32 ccc_ctl;                    /* Command Completion Coalescing control */
        !           220:        u32 ccc_pts;                    /* Command Completion Coalescing ports */
        !           221:        u32 em_loc;                     /* Enclosure Management location */
        !           222:        u32 em_ctrl;                    /* Enclosure Management control */
        !           223:        u32 cap2;                       /* Host capabilities extended */
        !           224:        u32 bohc;                       /* BIOS/OS Handoff Control and status */
        !           225:        u8 rsv[0xa0 - 0x2c];            /* Reserved */
        !           226:        u8 vendor[0x100 - 0xa0];        /* Vendor-specific */
        !           227:        struct ahci_port ports[];       /* Up to 32 ports */
        !           228: };
        !           229: 
        !           230: /* Our own data */
        !           231: 
        !           232: static struct port {
        !           233:        /* memory-mapped regions */
        !           234:        const volatile struct ahci_host *ahci_host;
        !           235:        const volatile struct ahci_port *ahci_port;
        !           236: 
        !           237:        /* host-memory buffers */
        !           238:        struct ahci_command *command;
        !           239:        struct ahci_fis *fis;
        !           240:        struct ahci_cmd_tbl *prdtl;
        !           241: 
        !           242:        unsigned long long capacity;    /* Nr of sectors */
        !           243:        u32 status;                     /* interrupt status */
        !           244:        unsigned cls;                   /* Command list maximum size.
        !           245:                                           We currently only use 1. */
        !           246:        struct wait_queue *q;           /* IRQ wait queue */
        !           247:        struct hd_struct *part;         /* drive partition table */
        !           248:        unsigned lba48;                 /* Whether LBA48 is supported */
        !           249:        unsigned identify;              /* Whether we are just identifying
        !           250:                                           at boot */
        !           251:        struct gendisk *gd;
        !           252: } ports[MAX_PORTS];
        !           253: 
        !           254: 
        !           255: /* do_request() gets called by the block layer to push a request to the disk.
        !           256:    We just push one, and when an interrupt tells it's over, we call do_request()
        !           257:    ourself again to push the next request, etc. */
        !           258: 
        !           259: /* Request completed, either successfully or with an error */
        !           260: static void ahci_end_request(int uptodate)
        !           261: {
        !           262:        struct request *rq = CURRENT;
        !           263:        struct buffer_head *bh;
        !           264: 
        !           265:        rq->errors = 0;
        !           266:        if (!uptodate) {
        !           267:                printk("end_request: I/O error, dev %s, sector %lu\n",
        !           268:                                kdevname(rq->rq_dev), rq->sector);
        !           269:                assert(0);
        !           270:        }
        !           271: 
        !           272:        for (bh = rq->bh; bh; )
        !           273:        {
        !           274:                struct buffer_head *next = bh->b_reqnext;
        !           275:                bh->b_reqnext = NULL;
        !           276:                mark_buffer_uptodate (bh, uptodate);
        !           277:                unlock_buffer (bh);
        !           278:                bh = next;
        !           279:        }
        !           280: 
        !           281:        CURRENT = rq->next;
        !           282:        if (rq->sem != NULL)
        !           283:                up(rq->sem);
        !           284:        rq->rq_status = RQ_INACTIVE;
        !           285:        wake_up(&wait_for_request);
        !           286: }
        !           287: 
        !           288: /* Push the request to the controler port */
        !           289: static void ahci_do_port_request(struct port *port, unsigned sector, struct request *rq)
        !           290: {
        !           291:        struct ahci_command *command = port->command;
        !           292:        struct ahci_cmd_tbl *prdtl = port->prdtl;
        !           293:        struct ahci_fis_h2d *fis_h2d;
        !           294:        unsigned slot = 0;
        !           295:        struct buffer_head *bh;
        !           296:        unsigned i;
        !           297: 
        !           298:        rq->rq_status = RQ_SCSI_BUSY;
        !           299: 
        !           300:        /* Shouldn't ever happen: the block glue is limited at 8 blocks */
        !           301:        assert(rq->nr_sectors < 0x10000);
        !           302: 
        !           303:        fis_h2d = (void*) &prdtl[slot].cfis;
        !           304:        fis_h2d->fis_type = FIS_TYPE_REG_H2D;
        !           305:        fis_h2d->flags = 128;
        !           306:        if (port->lba48)
        !           307:                if (rq->cmd == READ)
        !           308:                        fis_h2d->command = WIN_READDMA_EXT;
        !           309:                else
        !           310:                        fis_h2d->command = WIN_WRITEDMA_EXT;
        !           311:        else
        !           312:                if (rq->cmd == READ)
        !           313:                        fis_h2d->command = WIN_READDMA;
        !           314:                else
        !           315:                        fis_h2d->command = WIN_WRITEDMA;
        !           316: 
        !           317:        fis_h2d->device = 1<<6; /* LBA */
        !           318: 
        !           319:        fis_h2d->lba0 = sector;
        !           320:        fis_h2d->lba1 = sector >> 8;
        !           321:        fis_h2d->lba2 = sector >> 16;
        !           322: 
        !           323:        fis_h2d->lba3 = sector >> 24;
        !           324:        fis_h2d->lba4 = 0;
        !           325:        fis_h2d->lba5 = 0;
        !           326: 
        !           327:        fis_h2d->countl = rq->nr_sectors;
        !           328:        fis_h2d->counth = rq->nr_sectors >> 8;
        !           329: 
        !           330:        command[slot].opts = sizeof(*fis_h2d) / sizeof(u32);
        !           331: 
        !           332:        if (rq->cmd == WRITE)
        !           333:                command[slot].opts |= AHCI_CMD_WRITE;
        !           334: 
        !           335:        for (i = 0, bh = rq->bh; bh; i++, bh = bh->b_reqnext)
        !           336:        {
        !           337:                assert(i < PRDTL_SIZE);
        !           338:                assert((((unsigned long) bh->b_data) & ~PAGE_MASK) ==
        !           339:                        (((unsigned long) bh->b_data + bh->b_size - 1) & ~PAGE_MASK));
        !           340:                prdtl[slot].prdtl[i].dbau = 0;
        !           341:                prdtl[slot].prdtl[i].dba = vmtophys(bh->b_data);
        !           342:                prdtl[slot].prdtl[i].dbc = bh->b_size - 1;
        !           343:        }
        !           344: 
        !           345:        command[slot].opts |= i << 16;
        !           346: 
        !           347:        /* Make sure main memory buffers are up to date */
        !           348:        mb();
        !           349: 
        !           350:        /* Issue command */
        !           351:        writel(1 << slot, &port->ahci_port->ci);
        !           352: 
        !           353:        /* TODO: IRQ timeout handler */
        !           354: }
        !           355: 
        !           356: /* Called by block core to push a request */
        !           357: /* TODO: ideally, would have one request queue per port */
        !           358: /* TODO: ideally, would use tags to process several requests at a time */
        !           359: static void ahci_do_request()  /* invoked with cli() */
        !           360: {
        !           361:        struct request *rq;
        !           362:        unsigned minor, unit;
        !           363:        unsigned long block, blockend;
        !           364:        struct port *port;
        !           365: 
        !           366:        rq = CURRENT;
        !           367:        if (!rq)
        !           368:                return;
        !           369: 
        !           370:        if (rq->rq_status != RQ_ACTIVE)
        !           371:                /* Current one is already ongoing, let the interrupt handler
        !           372:                 * push the new one when the current one is finished. */
        !           373:                return;
        !           374: 
        !           375:        if (MAJOR(rq->rq_dev) != MAJOR_NR) {
        !           376:                printk("bad ahci major %u\n", MAJOR(rq->rq_dev));
        !           377:                goto kill_rq;
        !           378:        }
        !           379: 
        !           380:        minor = MINOR(rq->rq_dev);
        !           381:        unit = minor >> PARTN_BITS;
        !           382:        if (unit > MAX_PORTS) {
        !           383:                printk("bad ahci unit %u\n", unit);
        !           384:                goto kill_rq;
        !           385:        }
        !           386: 
        !           387:        port = &ports[unit];
        !           388: 
        !           389:        /* Compute start sector */
        !           390:        block = rq->sector;
        !           391:        block += port->part[minor & PARTN_MASK].start_sect;
        !           392: 
        !           393:        /* And check end */
        !           394:        blockend = block + rq->nr_sectors;
        !           395:        if (blockend < block) {
        !           396:                printk("bad blockend %lu vs %lu\n", blockend, block);
        !           397:                goto kill_rq;
        !           398:        }
        !           399:        if (blockend > port->capacity) {
        !           400:                printk("offset for %u was %lu\n", minor, port->part[minor & PARTN_MASK].start_sect);
        !           401:                printk("bad access: block %lu, count= %lu\n", blockend, (unsigned long) port->capacity);
        !           402:                goto kill_rq;
        !           403:        }
        !           404: 
        !           405:        /* Push this to the port */
        !           406:        ahci_do_port_request(port, block, rq);
        !           407:        return;
        !           408: 
        !           409: kill_rq:
        !           410:        ahci_end_request(0);
        !           411: }
        !           412: 
        !           413: /* The given port got an interrupt, terminate the current request if any */
        !           414: static void ahci_port_interrupt(struct port *port, u32 status)
        !           415: {
        !           416:        unsigned slot = 0;
        !           417: 
        !           418:        if (readl(&port->ahci_port->ci) & (1 << slot)) {
        !           419:                /* Command still pending */
        !           420:                return;
        !           421:        }
        !           422: 
        !           423:        if (port->identify) {
        !           424:                port->status = status;
        !           425:                wake_up(&port->q);
        !           426:                return;
        !           427:        }
        !           428: 
        !           429:        if (!CURRENT || CURRENT->rq_status != RQ_SCSI_BUSY) {
        !           430:                /* No request currently running */
        !           431:                return;
        !           432:        }
        !           433: 
        !           434:        if (status & (PORT_IRQ_TF_ERR | PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_IF_ERR | PORT_IRQ_IF_NONFATAL)) {
        !           435:                printk("ahci error %x %x\n", status, readl(&port->ahci_port->tfd));
        !           436:                ahci_end_request(0);
        !           437:                return;
        !           438:        }
        !           439: 
        !           440:        ahci_end_request(1);
        !           441: }
        !           442: 
        !           443: /* Start of IRQ handler. Iterate over all ports for this host */
        !           444: static void ahci_interrupt (int irq, void *host, struct pt_regs *regs)
        !           445: {
        !           446:        struct port *port;
        !           447:        struct ahci_host *ahci_host = host;
        !           448:        u32 irq_mask;
        !           449:        u32 status;
        !           450: 
        !           451:        irq_mask = readl(&ahci_host->is);
        !           452: 
        !           453:        if (!irq_mask)
        !           454:                return;
        !           455: 
        !           456:        for (port = &ports[0]; port < &ports[MAX_PORTS]; port++) {
        !           457:                if (port->ahci_host == ahci_host && (irq_mask & (1 << (port->ahci_port - ahci_host->ports)))) {
        !           458:                        status = readl(&port->ahci_port->is);
        !           459:                        /* Clear interrupt before possibly triggering others */
        !           460:                        writel(status, &port->ahci_port->is);
        !           461:                        ahci_port_interrupt (port, status);
        !           462:                }
        !           463:        }
        !           464: 
        !           465:        if (CURRENT)
        !           466:                /* Still some requests, queue another one */
        !           467:                ahci_do_request();
        !           468: 
        !           469:        /* Clear host after clearing ports */
        !           470:        writel(irq_mask, &ahci_host->is);
        !           471: 
        !           472:        /* unlock */
        !           473: }
        !           474: 
        !           475: static int ahci_ioctl (struct inode *inode, struct file *file,
        !           476:                        unsigned int cmd, unsigned long arg)
        !           477: {
        !           478:        int major, unit;
        !           479: 
        !           480:        if (!inode || !inode->i_rdev)
        !           481:                return -EINVAL;
        !           482: 
        !           483:        major = MAJOR(inode->i_rdev);
        !           484:        if (major != MAJOR_NR)
        !           485:                return -ENOTTY;
        !           486: 
        !           487:        unit = DEVICE_NR(inode->i_rdev);
        !           488:        if (unit >= MAX_PORTS)
        !           489:                return -EINVAL;
        !           490: 
        !           491:        switch (cmd) {
        !           492:                case BLKRRPART:
        !           493:                        if (!suser()) return -EACCES;
        !           494:                        if (!ports[unit].gd)
        !           495:                                return -EINVAL;
        !           496:                        resetup_one_dev(ports[unit].gd, unit);
        !           497:                        return 0;
        !           498:                default:
        !           499:                        return -EPERM;
        !           500:        }
        !           501: }
        !           502: 
        !           503: static int ahci_open (struct inode *inode, struct file *file)
        !           504: {
        !           505:        int target;
        !           506: 
        !           507:        if (MAJOR(inode->i_rdev) != MAJOR_NR)
        !           508:                return -ENXIO;
        !           509: 
        !           510:        target = MINOR(inode->i_rdev) >> PARTN_BITS;
        !           511:        if (target >= MAX_PORTS)
        !           512:                return -ENXIO;
        !           513: 
        !           514:        if (!ports[target].ahci_port)
        !           515:                return -ENXIO;
        !           516: 
        !           517:        return 0;
        !           518: }
        !           519: 
        !           520: static void ahci_release (struct inode *inode, struct file *file)
        !           521: {
        !           522: }
        !           523: 
        !           524: static int ahci_fsync (struct inode *inode, struct file *file)
        !           525: {
        !           526:        printk("fsync\n");
        !           527:        return -ENOSYS;
        !           528: }
        !           529: 
        !           530: static struct file_operations ahci_fops = {
        !           531:        .lseek = NULL,
        !           532:        .read = block_read,
        !           533:        .write = block_write,
        !           534:        .readdir = NULL,
        !           535:        .select = NULL,
        !           536:        .ioctl = ahci_ioctl,
        !           537:        .mmap = NULL,
        !           538:        .open = ahci_open,
        !           539:        .release = ahci_release,
        !           540:        .fsync = ahci_fsync,
        !           541:        .fasync = NULL,
        !           542:        .check_media_change = NULL,
        !           543:        .revalidate = NULL,
        !           544: };
        !           545: 
        !           546: /* Disk timed out while processing identify, interrupt ahci_probe_port */
        !           547: static void identify_timeout(unsigned long data)
        !           548: {
        !           549:        struct port *port = (void*) data;
        !           550: 
        !           551:        wake_up(&port->q);
        !           552: }
        !           553: 
        !           554: static struct timer_list identify_timer = { .function = identify_timeout };
        !           555: 
        !           556: /* Probe one AHCI port */
        !           557: static void ahci_probe_port(const volatile struct ahci_host *ahci_host, const volatile struct ahci_port *ahci_port)
        !           558: {
        !           559:        struct port *port;
        !           560:        void *mem;
        !           561:        struct hd_driveid id;
        !           562:        unsigned cls = ((readl(&ahci_host->cap) >> 8) & 0x1f) + 1;
        !           563:        struct ahci_command *command;
        !           564:        struct ahci_fis *fis;
        !           565:        struct ahci_cmd_tbl *prdtl;
        !           566:        struct ahci_fis_h2d *fis_h2d;
        !           567:        vm_size_t size =
        !           568:                  cls * sizeof(*command)
        !           569:                + sizeof(*fis)
        !           570:                + cls * sizeof(*prdtl);
        !           571:        unsigned i;
        !           572:        unsigned slot;
        !           573:        unsigned long first_part;
        !           574:        unsigned long long timeout;
        !           575:        unsigned long flags;
        !           576: 
        !           577:        for (i = 0; i < MAX_PORTS; i++) {
        !           578:                if (!ports[i].ahci_port)
        !           579:                        break;
        !           580:        }
        !           581:        if (i == MAX_PORTS)
        !           582:                return;
        !           583:        port = &ports[i];
        !           584: 
        !           585:        /* Has to be 1K-aligned */
        !           586:        mem = vmalloc (size);
        !           587:        if (!mem)
        !           588:                return;
        !           589:        assert (!(((unsigned long) mem) & (1024-1)));
        !           590:        memset (mem, 0, size);
        !           591: 
        !           592:        port->ahci_host = ahci_host;
        !           593:        port->ahci_port = ahci_port;
        !           594:        port->cls = cls;
        !           595: 
        !           596:        port->command = command = mem;
        !           597:        port->fis = fis = (void*) command + cls * sizeof(*command);
        !           598:        port->prdtl = prdtl = (void*) fis + sizeof(*fis);
        !           599: 
        !           600:        /* Stop commands */
        !           601:        writel(readl(&ahci_port->cmd) & ~PORT_CMD_START, &ahci_port->cmd);
        !           602:        timeout = jiffies + WAIT_MAX;
        !           603:        while (readl(&ahci_port->cmd) & PORT_CMD_LIST_ON)
        !           604:                if (jiffies > timeout) {
        !           605:                        printk("sd%u: timeout waiting for list completion\n", port-ports);
        !           606:                        port->ahci_host = NULL;
        !           607:                        port->ahci_port = NULL;
        !           608:                        return;
        !           609:                }
        !           610: 
        !           611:        writel(readl(&ahci_port->cmd) & ~PORT_CMD_FIS_RX, &ahci_port->cmd);
        !           612:        timeout = jiffies + WAIT_MAX;
        !           613:        while (readl(&ahci_port->cmd) & PORT_CMD_FIS_ON)
        !           614:                if (jiffies > timeout) {
        !           615:                        printk("sd%u: timeout waiting for FIS completion\n", port-ports);
        !           616:                        port->ahci_host = NULL;
        !           617:                        port->ahci_port = NULL;
        !           618:                        return;
        !           619:                }
        !           620: 
        !           621:        /* We don't support 64bit */
        !           622:        /* Point controller to our buffers */
        !           623:        writel(0, &ahci_port->clbu);
        !           624:        writel(vmtophys((void*) command), &ahci_port->clb);
        !           625:        writel(0, &ahci_port->fbu);
        !           626:        writel(vmtophys((void*) fis), &ahci_port->fb);
        !           627: 
        !           628:        /* Clear any previous interrupts */
        !           629:        writel(readl(&ahci_port->is), &ahci_port->is);
        !           630:        writel(1 << (ahci_port - ahci_host->ports), &ahci_host->is);
        !           631: 
        !           632:        /* And activate them */
        !           633:        writel(DEF_PORT_IRQ, &ahci_port->ie);
        !           634:        writel(readl(&ahci_host->ghc) | HOST_IRQ_EN, &ahci_host->ghc);
        !           635: 
        !           636:        for (i = 0; i < cls; i++)
        !           637:        {
        !           638:                command[i].ctbau = 0;
        !           639:                command[i].ctba = vmtophys((void*) &prdtl[i]);
        !           640:        }
        !           641: 
        !           642:        /* Start commands */
        !           643:        timeout = jiffies + WAIT_MAX;
        !           644:        while (readl(&ahci_port->cmd) & PORT_CMD_LIST_ON)
        !           645:                if (jiffies > timeout) {
        !           646:                        printk("sd%u: timeout waiting for list completion\n", port-ports);
        !           647:                        port->ahci_host = NULL;
        !           648:                        port->ahci_port = NULL;
        !           649:                        return;
        !           650:                }
        !           651: 
        !           652:        writel(readl(&ahci_port->cmd) | PORT_CMD_FIS_RX | PORT_CMD_START, &ahci_port->cmd);
        !           653: 
        !           654:        /* Identify device */
        !           655:        /* TODO: make this a request */
        !           656:        slot = 0;
        !           657: 
        !           658:        fis_h2d = (void*) &prdtl[slot].cfis;
        !           659:        fis_h2d->fis_type = FIS_TYPE_REG_H2D;
        !           660:        fis_h2d->flags = 128;
        !           661:        fis_h2d->command = WIN_IDENTIFY;
        !           662:        fis_h2d->device = 0;
        !           663: 
        !           664:        /* Fetch the 512 identify data */
        !           665:        memset(&id, 0, sizeof(id));
        !           666: 
        !           667:        command[slot].opts = sizeof(*fis_h2d) / sizeof(u32);
        !           668: 
        !           669:        first_part = PAGE_ALIGN((unsigned long) &id) - (unsigned long) &id;
        !           670: 
        !           671:        if (first_part && first_part < sizeof(id)) {
        !           672:                /* split over two pages */
        !           673: 
        !           674:                command[slot].opts |= (2 << 16);
        !           675: 
        !           676:                prdtl[slot].prdtl[0].dbau = 0;
        !           677:                prdtl[slot].prdtl[0].dba = vmtophys((void*) &id);
        !           678:                prdtl[slot].prdtl[0].dbc = first_part - 1;
        !           679:                prdtl[slot].prdtl[1].dbau = 0;
        !           680:                prdtl[slot].prdtl[1].dba = vmtophys((void*) &id + first_part);
        !           681:                prdtl[slot].prdtl[1].dbc = sizeof(id) - first_part - 1;
        !           682:        }
        !           683:        else
        !           684:        {
        !           685:                command[slot].opts |= (1 << 16);
        !           686: 
        !           687:                prdtl[slot].prdtl[0].dbau = 0;
        !           688:                prdtl[slot].prdtl[0].dba = vmtophys((void*) &id);
        !           689:                prdtl[slot].prdtl[0].dbc = sizeof(id) - 1;
        !           690:        }
        !           691: 
        !           692:        timeout = jiffies + WAIT_MAX;
        !           693:        while (readl(&ahci_port->tfd) & (BUSY_STAT | DRQ_STAT))
        !           694:                if (jiffies > timeout) {
        !           695:                        printk("sd%u: timeout waiting for ready\n", port-ports);
        !           696:                        port->ahci_host = NULL;
        !           697:                        port->ahci_port = NULL;
        !           698:                        return;
        !           699:                }
        !           700: 
        !           701:        save_flags(flags);
        !           702:        cli();
        !           703: 
        !           704:        port->identify = 1;
        !           705:        port->status = 0;
        !           706: 
        !           707:        /* Issue command */
        !           708:        mb();
        !           709:        writel(1 << slot, &ahci_port->ci);
        !           710: 
        !           711:        timeout = jiffies + WAIT_MAX;
        !           712:        identify_timer.expires = timeout;
        !           713:        identify_timer.data = (unsigned long) port;
        !           714:        add_timer(&identify_timer);
        !           715:        while (!port->status) {
        !           716:                if (jiffies >= timeout) {
        !           717:                        printk("sd%u: timeout waiting for ready\n", port-ports);
        !           718:                        port->ahci_host = NULL;
        !           719:                        port->ahci_port = NULL;
        !           720:                        del_timer(&identify_timer);
        !           721:                        return;
        !           722:                }
        !           723:                sleep_on(&port->q);
        !           724:        }
        !           725:        del_timer(&identify_timer);
        !           726:        restore_flags(flags);
        !           727: 
        !           728:        if (readl(&ahci_port->is) & PORT_IRQ_TF_ERR)
        !           729:        {
        !           730:                printk("sd%u: identify error\n", port-ports);
        !           731:                port->capacity = 0;
        !           732:                port->lba48 = 0;
        !           733:        } else {
        !           734:                ide_fixstring(id.model,     sizeof(id.model),     1);
        !           735:                ide_fixstring(id.fw_rev,    sizeof(id.fw_rev),    1);
        !           736:                ide_fixstring(id.serial_no, sizeof(id.serial_no), 1);
        !           737:                if (id.command_set_2 & (1U<<10))
        !           738:                {
        !           739:                        port->lba48 = 1;
        !           740:                        port->capacity = id.lba_capacity_2;
        !           741:                        if (port->capacity >= (1ULL << 32))
        !           742:                        {
        !           743:                                port->capacity = (1ULL << 32) - 1;
        !           744:                                printk("Warning: truncating disk size to 2TiB\n");
        !           745:                        }
        !           746:                }
        !           747:                else
        !           748:                {
        !           749:                        port->lba48 = 0;
        !           750:                        port->capacity = id.lba_capacity;
        !           751:                        if (port->capacity > (1ULL << 24))
        !           752:                        {
        !           753:                                port->capacity = (1ULL << 24);
        !           754:                                printk("Warning: truncating disk size to 128GiB\n");
        !           755:                        }
        !           756:                }
        !           757:                if (port->capacity/2048 >= 10240)
        !           758:                        printk("sd%u: %s, %uGB w/%dkB Cache\n", port - ports, id.model, (unsigned) (port->capacity/(2048*1024)), id.buf_size/2);
        !           759:                else
        !           760:                        printk("sd%u: %s, %uMB w/%dkB Cache\n", port - ports, id.model, (unsigned) (port->capacity/2048), id.buf_size/2);
        !           761:        }
        !           762:        port->identify = 0;
        !           763: }
        !           764: 
        !           765: /* Probe one AHCI PCI device */
        !           766: static void ahci_probe_dev(unsigned char bus, unsigned char device)
        !           767: {
        !           768:        unsigned char hdrtype;
        !           769:        unsigned char dev, fun;
        !           770:        const volatile struct ahci_host *ahci_host;
        !           771:        const volatile struct ahci_port *ahci_port;
        !           772:        unsigned nports, n, i;
        !           773:        unsigned port_map;
        !           774:        unsigned bar;
        !           775:        unsigned char irq;
        !           776: 
        !           777:        dev = PCI_SLOT(device);
        !           778:        fun = PCI_FUNC(device);
        !           779: 
        !           780:        /* Get configuration */
        !           781:        if (pcibios_read_config_byte(bus, device, PCI_HEADER_TYPE, &hdrtype) != PCIBIOS_SUCCESSFUL) {
        !           782:                printk("ahci: %02u:%02u.%u: Can not read configuration", bus, dev, fun);
        !           783:                return;
        !           784:        }
        !           785: 
        !           786:        if (hdrtype != 0) {
        !           787:                printk("ahci: %02u:%02u.%u: Unknown hdrtype %d\n", bus, dev, fun, hdrtype);
        !           788:                return;
        !           789:        }
        !           790: 
        !           791:        if (pcibios_read_config_dword(bus, device, PCI_BASE_ADDRESS_5, &bar) != PCIBIOS_SUCCESSFUL) {
        !           792:                printk("ahci: %02u:%02u.%u: Can not read BAR 5", bus, dev, fun);
        !           793:                return;
        !           794:        }
        !           795:        if (bar & 0x01) {
        !           796:                printk("ahci: %02u:%02u.%u: BAR 5 is I/O?!", bus, dev, fun);
        !           797:                return;
        !           798:        }
        !           799:        bar &= ~0x0f;
        !           800: 
        !           801:        if (pcibios_read_config_byte(bus, device, PCI_INTERRUPT_LINE, &irq) != PCIBIOS_SUCCESSFUL) {
        !           802:                printk("ahci: %02u:%02u.%u: Can not read IRQ", bus, dev, fun);
        !           803:                return;
        !           804:        }
        !           805: 
        !           806:        printk("AHCI SATA %02u:%02u.%u BAR 0x%x IRQ %u\n", bus, dev, fun, bar, irq);
        !           807: 
        !           808:        /* Map mmio */
        !           809:        ahci_host = vremap(bar, 0x2000);
        !           810: 
        !           811:        /* Request IRQ */
        !           812:        if (request_irq(irq, &ahci_interrupt, SA_SHIRQ, "ahci", (void*) ahci_host)) {
        !           813:                printk("ahci: %02u:%02u.%u: Can not get irq %u\n", bus, dev, fun, irq);
        !           814:                return;
        !           815:        }
        !           816: 
        !           817:        nports = (readl(&ahci_host->cap) & 0x1f) + 1;
        !           818:        port_map = readl(&ahci_host->pi);
        !           819: 
        !           820:        for (n = 0, i = 0; i < AHCI_MAX_PORTS; i++)
        !           821:                if (port_map & (1U << i))
        !           822:                        n++;
        !           823: 
        !           824:        if (nports != n) {
        !           825:                printk("ahci: %02u:%02u.%u: Odd number of ports, assuming %d is correct\n", bus, dev, fun, nports);
        !           826:                port_map = 0;
        !           827:        }
        !           828:        if (!port_map) {
        !           829:                port_map = (1U << nports) - 1;
        !           830:        }
        !           831: 
        !           832:        for (i = 0; i < AHCI_MAX_PORTS; i++) {
        !           833:                u32 ssts;
        !           834: 
        !           835:                if (!(port_map & (1U << i)))
        !           836:                        continue;
        !           837: 
        !           838:                ahci_port = &ahci_host->ports[i];
        !           839: 
        !           840:                ssts = readl(&ahci_port->ssts);
        !           841:                if ((ssts & 0xf) != 0x3)
        !           842:                        /* Device not present */
        !           843:                        continue;
        !           844:                if (((ssts >> 8) & 0xf) != 0x1)
        !           845:                        /* Device down */
        !           846:                        continue;
        !           847: 
        !           848:                /* OK! Probe this port */
        !           849:                ahci_probe_port(ahci_host, ahci_port);
        !           850:        }
        !           851: }
        !           852: 
        !           853: /* genhd callback to set size of disks */
        !           854: static void ahci_geninit(struct gendisk *gd)
        !           855: {
        !           856:        unsigned unit;
        !           857:        struct port *port;
        !           858: 
        !           859:        for (unit = 0; unit < gd->nr_real; unit++) {
        !           860:                port = &ports[unit];
        !           861:                port->part[0].nr_sects = port->capacity;
        !           862:        }
        !           863: }
        !           864: 
        !           865: /* Probe all AHCI PCI devices */
        !           866: void ahci_probe_pci(void)
        !           867: {
        !           868:        unsigned char bus, device;
        !           869:        unsigned short index;
        !           870:        int ret;
        !           871:        unsigned nports, unit, nminors;
        !           872:        struct port *port;
        !           873:        struct gendisk *gd, **gdp;
        !           874:        int *bs;
        !           875: 
        !           876:        for (index = 0;
        !           877:                (ret = pcibios_find_class(PCI_CLASS_STORAGE_SATA_AHCI, index, &bus, &device)) == PCIBIOS_SUCCESSFUL;
        !           878:                index++)
        !           879:        {
        !           880:                /* Note: this prevents from also having a SCSI controler.
        !           881:                 * It shouldn't harm too much until we have proper hardware
        !           882:                 * enumeration.
        !           883:                 */
        !           884:                if (register_blkdev(MAJOR_NR, "sd", &ahci_fops) < 0)
        !           885:                        printk("could not register ahci\n");
        !           886:                ahci_probe_dev(bus, device);
        !           887:        }
        !           888: 
        !           889:        for (nports = 0, port = &ports[0]; port < &ports[MAX_PORTS]; port++)
        !           890:                if (port->ahci_port)
        !           891:                        nports++;
        !           892: 
        !           893:        nminors = nports * (1<<PARTN_BITS);
        !           894: 
        !           895:        gd              = kmalloc(sizeof(*gd), GFP_KERNEL);
        !           896:        gd->sizes       = kmalloc(nminors * sizeof(*gd->sizes), GFP_KERNEL);
        !           897:        gd->part        = kmalloc(nminors * sizeof(*gd->part), GFP_KERNEL);
        !           898:        bs              = kmalloc(nminors * sizeof(*bs), GFP_KERNEL);
        !           899: 
        !           900:        blksize_size[MAJOR_NR] = bs;
        !           901:        for (unit = 0; unit < nminors; unit++)
        !           902:                /* We prefer to transfer whole pages */
        !           903:                *bs++ = PAGE_SIZE;
        !           904: 
        !           905:        memset(gd->part, 0, nminors * sizeof(*gd->part));
        !           906: 
        !           907:        for (unit = 0; unit < nports; unit++) {
        !           908:                ports[unit].gd = gd;
        !           909:                ports[unit].part = &gd->part[unit << PARTN_BITS];
        !           910:        }
        !           911: 
        !           912:        gd->major       = MAJOR_NR;
        !           913:        gd->major_name  = "sd";
        !           914:        gd->minor_shift = PARTN_BITS;
        !           915:        gd->max_p       = 1<<PARTN_BITS;
        !           916:        gd->max_nr      = nports;
        !           917:        gd->nr_real     = nports;
        !           918:        gd->init        = ahci_geninit;
        !           919:        gd->next        = NULL;
        !           920: 
        !           921:        for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
        !           922:                ;
        !           923:        *gdp = gd;
        !           924: 
        !           925:        blk_dev[MAJOR_NR].request_fn = ahci_do_request;
        !           926: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.