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 */ 124void *base_addr; 125int 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 */ 129const char *const cf_type[] = { 130 "impossible type", 131 "CF 8-bit", 132 "CF 16-bit", 133 "True IDE" 134}; 135 136/* Device parameters */ 137struct 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 */ 152struct 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 */ 163static g_access_t cf_access; 164static g_start_t cf_start; 165static g_ioctl_t cf_ioctl; 166 167struct 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 175DECLARE_GEOM_CLASS(g_cf_class, g_cf); 176 177/* Device methods */ 178static int cf_probe(device_t); 179static void cf_identify(driver_t *, device_t); 180static int cf_attach(device_t); 181static void cf_attach_geom(void *, int); 182 183/* ATA methods */ 184static int cf_cmd_identify(struct cf_priv *); 185static int cf_cmd_write(uint32_t, uint32_t, void *); 186static int cf_cmd_read(uint32_t, uint32_t, void *); 187static int cf_wait_busy(void); 188static int cf_send_cmd(uint32_t, uint8_t); 189 190/* Miscelenous */ 191static void cf_swap_ascii(unsigned char[], char[]); 192 193 194/* ------------------------------------------------------------------- * 195 * cf_access() * 196 * ------------------------------------------------------------------- */ 197static 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 * ------------------------------------------------------------------- */ 206static 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 252static int cf_ioctl (struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td) 253{ 254 return (0); 255} 256 257 258static 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 275static 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 293static 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 302static 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 309static 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 */ 321static 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 */ 374static 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 */ 428static 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 */ 484static 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 */ 527static 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 */ 578static 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 591static 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 */ 614static 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 677static 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 694static 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 718static 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 729static driver_t cf_driver = { 730 "cf", 731 cf_methods, 732 sizeof(struct cf_priv) 733}; 734 735static devclass_t cf_devclass; 736 737DRIVER_MODULE(cf, nexus, cf_driver, cf_devclass, 0, 0); 738