The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mips/cavium/octeon_ebt3000_cf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /***********************license start***************
    2  *  Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
    3  *  reserved.
    4  *
    5  *
    6  *  Redistribution and use in source and binary forms, with or without
    7  *  modification, are permitted provided that the following conditions are
    8  *  met:
    9  *
   10  *      * Redistributions of source code must retain the above copyright
   11  *        notice, this list of conditions and the following disclaimer.
   12  *
   13  *      * Redistributions in binary form must reproduce the above
   14  *        copyright notice, this list of conditions and the following
   15  *        disclaimer in the documentation and/or other materials provided
   16  *        with the distribution.
   17  *
   18  *      * Neither the name of Cavium Networks nor the names of
   19  *        its contributors may be used to endorse or promote products
   20  *        derived from this software without specific prior written
   21  *        permission.
   22  *
   23  *  TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
   24  *  AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
   25  *  OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
   26  *  RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
   27  *  REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
   28  *  DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
   29  *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
   30  *  PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
   31  *  POSSESSION OR CORRESPONDENCE TO DESCRIPTION.  THE ENTIRE RISK ARISING OUT
   32  *  OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
   33  *
   34  *
   35  *  For any questions regarding licensing please contact marketing@caviumnetworks.com
   36  *
   37  ***********************license end**************************************/
   38 
   39 /*
   40  *  octeon_ebt3000_cf.c
   41  *
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __FBSDID("$FreeBSD: releng/10.3/sys/mips/cavium/octeon_ebt3000_cf.c 265999 2014-05-14 01:35:43Z ian $");
   46 
   47 #include <sys/param.h>
   48 #include <sys/bio.h>
   49 #include <sys/systm.h>
   50 #include <sys/sysctl.h>
   51 #include <sys/ata.h>
   52 #include <sys/bus.h>
   53 #include <sys/kernel.h>
   54 #include <sys/module.h>
   55 #include <sys/rman.h>
   56 #include <sys/power.h>
   57 #include <sys/smp.h>
   58 #include <sys/time.h>
   59 #include <sys/timetc.h>
   60 #include <sys/malloc.h>
   61 
   62 #include <geom/geom.h>
   63 
   64 #include <machine/clock.h>
   65 #include <machine/locore.h>
   66 #include <machine/md_var.h>
   67 #include <machine/cpuregs.h>
   68 
   69 #include <mips/cavium/octeon_pcmap_regs.h>
   70 
   71 #include <contrib/octeon-sdk/cvmx.h>
   72 
   73 /* ATA Commands */
   74 #define CMD_READ_SECTOR         0x20
   75 #define CMD_WRITE_SECTOR        0x30
   76 #define CMD_IDENTIFY            0xEC
   77 
   78 /* The ATA Task File */
   79 #define TF_DATA                 0x00
   80 #define TF_ERROR                0x01
   81 #define TF_PRECOMP              0x01
   82 #define TF_SECTOR_COUNT         0x02
   83 #define TF_SECTOR_NUMBER        0x03
   84 #define TF_CYL_LSB              0x04
   85 #define TF_CYL_MSB              0x05
   86 #define TF_DRV_HEAD             0x06
   87 #define TF_STATUS               0x07
   88 #define TF_COMMAND              0x07
   89 
   90 /* Status Register */
   91 #define STATUS_BSY              0x80    /* Drive is busy */
   92 #define STATUS_RDY              0x40    /* Drive is ready */
   93 #define STATUS_DF               0x20    /* Device fault */
   94 #define STATUS_DRQ              0x08    /* Data can be transferred */
   95 
   96 /* Miscelaneous */
   97 #define SECTOR_SIZE             512
   98 #define WAIT_DELAY              1000
   99 #define NR_TRIES                1000
  100 #define SWAP_SHORT(x)           ((x << 8) | (x >> 8))
  101 #define MODEL_STR_SIZE          40
  102 
  103 /* Globals */
  104 /*
  105  * There's three bus types supported by this driver.
  106  *
  107  * CF_8 -- Traditional PC Card IDE interface on an 8-bit wide bus.  We assume
  108  * the bool loader has configure attribute memory properly.  We then access
  109  * the device like old-school 8-bit IDE card (which is all a traditional PC Card
  110  * interface really is).
  111  * CF_16 -- Traditional PC Card IDE interface on a 16-bit wide bus.  Registers on
  112  * this bus are 16-bits wide too.  When accessing registers in the task file, you
  113  * have to do it in 16-bit chunks, and worry about masking out what you don't want
  114  * or ORing together the traditional 8-bit values.  We assume the bootloader does
  115  * the right attribute memory initialization dance.
  116  * CF_TRUE_IDE_8 - CF Card wired to True IDE mode.  There's no Attribute memory
  117  * space at all.  Instead all the traditional 8-bit registers are there, but
  118  * on a 16-bit bus where addr0 isn't wired.  This means we need to read/write them
  119  * 16-bit chunks, but only the lower 8 bits are valid.  We do not (and can not)
  120  * access this like CF_16 with the comingled registers.  Yet we can't access
  121  * this like CF_8 because of the register offset.  Except the TF_DATA register
  122  * appears to be full width?
  123  */
  124 void    *base_addr;
  125 int     bus_type;
  126 #define CF_8            1       /* 8-bit bus, no offsets - PC Card */
  127 #define CF_16           2       /* 16-bit bus, registers shared - PC Card */
  128 #define CF_TRUE_IDE_8   3       /* 16-bit bus, only lower 8-bits, TrueIDE */
  129 const char *const cf_type[] = {
  130         "impossible type",
  131         "CF 8-bit",
  132         "CF 16-bit",
  133         "True IDE"
  134 };
  135 
  136 /* Device parameters */
  137 struct drive_param{
  138         union {
  139                 char buf[SECTOR_SIZE];
  140                 struct ata_params driveid;
  141         } u;
  142 
  143         char model[MODEL_STR_SIZE];
  144         uint32_t nr_sectors;
  145         uint16_t sector_size;
  146         uint16_t heads;
  147         uint16_t tracks;
  148         uint16_t sec_track;
  149 };
  150 
  151 /* Device softc */
  152 struct cf_priv {
  153         device_t dev;
  154         struct drive_param drive_param;
  155 
  156         struct bio_queue_head cf_bq;
  157         struct g_geom *cf_geom;
  158         struct g_provider *cf_provider;
  159 
  160 };
  161 
  162 /* GEOM class implementation */
  163 static g_access_t       cf_access;
  164 static g_start_t        cf_start;
  165 static g_ioctl_t        cf_ioctl;
  166 
  167 struct g_class g_cf_class = {
  168         .name =         "CF",
  169         .version =      G_VERSION,
  170         .start =        cf_start,
  171         .access =       cf_access,
  172         .ioctl =        cf_ioctl,
  173 };
  174 
  175 DECLARE_GEOM_CLASS(g_cf_class, g_cf);
  176 
  177 /* Device methods */
  178 static int      cf_probe(device_t);
  179 static void     cf_identify(driver_t *, device_t);
  180 static int      cf_attach(device_t);
  181 static void     cf_attach_geom(void *, int);
  182 
  183 /* ATA methods */
  184 static int      cf_cmd_identify(struct cf_priv *);
  185 static int      cf_cmd_write(uint32_t, uint32_t, void *);
  186 static int      cf_cmd_read(uint32_t, uint32_t, void *);
  187 static int      cf_wait_busy(void);
  188 static int      cf_send_cmd(uint32_t, uint8_t);
  189 
  190 /* Miscelenous */
  191 static void     cf_swap_ascii(unsigned char[], char[]);
  192 
  193 
  194 /* ------------------------------------------------------------------- *
  195  *                      cf_access()                                    *
  196  * ------------------------------------------------------------------- */
  197 static int cf_access (struct g_provider *pp, int r, int w, int e)
  198 {
  199         return (0);
  200 }
  201 
  202 
  203 /* ------------------------------------------------------------------- *
  204  *                      cf_start()                                     *
  205  * ------------------------------------------------------------------- */
  206 static void cf_start (struct bio *bp)
  207 {
  208         struct cf_priv *cf_priv;
  209         int error;
  210 
  211         cf_priv = bp->bio_to->geom->softc;
  212 
  213         /*
  214         * Handle actual I/O requests. The request is passed down through
  215         * the bio struct.
  216         */
  217 
  218         if(bp->bio_cmd & BIO_GETATTR) {
  219                 if (g_handleattr_int(bp, "GEOM::fwsectors", cf_priv->drive_param.sec_track))
  220                         return;
  221                 if (g_handleattr_int(bp, "GEOM::fwheads", cf_priv->drive_param.heads))
  222                         return;
  223                 g_io_deliver(bp, ENOIOCTL);
  224                 return;
  225         }
  226 
  227         if ((bp->bio_cmd & (BIO_READ | BIO_WRITE))) {
  228 
  229                 if (bp->bio_cmd & BIO_READ) {
  230                         error = cf_cmd_read(bp->bio_length / cf_priv->drive_param.sector_size,
  231                             bp->bio_offset / cf_priv->drive_param.sector_size, bp->bio_data);
  232                 } else if (bp->bio_cmd & BIO_WRITE) {
  233                         error = cf_cmd_write(bp->bio_length / cf_priv->drive_param.sector_size,
  234                             bp->bio_offset/cf_priv->drive_param.sector_size, bp->bio_data);
  235                 } else {
  236                         printf("%s: unrecognized bio_cmd %x.\n", __func__, bp->bio_cmd);
  237                         error = ENOTSUP;
  238                 }
  239 
  240                 if (error != 0) {
  241                         g_io_deliver(bp, error);
  242                         return;
  243                 }
  244 
  245                 bp->bio_resid = 0;
  246                 bp->bio_completed = bp->bio_length;
  247                 g_io_deliver(bp, 0);
  248         }
  249 }
  250 
  251 
  252 static int cf_ioctl (struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td)
  253 {
  254         return (0);
  255 }
  256 
  257 
  258 static uint8_t cf_inb_8(int port)
  259 {
  260         /*
  261          * Traditional 8-bit PC Card/CF bus access.
  262          */
  263         if (bus_type == CF_8) {
  264                 volatile uint8_t *task_file = (volatile uint8_t *)base_addr;
  265                 return task_file[port];
  266         }
  267 
  268         /*
  269          * True IDE access.  lower 8 bits on a 16-bit bus (see above).
  270          */
  271         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  272         return task_file[port] & 0xff;
  273 }
  274 
  275 static void cf_outb_8(int port, uint8_t val)
  276 {
  277         /*
  278          * Traditional 8-bit PC Card/CF bus access.
  279          */
  280         if (bus_type == CF_8) {
  281                 volatile uint8_t *task_file = (volatile uint8_t *)base_addr;
  282                 task_file[port] = val;
  283                 return;
  284         }
  285 
  286         /*
  287          * True IDE access.  lower 8 bits on a 16-bit bus (see above).
  288          */
  289         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  290         task_file[port] = val & 0xff;
  291 }
  292 
  293 static uint8_t cf_inb_16(int port)
  294 {
  295         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  296         uint16_t val = task_file[port / 2];
  297         if (port & 1)
  298                 return (val >> 8) & 0xff;
  299         return val & 0xff;
  300 }
  301 
  302 static uint16_t cf_inw_16(int port)
  303 {
  304         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  305         uint16_t val = task_file[port / 2];
  306         return val;
  307 }
  308 
  309 static void cf_outw_16(int port, uint16_t val)
  310 {
  311         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  312         task_file[port / 2] = val;
  313 }
  314 
  315 /* ------------------------------------------------------------------- *
  316  *                      cf_cmd_read()                                  *
  317  * ------------------------------------------------------------------- *
  318  *
  319  *  Read nr_sectors from the device starting from start_sector.
  320  */
  321 static int cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf)
  322 {
  323         unsigned long lba;
  324         uint32_t count;
  325         uint16_t *ptr_16;
  326         uint8_t  *ptr_8;
  327         int error;
  328 
  329         ptr_8  = (uint8_t*)buf;
  330         ptr_16 = (uint16_t*)buf;
  331         lba = start_sector; 
  332 
  333         while (nr_sectors--) {
  334                 error = cf_send_cmd(lba, CMD_READ_SECTOR);
  335                 if (error != 0) {
  336                         printf("%s: cf_send_cmd(CMD_READ_SECTOR) failed: %d\n", __func__, error);
  337                         return (error);
  338                 }
  339 
  340                 switch (bus_type)
  341                 {
  342                 case CF_8:
  343                         for (count = 0; count < SECTOR_SIZE; count++) {
  344                                 *ptr_8++ = cf_inb_8(TF_DATA);
  345                                 if ((count & 0xf) == 0)
  346                                         (void)cf_inb_8(TF_STATUS);
  347                         }
  348                         break;
  349                 case CF_TRUE_IDE_8:
  350                 case CF_16:
  351                 default:
  352                         for (count = 0; count < SECTOR_SIZE; count+=2) {
  353                                 uint16_t temp;
  354                                 temp = cf_inw_16(TF_DATA);
  355                                 *ptr_16++ = SWAP_SHORT(temp);
  356                                 if ((count & 0xf) == 0)
  357                                         (void)cf_inb_16(TF_STATUS);
  358                         }
  359                         break;
  360                 }  
  361 
  362                 lba++;
  363         }
  364         return (0);
  365 }
  366 
  367 
  368 /* ------------------------------------------------------------------- *
  369  *                      cf_cmd_write()                                 *
  370  * ------------------------------------------------------------------- *
  371  *
  372  * Write nr_sectors to the device starting from start_sector.
  373  */
  374 static int cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
  375 {
  376         uint32_t lba;
  377         uint32_t count;
  378         uint16_t *ptr_16;
  379         uint8_t  *ptr_8;
  380         int error;
  381         
  382         lba = start_sector;
  383         ptr_8  = (uint8_t*)buf;
  384         ptr_16 = (uint16_t*)buf;
  385 
  386         while (nr_sectors--) {
  387                 error = cf_send_cmd(lba, CMD_WRITE_SECTOR);
  388                 if (error != 0) {
  389                         printf("%s: cf_send_cmd(CMD_WRITE_SECTOR) failed: %d\n", __func__, error);
  390                         return (error);
  391                 }
  392 
  393                 switch (bus_type)
  394                 {
  395                 case CF_8:
  396                         for (count = 0; count < SECTOR_SIZE; count++) {
  397                                 cf_outb_8(TF_DATA, *ptr_8++);
  398                                 if ((count & 0xf) == 0)
  399                                         (void)cf_inb_8(TF_STATUS);
  400                         }
  401                         break;
  402                 case CF_TRUE_IDE_8:
  403                 case CF_16:
  404                 default:
  405                         for (count = 0; count < SECTOR_SIZE; count+=2) {
  406                                 uint16_t temp = *ptr_16++;
  407                                 cf_outw_16(TF_DATA, SWAP_SHORT(temp));
  408                                 if ((count & 0xf) == 0)
  409                                         (void)cf_inb_16(TF_STATUS);
  410                         }
  411                         break;
  412                 } 
  413 
  414                 lba++;
  415         }
  416         return (0);
  417 }
  418 
  419 
  420 /* ------------------------------------------------------------------- *
  421  *                      cf_cmd_identify()                              *
  422  * ------------------------------------------------------------------- *
  423  *
  424  * Read parameters and other information from the drive and store 
  425  * it in the drive_param structure
  426  *
  427  */
  428 static int cf_cmd_identify(struct cf_priv *cf_priv)
  429 {
  430         int count;
  431         int error;
  432 
  433         error = cf_send_cmd(0, CMD_IDENTIFY);
  434         if (error != 0) {
  435                 printf("%s: identify failed: %d\n", __func__, error);
  436                 return (error);
  437         }
  438         switch (bus_type)
  439         {
  440         case CF_8:
  441                 for (count = 0; count < SECTOR_SIZE; count++) 
  442                         cf_priv->drive_param.u.buf[count] = cf_inb_8(TF_DATA);
  443                 break;
  444         case CF_TRUE_IDE_8:
  445         case CF_16:
  446         default:
  447                 for (count = 0; count < SECTOR_SIZE; count += 2) {
  448                         uint16_t temp;
  449                         temp = cf_inw_16(TF_DATA);
  450                                 
  451                         /* endianess will be swapped below */
  452                         cf_priv->drive_param.u.buf[count]   = (temp & 0xff);
  453                         cf_priv->drive_param.u.buf[count + 1] = (temp & 0xff00) >> 8;
  454                 }
  455                 break;
  456         }
  457 
  458         cf_swap_ascii(cf_priv->drive_param.u.driveid.model, cf_priv->drive_param.model);
  459 
  460         cf_priv->drive_param.sector_size =  512;   //=  SWAP_SHORT (cf_priv->drive_param.u.driveid.sector_bytes);
  461         cf_priv->drive_param.heads      =  SWAP_SHORT (cf_priv->drive_param.u.driveid.current_heads);
  462         cf_priv->drive_param.tracks     =  SWAP_SHORT (cf_priv->drive_param.u.driveid.current_cylinders); 
  463         cf_priv->drive_param.sec_track   =  SWAP_SHORT (cf_priv->drive_param.u.driveid.current_sectors);
  464         cf_priv->drive_param.nr_sectors  = (uint32_t)SWAP_SHORT (cf_priv->drive_param.u.driveid.lba_size_1) |
  465             ((uint32_t)SWAP_SHORT (cf_priv->drive_param.u.driveid.lba_size_2));
  466         if (bootverbose) {
  467                 printf("    model %s\n", cf_priv->drive_param.model);
  468                 printf("    heads %d tracks %d sec_tracks %d sectors %d\n",
  469                         cf_priv->drive_param.heads, cf_priv->drive_param.tracks,
  470                         cf_priv->drive_param.sec_track, cf_priv->drive_param.nr_sectors);
  471         }
  472 
  473         return (0);
  474 }
  475 
  476 
  477 /* ------------------------------------------------------------------- *
  478  *                      cf_send_cmd()                                  *
  479  * ------------------------------------------------------------------- *
  480  *
  481  * Send command to read/write one sector specified by lba.
  482  *
  483  */
  484 static int cf_send_cmd (uint32_t lba, uint8_t cmd)
  485 {
  486         switch (bus_type)
  487         {
  488         case CF_8:
  489         case CF_TRUE_IDE_8:
  490                 while (cf_inb_8(TF_STATUS) & STATUS_BSY)
  491                         DELAY(WAIT_DELAY);
  492                 cf_outb_8(TF_SECTOR_COUNT, 1);
  493                 cf_outb_8(TF_SECTOR_NUMBER, lba & 0xff);
  494                 cf_outb_8(TF_CYL_LSB, (lba >> 8) & 0xff);
  495                 cf_outb_8(TF_CYL_MSB, (lba >> 16) & 0xff);
  496                 cf_outb_8(TF_DRV_HEAD, ((lba >> 24) & 0xff) | 0xe0);
  497                 cf_outb_8(TF_COMMAND, cmd);
  498                 break;
  499         case CF_16:
  500         default:
  501                 while (cf_inb_16(TF_STATUS) & STATUS_BSY)
  502                         DELAY(WAIT_DELAY);
  503                 cf_outw_16(TF_SECTOR_COUNT, 1 | ((lba & 0xff) << 8));
  504                 cf_outw_16(TF_CYL_LSB, ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8));
  505                 cf_outw_16(TF_DRV_HEAD, (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8));
  506                 break;
  507         }
  508 
  509         return (cf_wait_busy());
  510 }
  511 
  512 /* ------------------------------------------------------------------- *
  513  *                      cf_wait_busy()                                 *
  514  * ------------------------------------------------------------------- *
  515  *
  516  * Wait until the drive finishes a given command and data is
  517  * ready to be transferred. This is done by repeatedly checking 
  518  * the BSY bit of the status register. When the controller is ready for
  519  * data transfer, it clears the BSY bit and sets the DRQ bit.
  520  *
  521  * If the DF bit is ever set, we return error.
  522  *
  523  * This code originally spun on DRQ.  If that behavior turns out to be
  524  * necessary, a flag can be added or this function can be called
  525  * repeatedly as long as it is returning ENXIO.
  526  */
  527 static int cf_wait_busy (void)
  528 {
  529         uint8_t status;
  530 
  531         switch (bus_type)
  532         {
  533         case CF_8:
  534         case CF_TRUE_IDE_8:
  535                 status = cf_inb_8(TF_STATUS);
  536                 while ((status & STATUS_BSY) == STATUS_BSY) {
  537                         if ((status & STATUS_DF) != 0) {
  538                                 printf("%s: device fault (status=%x)\n", __func__, status);
  539                                 return (EIO);
  540                         }
  541                         DELAY(WAIT_DELAY);
  542                         status = cf_inb_8(TF_STATUS);
  543                 }
  544                 break;
  545         case CF_16:
  546         default:
  547                 status = cf_inb_16(TF_STATUS);
  548                 while ((status & STATUS_BSY) == STATUS_BSY) {
  549                         if ((status & STATUS_DF) != 0) {
  550                                 printf("%s: device fault (status=%x)\n", __func__, status);
  551                                 return (EIO);
  552                         }
  553                         DELAY(WAIT_DELAY);
  554                         status = cf_inb_16(TF_STATUS);
  555                 }
  556                 break;
  557         }
  558 
  559         /* DRQ is only for when read data is actually available; check BSY */
  560         /* Some vendors do assert DRQ, but not all. Check BSY instead. */
  561         if (status & STATUS_BSY) {
  562                 printf("%s: device not ready (status=%x)\n", __func__, status);
  563                 return (ENXIO);
  564         }
  565 
  566         return (0);
  567 }
  568 
  569 /* ------------------------------------------------------------------- *
  570  *                      cf_swap_ascii()                                *
  571  * ------------------------------------------------------------------- *
  572  *
  573  * The ascii string returned by the controller specifying 
  574  * the model of the drive is byte-swaped. This routine 
  575  * corrects the byte ordering.
  576  *
  577  */
  578 static void cf_swap_ascii (unsigned char str1[], char str2[])
  579 {
  580         int i;
  581 
  582         for(i = 0; i < MODEL_STR_SIZE; i++)
  583                 str2[i] = str1[i ^ 1];
  584 }
  585 
  586 
  587 /* ------------------------------------------------------------------- *
  588  *                      cf_probe()                                     *
  589  * ------------------------------------------------------------------- */
  590 
  591 static int cf_probe (device_t dev)
  592 {
  593         if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
  594                 return (ENXIO);
  595 
  596         if (device_get_unit(dev) != 0) {
  597                 panic("can't attach more devices\n");
  598         }
  599 
  600         device_set_desc(dev, "Octeon Compact Flash Driver");
  601 
  602         return (BUS_PROBE_NOWILDCARD);
  603 }
  604 
  605 /* ------------------------------------------------------------------- *
  606  *                      cf_identify()                                  *
  607  * ------------------------------------------------------------------- *
  608  *
  609  * Find the bootbus region for the CF to determine 
  610  * 16 or 8 bit and check to see if device is 
  611  * inserted.
  612  *
  613  */
  614 static void cf_identify (driver_t *drv, device_t parent)
  615 {
  616         int bus_region;
  617         int count = 0;
  618         cvmx_mio_boot_reg_cfgx_t cfg;
  619         uint64_t phys_base;
  620         
  621         if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
  622                 return;
  623 
  624         phys_base = cvmx_sysinfo_get()->compact_flash_common_base_addr;
  625         if (phys_base == 0)
  626                 return;
  627         base_addr = cvmx_phys_to_ptr(phys_base);
  628 
  629         for (bus_region = 0; bus_region < 8; bus_region++)
  630         {
  631                 cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(bus_region));
  632                 if (cfg.s.base == phys_base >> 16)
  633                 {
  634                         if (cvmx_sysinfo_get()->compact_flash_attribute_base_addr == 0)
  635                                 bus_type = CF_TRUE_IDE_8;
  636                         else
  637                                 bus_type = (cfg.s.width) ? CF_16 : CF_8;
  638                         printf("Compact flash found in bootbus region %d (%s).\n", bus_region, cf_type[bus_type]);
  639                         break;
  640                 }
  641         }
  642 
  643         switch (bus_type)
  644         {
  645         case CF_8:
  646         case CF_TRUE_IDE_8:
  647                 /* Check if CF is inserted */
  648                 while (cf_inb_8(TF_STATUS) & STATUS_BSY) {
  649                         if ((count++) == NR_TRIES ) {
  650                                 printf("Compact Flash not present\n");
  651                                 return;
  652                         }
  653                         DELAY(WAIT_DELAY);
  654                 }
  655                 break;
  656         case CF_16:
  657         default:
  658                 /* Check if CF is inserted */
  659                 while (cf_inb_16(TF_STATUS) & STATUS_BSY) {
  660                         if ((count++) == NR_TRIES ) {
  661                                 printf("Compact Flash not present\n");
  662                                 return;
  663                         }
  664                         DELAY(WAIT_DELAY);
  665                 }
  666                 break;
  667         }
  668 
  669         BUS_ADD_CHILD(parent, 0, "cf", 0);
  670 }
  671 
  672 
  673 /* ------------------------------------------------------------------- *
  674  *                      cf_attach_geom()                               *
  675  * ------------------------------------------------------------------- */
  676 
  677 static void cf_attach_geom (void *arg, int flag)
  678 {
  679         struct cf_priv *cf_priv;
  680 
  681         cf_priv = (struct cf_priv *) arg;
  682         cf_priv->cf_geom = g_new_geomf(&g_cf_class, "cf%d", device_get_unit(cf_priv->dev));
  683         cf_priv->cf_geom->softc = cf_priv;
  684         cf_priv->cf_provider = g_new_providerf(cf_priv->cf_geom, cf_priv->cf_geom->name);
  685         cf_priv->cf_provider->sectorsize = cf_priv->drive_param.sector_size;
  686         cf_priv->cf_provider->mediasize = cf_priv->drive_param.nr_sectors * cf_priv->cf_provider->sectorsize;
  687         g_error_provider(cf_priv->cf_provider, 0);
  688 }
  689 
  690 /* ------------------------------------------------------------------- *
  691  *                      cf_attach()                                    *
  692  * ------------------------------------------------------------------- */
  693 
  694 static int cf_attach (device_t dev)
  695 {
  696         struct cf_priv *cf_priv;
  697         int error;
  698 
  699         if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM)
  700                 return (ENXIO);
  701 
  702         cf_priv = device_get_softc(dev);
  703         cf_priv->dev = dev;
  704 
  705         error = cf_cmd_identify(cf_priv);
  706         if (error != 0) {
  707                 device_printf(dev, "cf_cmd_identify failed: %d\n", error);
  708                 return (error);
  709         }
  710 
  711         g_post_event(cf_attach_geom, cf_priv, M_WAITOK, NULL);
  712         bioq_init(&cf_priv->cf_bq);
  713 
  714         return 0;
  715 }
  716 
  717 
  718 static device_method_t cf_methods[] = {
  719         /* Device interface */
  720         DEVMETHOD(device_probe,         cf_probe),
  721         DEVMETHOD(device_identify,      cf_identify),
  722         DEVMETHOD(device_attach,        cf_attach),
  723         DEVMETHOD(device_detach,        bus_generic_detach),
  724         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  725 
  726         { 0, 0 }
  727 };
  728 
  729 static driver_t cf_driver = {
  730         "cf", 
  731         cf_methods, 
  732         sizeof(struct cf_priv)
  733 };
  734 
  735 static devclass_t cf_devclass;
  736 
  737 DRIVER_MODULE(cf, nexus, cf_driver, cf_devclass, 0, 0);

Cache object: 52378cb3d3dd596e45bd83c471671628


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.