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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
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: stable/9/sys/mips/cavium/octeon_ebt3000_cf.c 222671 2011-06-04 07:06:05Z imp $");
   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 /* XXX */
  104 extern cvmx_bootinfo_t *octeon_bootinfo;
  105 
  106 /* Globals */
  107 /*
  108  * There's three bus types supported by this driver.
  109  *
  110  * CF_8 -- Traditional PC Card IDE interface on an 8-bit wide bus.  We assume
  111  * the bool loader has configure attribute memory properly.  We then access
  112  * the device like old-school 8-bit IDE card (which is all a traditional PC Card
  113  * interface really is).
  114  * CF_16 -- Traditional PC Card IDE interface on a 16-bit wide bus.  Registers on
  115  * this bus are 16-bits wide too.  When accessing registers in the task file, you
  116  * have to do it in 16-bit chunks, and worry about masking out what you don't want
  117  * or ORing together the traditional 8-bit values.  We assume the bootloader does
  118  * the right attribute memory initialization dance.
  119  * CF_TRUE_IDE_8 - CF Card wired to True IDE mode.  There's no Attribute memory
  120  * space at all.  Instead all the traditional 8-bit registers are there, but
  121  * on a 16-bit bus where addr0 isn't wired.  This means we need to read/write them
  122  * 16-bit chunks, but only the lower 8 bits are valid.  We do not (and can not)
  123  * access this like CF_16 with the comingled registers.  Yet we can't access
  124  * this like CF_8 because of the register offset.  Except the TF_DATA register
  125  * appears to be full width?
  126  */
  127 void    *base_addr;
  128 int     bus_type;
  129 #define CF_8            1       /* 8-bit bus, no offsets - PC Card */
  130 #define CF_16           2       /* 16-bit bus, registers shared - PC Card */
  131 #define CF_TRUE_IDE_8   3       /* 16-bit bus, only lower 8-bits, TrueIDE */
  132 const char *const cf_type[] = {
  133         "impossible type",
  134         "CF 8-bit",
  135         "CF 16-bit",
  136         "True IDE"
  137 };
  138 
  139 /* Device softc */
  140 struct cf_priv {
  141         device_t dev;
  142         struct drive_param *drive_param;
  143 
  144         struct bio_queue_head cf_bq;
  145         struct g_geom *cf_geom;
  146         struct g_provider *cf_provider;
  147 
  148 };
  149 
  150 /* Device parameters */
  151 struct drive_param{
  152         union {
  153                 char buf[SECTOR_SIZE];
  154                 struct ata_params driveid;
  155         } u;
  156 
  157         char model[MODEL_STR_SIZE];
  158         uint32_t nr_sectors;
  159         uint16_t sector_size;
  160         uint16_t heads;
  161         uint16_t tracks;
  162         uint16_t sec_track;
  163 
  164 } drive_param;
  165 
  166 /* GEOM class implementation */
  167 static g_access_t       cf_access;
  168 static g_start_t        cf_start;
  169 static g_ioctl_t        cf_ioctl;
  170 
  171 struct g_class g_cf_class = {
  172         .name =         "CF",
  173         .version =      G_VERSION,
  174         .start =        cf_start,
  175         .access =       cf_access,
  176         .ioctl =        cf_ioctl,
  177 };
  178 
  179 DECLARE_GEOM_CLASS(g_cf_class, g_cf);
  180 
  181 /* Device methods */
  182 static int      cf_probe(device_t);
  183 static void     cf_identify(driver_t *, device_t);
  184 static int      cf_attach(device_t);
  185 static int      cf_attach_geom(void *, int);
  186 
  187 /* ATA methods */
  188 static int      cf_cmd_identify(void);
  189 static int      cf_cmd_write(uint32_t, uint32_t, void *);
  190 static int      cf_cmd_read(uint32_t, uint32_t, void *);
  191 static int      cf_wait_busy(void);
  192 static int      cf_send_cmd(uint32_t, uint8_t);
  193 static void     cf_attach_geom_proxy(void *arg, int flag);
  194 
  195 /* Miscelenous */
  196 static void     cf_swap_ascii(unsigned char[], char[]);
  197 
  198 
  199 /* ------------------------------------------------------------------- *
  200  *                      cf_access()                                    *
  201  * ------------------------------------------------------------------- */
  202 static int cf_access (struct g_provider *pp, int r, int w, int e)
  203 {
  204 
  205         pp->sectorsize = drive_param.sector_size;
  206         pp->stripesize = drive_param.heads * drive_param.sec_track * drive_param.sector_size;
  207         pp->mediasize  = pp->stripesize * drive_param.tracks;
  208 
  209         return (0);
  210 }
  211 
  212 
  213 /* ------------------------------------------------------------------- *
  214  *                      cf_start()                                     *
  215  * ------------------------------------------------------------------- */
  216 static void cf_start (struct bio *bp)
  217 {
  218         int error;
  219 
  220         /*
  221         * Handle actual I/O requests. The request is passed down through
  222         * the bio struct.
  223         */
  224 
  225         if(bp->bio_cmd & BIO_GETATTR) {
  226                 if (g_handleattr_int(bp, "GEOM::fwsectors", drive_param.sec_track))
  227                         return;
  228                 if (g_handleattr_int(bp, "GEOM::fwheads",   drive_param.heads))
  229                         return;
  230                 g_io_deliver(bp, ENOIOCTL);
  231                 return;
  232         }
  233 
  234         if ((bp->bio_cmd & (BIO_READ | BIO_WRITE))) {
  235 
  236                 if (bp->bio_cmd & BIO_READ) {
  237                         error = cf_cmd_read(bp->bio_length / drive_param.sector_size,
  238                             bp->bio_offset / drive_param.sector_size, bp->bio_data);
  239                 } else if (bp->bio_cmd & BIO_WRITE) {
  240                         error = cf_cmd_write(bp->bio_length / drive_param.sector_size,
  241                             bp->bio_offset/drive_param.sector_size, bp->bio_data);
  242                 } else {
  243                         printf("%s: unrecognized bio_cmd %x.\n", __func__, bp->bio_cmd);
  244                         error = ENOTSUP;
  245                 }
  246 
  247                 if (error != 0) {
  248                         g_io_deliver(bp, error);
  249                         return;
  250                 }
  251 
  252                 bp->bio_resid = 0;
  253                 bp->bio_completed = bp->bio_length;
  254                 g_io_deliver(bp, 0);
  255         }
  256 }
  257 
  258 
  259 static int cf_ioctl (struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td)
  260 {
  261         return (0);
  262 }
  263 
  264 
  265 static uint8_t cf_inb_8(int port)
  266 {
  267         /*
  268          * Traditional 8-bit PC Card/CF bus access.
  269          */
  270         if (bus_type == CF_8) {
  271                 volatile uint8_t *task_file = (volatile uint8_t *)base_addr;
  272                 return task_file[port];
  273         }
  274 
  275         /*
  276          * True IDE access.  lower 8 bits on a 16-bit bus (see above).
  277          */
  278         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  279         return task_file[port] & 0xff;
  280 }
  281 
  282 static void cf_outb_8(int port, uint8_t val)
  283 {
  284         /*
  285          * Traditional 8-bit PC Card/CF bus access.
  286          */
  287         if (bus_type == CF_8) {
  288                 volatile uint8_t *task_file = (volatile uint8_t *)base_addr;
  289                 task_file[port] = val;
  290         }
  291 
  292         /*
  293          * True IDE access.  lower 8 bits on a 16-bit bus (see above).
  294          */
  295         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  296         task_file[port] = val & 0xff;
  297 }
  298 
  299 static uint8_t cf_inb_16(int port)
  300 {
  301         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  302         uint16_t val = task_file[port / 2];
  303         if (port & 1)
  304                 return (val >> 8) & 0xff;
  305         return val & 0xff;
  306 }
  307 
  308 static uint16_t cf_inw_16(int port)
  309 {
  310         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  311         uint16_t val = task_file[port / 2];
  312         return val;
  313 }
  314 
  315 static void cf_outw_16(int port, uint16_t val)
  316 {
  317         volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
  318         task_file[port / 2] = val;
  319 }
  320 
  321 /* ------------------------------------------------------------------- *
  322  *                      cf_cmd_read()                                  *
  323  * ------------------------------------------------------------------- *
  324  *
  325  *  Read nr_sectors from the device starting from start_sector.
  326  */
  327 static int cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf)
  328 {
  329         unsigned long lba;
  330         uint32_t count;
  331         uint16_t *ptr_16;
  332         uint8_t  *ptr_8;
  333         int error;
  334 
  335 //#define OCTEON_VISUAL_CF_0 1
  336 #ifdef OCTEON_VISUAL_CF_0
  337         octeon_led_write_char(0, 'R');
  338 #endif
  339         ptr_8  = (uint8_t*)buf;
  340         ptr_16 = (uint16_t*)buf;
  341         lba = start_sector; 
  342 
  343 
  344         while (nr_sectors--) {
  345                 error = cf_send_cmd(lba, CMD_READ_SECTOR);
  346                 if (error != 0) {
  347                         printf("%s: cf_send_cmd(CMD_READ_SECTOR) failed: %d\n", __func__, error);
  348                         return (error);
  349                 }
  350 
  351                 switch (bus_type)
  352                 {
  353                 case CF_8:
  354                         for (count = 0; count < SECTOR_SIZE; count++) {
  355                                 *ptr_8++ = cf_inb_8(TF_DATA);
  356                                 if ((count & 0xf) == 0)
  357                                         (void)cf_inb_8(TF_STATUS);
  358                         }
  359                         break;
  360                 case CF_TRUE_IDE_8:
  361                 case CF_16:
  362                 default:
  363                         for (count = 0; count < SECTOR_SIZE; count+=2) {
  364                                 uint16_t temp;
  365                                 temp = cf_inw_16(TF_DATA);
  366                                 *ptr_16++ = SWAP_SHORT(temp);
  367                                 if ((count & 0xf) == 0)
  368                                         (void)cf_inb_16(TF_STATUS);
  369                         }
  370                         break;
  371                 }  
  372 
  373                 lba++;
  374         }
  375 #ifdef OCTEON_VISUAL_CF_0
  376         octeon_led_write_char(0, ' ');
  377 #endif
  378         return (0);
  379 }
  380 
  381 
  382 /* ------------------------------------------------------------------- *
  383  *                      cf_cmd_write()                                 *
  384  * ------------------------------------------------------------------- *
  385  *
  386  * Write nr_sectors to the device starting from start_sector.
  387  */
  388 static int cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
  389 {
  390         uint32_t lba;
  391         uint32_t count;
  392         uint16_t *ptr_16;
  393         uint8_t  *ptr_8;
  394         int error;
  395         
  396 //#define OCTEON_VISUAL_CF_1 1
  397 #ifdef OCTEON_VISUAL_CF_1
  398         octeon_led_write_char(1, 'W');
  399 #endif
  400         lba = start_sector;
  401         ptr_8  = (uint8_t*)buf;
  402         ptr_16 = (uint16_t*)buf;
  403 
  404         while (nr_sectors--) {
  405                 error = cf_send_cmd(lba, CMD_WRITE_SECTOR);
  406                 if (error != 0) {
  407                         printf("%s: cf_send_cmd(CMD_WRITE_SECTOR) failed: %d\n", __func__, error);
  408                         return (error);
  409                 }
  410 
  411                 switch (bus_type)
  412                 {
  413                 case CF_8:
  414                         for (count = 0; count < SECTOR_SIZE; count++) {
  415                                 cf_outb_8(TF_DATA, *ptr_8++);
  416                                 if ((count & 0xf) == 0)
  417                                         (void)cf_inb_8(TF_STATUS);
  418                         }
  419                         break;
  420                 case CF_TRUE_IDE_8:
  421                 case CF_16:
  422                 default:
  423                         for (count = 0; count < SECTOR_SIZE; count+=2) {
  424                                 uint16_t temp = *ptr_16++;
  425                                 cf_outw_16(TF_DATA, SWAP_SHORT(temp));
  426                                 if ((count & 0xf) == 0)
  427                                         (void)cf_inb_16(TF_STATUS);
  428                         }
  429                         break;
  430                 } 
  431 
  432                 lba++;
  433         }
  434 #ifdef OCTEON_VISUAL_CF_1
  435         octeon_led_write_char(1, ' ');
  436 #endif
  437         return (0);
  438 }
  439 
  440 
  441 /* ------------------------------------------------------------------- *
  442  *                      cf_cmd_identify()                              *
  443  * ------------------------------------------------------------------- *
  444  *
  445  * Read parameters and other information from the drive and store 
  446  * it in the drive_param structure
  447  *
  448  */
  449 static int cf_cmd_identify (void)
  450 {
  451         int count;
  452         int error;
  453 
  454         error = cf_send_cmd(0, CMD_IDENTIFY);
  455         if (error != 0) {
  456                 printf("%s: identify failed: %d\n", __func__, error);
  457                 return (error);
  458         }
  459         switch (bus_type)
  460         {
  461         case CF_8:
  462                 for (count = 0; count < SECTOR_SIZE; count++) 
  463                         drive_param.u.buf[count] = cf_inb_8(TF_DATA);
  464                 break;
  465         case CF_TRUE_IDE_8:
  466         case CF_16:
  467         default:
  468                 for (count = 0; count < SECTOR_SIZE; count += 2) {
  469                         uint16_t temp;
  470                         temp = cf_inw_16(TF_DATA);
  471                                 
  472                         /* endianess will be swapped below */
  473                         drive_param.u.buf[count]   = (temp & 0xff);
  474                         drive_param.u.buf[count + 1] = (temp & 0xff00) >> 8;
  475                 }
  476                 break;
  477         }
  478 
  479         cf_swap_ascii(drive_param.u.driveid.model, drive_param.model);
  480 
  481         drive_param.sector_size =  512;   //=  SWAP_SHORT (drive_param.u.driveid.sector_bytes);
  482         drive_param.heads       =  SWAP_SHORT (drive_param.u.driveid.current_heads);
  483         drive_param.tracks      =  SWAP_SHORT (drive_param.u.driveid.current_cylinders); 
  484         drive_param.sec_track   =  SWAP_SHORT (drive_param.u.driveid.current_sectors);
  485         drive_param.nr_sectors  = (uint32_t)SWAP_SHORT (drive_param.u.driveid.lba_size_1) |
  486             ((uint32_t)SWAP_SHORT (drive_param.u.driveid.lba_size_2));
  487         printf("cf0: <%s> %lld sectors\n", drive_param.model, (long long)drive_param.nr_sectors);
  488 
  489         return (0);
  490 }
  491 
  492 
  493 /* ------------------------------------------------------------------- *
  494  *                      cf_send_cmd()                                  *
  495  * ------------------------------------------------------------------- *
  496  *
  497  * Send command to read/write one sector specified by lba.
  498  *
  499  */
  500 static int cf_send_cmd (uint32_t lba, uint8_t cmd)
  501 {
  502         switch (bus_type)
  503         {
  504         case CF_8:
  505         case CF_TRUE_IDE_8:
  506                 while (cf_inb_8(TF_STATUS) & STATUS_BSY)
  507                         DELAY(WAIT_DELAY);
  508                 cf_outb_8(TF_SECTOR_COUNT, 1);
  509                 cf_outb_8(TF_SECTOR_NUMBER, lba & 0xff);
  510                 cf_outb_8(TF_CYL_LSB, (lba >> 8) & 0xff);
  511                 cf_outb_8(TF_CYL_MSB, (lba >> 16) & 0xff);
  512                 cf_outb_8(TF_DRV_HEAD, ((lba >> 24) & 0xff) | 0xe0);
  513                 cf_outb_8(TF_COMMAND, cmd);
  514                 break;
  515         case CF_16:
  516         default:
  517                 while (cf_inb_16(TF_STATUS) & STATUS_BSY)
  518                         DELAY(WAIT_DELAY);
  519                 cf_outw_16(TF_SECTOR_COUNT, 1 | ((lba & 0xff) << 8));
  520                 cf_outw_16(TF_CYL_LSB, ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8));
  521                 cf_outw_16(TF_DRV_HEAD, (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8));
  522                 break;
  523         }
  524 
  525         return (cf_wait_busy());
  526 }
  527 
  528 /* ------------------------------------------------------------------- *
  529  *                      cf_wait_busy()                                 *
  530  * ------------------------------------------------------------------- *
  531  *
  532  * Wait until the drive finishes a given command and data is
  533  * ready to be transferred. This is done by repeatedly checking 
  534  * the BSY bit of the status register. When the controller is ready for
  535  * data transfer, it clears the BSY bit and sets the DRQ bit.
  536  *
  537  * If the DF bit is ever set, we return error.
  538  *
  539  * This code originally spun on DRQ.  If that behavior turns out to be
  540  * necessary, a flag can be added or this function can be called
  541  * repeatedly as long as it is returning ENXIO.
  542  */
  543 static int cf_wait_busy (void)
  544 {
  545         uint8_t status;
  546 
  547 //#define OCTEON_VISUAL_CF_2 1
  548 #ifdef OCTEON_VISUAL_CF_2
  549         static int where0 = 0;
  550 
  551         octeon_led_run_wheel(&where0, 2);
  552 #endif
  553 
  554         switch (bus_type)
  555         {
  556         case CF_8:
  557         case CF_TRUE_IDE_8:
  558                 status = cf_inb_8(TF_STATUS);
  559                 while ((status & STATUS_BSY) == STATUS_BSY) {
  560                         if ((status & STATUS_DF) != 0) {
  561                                 printf("%s: device fault (status=%x)\n", __func__, status);
  562                                 return (EIO);
  563                         }
  564                         DELAY(WAIT_DELAY);
  565                         status = cf_inb_8(TF_STATUS);
  566                 }
  567                 break;
  568         case CF_16:
  569         default:
  570                 status = cf_inb_16(TF_STATUS);
  571                 while ((status & STATUS_BSY) == STATUS_BSY) {
  572                         if ((status & STATUS_DF) != 0) {
  573                                 printf("%s: device fault (status=%x)\n", __func__, status);
  574                                 return (EIO);
  575                         }
  576                         DELAY(WAIT_DELAY);
  577                         status = cf_inb_16(TF_STATUS);
  578                 }
  579                 break;
  580         }
  581         if ((status & STATUS_DRQ) == 0) {
  582                 printf("%s: device not ready (status=%x)\n", __func__, status);
  583                 return (ENXIO);
  584         }
  585 
  586 #ifdef OCTEON_VISUAL_CF_2
  587         octeon_led_write_char(2, ' ');
  588 #endif
  589         return (0);
  590 }
  591 
  592 /* ------------------------------------------------------------------- *
  593  *                      cf_swap_ascii()                                *
  594  * ------------------------------------------------------------------- *
  595  *
  596  * The ascii string returned by the controller specifying 
  597  * the model of the drive is byte-swaped. This routine 
  598  * corrects the byte ordering.
  599  *
  600  */
  601 static void cf_swap_ascii (unsigned char str1[], char str2[])
  602 {
  603         int i;
  604 
  605         for(i = 0; i < MODEL_STR_SIZE; i++)
  606                 str2[i] = str1[i ^ 1];
  607 }
  608 
  609 
  610 /* ------------------------------------------------------------------- *
  611  *                      cf_probe()                                     *
  612  * ------------------------------------------------------------------- */
  613 
  614 static int cf_probe (device_t dev)
  615 {
  616         if (octeon_is_simulation())
  617                 return (ENXIO);
  618 
  619         if (device_get_unit(dev) != 0) {
  620                 panic("can't attach more devices\n");
  621         }
  622 
  623         device_set_desc(dev, "Octeon Compact Flash Driver");
  624 
  625         return (cf_cmd_identify());
  626 }
  627 
  628 /* ------------------------------------------------------------------- *
  629  *                      cf_identify()                                  *
  630  * ------------------------------------------------------------------- *
  631  *
  632  * Find the bootbus region for the CF to determine 
  633  * 16 or 8 bit and check to see if device is 
  634  * inserted.
  635  *
  636  */
  637 typedef unsigned long long llu;
  638 static void cf_identify (driver_t *drv, device_t parent)
  639 {
  640         int bus_region;
  641         int count = 0;
  642         cvmx_mio_boot_reg_cfgx_t cfg;
  643 
  644         if (octeon_is_simulation())
  645                 return;
  646 
  647         base_addr = cvmx_phys_to_ptr(octeon_bootinfo->compact_flash_common_base_addr);
  648 
  649         for (bus_region = 0; bus_region < 8; bus_region++)
  650         {
  651                 cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(bus_region));
  652                 if (cfg.s.base == octeon_bootinfo->compact_flash_common_base_addr >> 16)
  653                 {
  654                         if (octeon_bootinfo->compact_flash_attribute_base_addr == 0)
  655                                 bus_type = CF_TRUE_IDE_8;
  656                         else
  657                                 bus_type = (cfg.s.width) ? CF_16 : CF_8;
  658                         printf("Compact flash found in bootbus region %d (%s).\n", bus_region, cf_type[bus_type]);
  659                         break;
  660                 }
  661         }
  662 
  663         switch (bus_type)
  664         {
  665         case CF_8:
  666         case CF_TRUE_IDE_8:
  667                 /* Check if CF is inserted */
  668                 while (cf_inb_8(TF_STATUS) & STATUS_BSY) {
  669                         if ((count++) == NR_TRIES ) {
  670                                 printf("Compact Flash not present\n");
  671                                 return;
  672                         }
  673                         DELAY(WAIT_DELAY);
  674                 }
  675                 break;
  676         case CF_16:
  677         default:
  678                 /* Check if CF is inserted */
  679                 while (cf_inb_16(TF_STATUS) & STATUS_BSY) {
  680                         if ((count++) == NR_TRIES ) {
  681                                 printf("Compact Flash not present\n");
  682                                 return;
  683                         }
  684                         DELAY(WAIT_DELAY);
  685                 }
  686                 break;
  687         }
  688 
  689         BUS_ADD_CHILD(parent, 0, "cf", 0);
  690 }
  691 
  692 
  693 /* ------------------------------------------------------------------- *
  694  *                      cf_attach_geom()                               *
  695  * ------------------------------------------------------------------- */
  696 
  697 static int cf_attach_geom (void *arg, int flag)
  698 {
  699         struct cf_priv *cf_priv;
  700 
  701         cf_priv = (struct cf_priv *) arg;
  702         cf_priv->cf_geom = g_new_geomf(&g_cf_class, "cf%d", device_get_unit(cf_priv->dev));
  703         cf_priv->cf_provider = g_new_providerf(cf_priv->cf_geom, cf_priv->cf_geom->name);
  704         cf_priv->cf_geom->softc = cf_priv;
  705         g_error_provider(cf_priv->cf_provider, 0);
  706 
  707         return (0);
  708 }
  709 
  710 /* ------------------------------------------------------------------- *
  711  *                      cf_attach_geom()                               *
  712  * ------------------------------------------------------------------- */
  713 static void cf_attach_geom_proxy (void *arg, int flag)
  714 {
  715         cf_attach_geom(arg, flag);
  716 }
  717 
  718 
  719 
  720 /* ------------------------------------------------------------------- *
  721  *                      cf_attach()                                    *
  722  * ------------------------------------------------------------------- */
  723 
  724 static int cf_attach (device_t dev)
  725 {
  726         struct cf_priv *cf_priv;
  727 
  728         if (octeon_is_simulation())
  729                 return (ENXIO);
  730 
  731         cf_priv = device_get_softc(dev);
  732         cf_priv->dev = dev;
  733         cf_priv->drive_param = &drive_param;
  734 
  735         g_post_event(cf_attach_geom_proxy, cf_priv, M_WAITOK, NULL);
  736         bioq_init(&cf_priv->cf_bq);
  737 
  738         return 0;
  739 }
  740 
  741 
  742 static device_method_t cf_methods[] = {
  743         /* Device interface */
  744         DEVMETHOD(device_probe,         cf_probe),
  745         DEVMETHOD(device_identify,      cf_identify),
  746         DEVMETHOD(device_attach,        cf_attach),
  747         DEVMETHOD(device_detach,        bus_generic_detach),
  748         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
  749 
  750         { 0, 0 }
  751 };
  752 
  753 static driver_t cf_driver = {
  754         "cf", 
  755         cf_methods, 
  756         sizeof(struct cf_priv)
  757 };
  758 
  759 static devclass_t cf_devclass;
  760 
  761 DRIVER_MODULE(cf, nexus, cf_driver, cf_devclass, 0, 0);

Cache object: 5bd2c2ea2f5ef5b03bc1099668b5d71a


[ 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.