]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/mips/cavium/octeon_ebt3000_cf.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / mips / cavium / octeon_ebt3000_cf.c
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$");
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);