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