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