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>
| 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: head/sys/mips/cavium/octeon_ebt3000_cf.c 242201 2012-10-27 23:36:41Z jmallett $");
| 45__FBSDID("$FreeBSD: head/sys/mips/cavium/octeon_ebt3000_cf.c 242273 2012-10-29 00:51:53Z jmallett $");
|
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
| 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//#define OCTEON_VISUAL_CF_0 1 330#ifdef OCTEON_VISUAL_CF_0 331 octeon_led_write_char(0, 'R'); 332#endif
| |
333 ptr_8 = (uint8_t*)buf; 334 ptr_16 = (uint16_t*)buf; 335 lba = start_sector; 336
| 329 ptr_8 = (uint8_t*)buf; 330 ptr_16 = (uint16_t*)buf; 331 lba = start_sector; 332
|
337
| |
338 while (nr_sectors--) { 339 error = cf_send_cmd(lba, CMD_READ_SECTOR); 340 if (error != 0) { 341 printf("%s: cf_send_cmd(CMD_READ_SECTOR) failed: %d\n", __func__, error); 342 return (error); 343 } 344 345 switch (bus_type) 346 { 347 case CF_8: 348 for (count = 0; count < SECTOR_SIZE; count++) { 349 *ptr_8++ = cf_inb_8(TF_DATA); 350 if ((count & 0xf) == 0) 351 (void)cf_inb_8(TF_STATUS); 352 } 353 break; 354 case CF_TRUE_IDE_8: 355 case CF_16: 356 default: 357 for (count = 0; count < SECTOR_SIZE; count+=2) { 358 uint16_t temp; 359 temp = cf_inw_16(TF_DATA); 360 *ptr_16++ = SWAP_SHORT(temp); 361 if ((count & 0xf) == 0) 362 (void)cf_inb_16(TF_STATUS); 363 } 364 break; 365 } 366 367 lba++; 368 }
| 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 }
|
369#ifdef OCTEON_VISUAL_CF_0 370 octeon_led_write_char(0, ' '); 371#endif
| |
372 return (0); 373} 374 375 376/* ------------------------------------------------------------------- * 377 * cf_cmd_write() * 378 * ------------------------------------------------------------------- * 379 * 380 * Write nr_sectors to the device starting from start_sector. 381 */ 382static int cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf) 383{ 384 uint32_t lba; 385 uint32_t count; 386 uint16_t *ptr_16; 387 uint8_t *ptr_8; 388 int error; 389
| 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
|
390//#define OCTEON_VISUAL_CF_1 1 391#ifdef OCTEON_VISUAL_CF_1 392 octeon_led_write_char(1, 'W'); 393#endif
| |
394 lba = start_sector; 395 ptr_8 = (uint8_t*)buf; 396 ptr_16 = (uint16_t*)buf; 397 398 while (nr_sectors--) { 399 error = cf_send_cmd(lba, CMD_WRITE_SECTOR); 400 if (error != 0) { 401 printf("%s: cf_send_cmd(CMD_WRITE_SECTOR) failed: %d\n", __func__, error); 402 return (error); 403 } 404 405 switch (bus_type) 406 { 407 case CF_8: 408 for (count = 0; count < SECTOR_SIZE; count++) { 409 cf_outb_8(TF_DATA, *ptr_8++); 410 if ((count & 0xf) == 0) 411 (void)cf_inb_8(TF_STATUS); 412 } 413 break; 414 case CF_TRUE_IDE_8: 415 case CF_16: 416 default: 417 for (count = 0; count < SECTOR_SIZE; count+=2) { 418 uint16_t temp = *ptr_16++; 419 cf_outw_16(TF_DATA, SWAP_SHORT(temp)); 420 if ((count & 0xf) == 0) 421 (void)cf_inb_16(TF_STATUS); 422 } 423 break; 424 } 425 426 lba++; 427 }
| 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 }
|
428#ifdef OCTEON_VISUAL_CF_1 429 octeon_led_write_char(1, ' '); 430#endif
| |
431 return (0); 432} 433 434 435/* ------------------------------------------------------------------- * 436 * cf_cmd_identify() * 437 * ------------------------------------------------------------------- * 438 * 439 * Read parameters and other information from the drive and store 440 * it in the drive_param structure 441 * 442 */ 443static int cf_cmd_identify(struct cf_priv *cf_priv) 444{ 445 int count; 446 int error; 447 448 error = cf_send_cmd(0, CMD_IDENTIFY); 449 if (error != 0) { 450 printf("%s: identify failed: %d\n", __func__, error); 451 return (error); 452 } 453 switch (bus_type) 454 { 455 case CF_8: 456 for (count = 0; count < SECTOR_SIZE; count++) 457 cf_priv->drive_param.u.buf[count] = cf_inb_8(TF_DATA); 458 break; 459 case CF_TRUE_IDE_8: 460 case CF_16: 461 default: 462 for (count = 0; count < SECTOR_SIZE; count += 2) { 463 uint16_t temp; 464 temp = cf_inw_16(TF_DATA); 465 466 /* endianess will be swapped below */ 467 cf_priv->drive_param.u.buf[count] = (temp & 0xff); 468 cf_priv->drive_param.u.buf[count + 1] = (temp & 0xff00) >> 8; 469 } 470 break; 471 } 472 473 cf_swap_ascii(cf_priv->drive_param.u.driveid.model, cf_priv->drive_param.model); 474 475 cf_priv->drive_param.sector_size = 512; //= SWAP_SHORT (cf_priv->drive_param.u.driveid.sector_bytes); 476 cf_priv->drive_param.heads = SWAP_SHORT (cf_priv->drive_param.u.driveid.current_heads); 477 cf_priv->drive_param.tracks = SWAP_SHORT (cf_priv->drive_param.u.driveid.current_cylinders); 478 cf_priv->drive_param.sec_track = SWAP_SHORT (cf_priv->drive_param.u.driveid.current_sectors); 479 cf_priv->drive_param.nr_sectors = (uint32_t)SWAP_SHORT (cf_priv->drive_param.u.driveid.lba_size_1) | 480 ((uint32_t)SWAP_SHORT (cf_priv->drive_param.u.driveid.lba_size_2)); 481 if (bootverbose) { 482 printf(" model %s\n", cf_priv->drive_param.model); 483 printf(" heads %d tracks %d sec_tracks %d sectors %d\n", 484 cf_priv->drive_param.heads, cf_priv->drive_param.tracks, 485 cf_priv->drive_param.sec_track, cf_priv->drive_param.nr_sectors); 486 } 487 488 return (0); 489} 490 491 492/* ------------------------------------------------------------------- * 493 * cf_send_cmd() * 494 * ------------------------------------------------------------------- * 495 * 496 * Send command to read/write one sector specified by lba. 497 * 498 */ 499static int cf_send_cmd (uint32_t lba, uint8_t cmd) 500{ 501 switch (bus_type) 502 { 503 case CF_8: 504 case CF_TRUE_IDE_8: 505 while (cf_inb_8(TF_STATUS) & STATUS_BSY) 506 DELAY(WAIT_DELAY); 507 cf_outb_8(TF_SECTOR_COUNT, 1); 508 cf_outb_8(TF_SECTOR_NUMBER, lba & 0xff); 509 cf_outb_8(TF_CYL_LSB, (lba >> 8) & 0xff); 510 cf_outb_8(TF_CYL_MSB, (lba >> 16) & 0xff); 511 cf_outb_8(TF_DRV_HEAD, ((lba >> 24) & 0xff) | 0xe0); 512 cf_outb_8(TF_COMMAND, cmd); 513 break; 514 case CF_16: 515 default: 516 while (cf_inb_16(TF_STATUS) & STATUS_BSY) 517 DELAY(WAIT_DELAY); 518 cf_outw_16(TF_SECTOR_COUNT, 1 | ((lba & 0xff) << 8)); 519 cf_outw_16(TF_CYL_LSB, ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8)); 520 cf_outw_16(TF_DRV_HEAD, (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8)); 521 break; 522 } 523 524 return (cf_wait_busy()); 525} 526 527/* ------------------------------------------------------------------- * 528 * cf_wait_busy() * 529 * ------------------------------------------------------------------- * 530 * 531 * Wait until the drive finishes a given command and data is 532 * ready to be transferred. This is done by repeatedly checking 533 * the BSY bit of the status register. When the controller is ready for 534 * data transfer, it clears the BSY bit and sets the DRQ bit. 535 * 536 * If the DF bit is ever set, we return error. 537 * 538 * This code originally spun on DRQ. If that behavior turns out to be 539 * necessary, a flag can be added or this function can be called 540 * repeatedly as long as it is returning ENXIO. 541 */ 542static int cf_wait_busy (void) 543{ 544 uint8_t status; 545
| 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
|
546//#define OCTEON_VISUAL_CF_2 1 547#ifdef OCTEON_VISUAL_CF_2 548 static int where0 = 0; 549 550 octeon_led_run_wheel(&where0, 2); 551#endif 552
| |
553 switch (bus_type) 554 { 555 case CF_8: 556 case CF_TRUE_IDE_8: 557 status = cf_inb_8(TF_STATUS); 558 while ((status & STATUS_BSY) == STATUS_BSY) { 559 if ((status & STATUS_DF) != 0) { 560 printf("%s: device fault (status=%x)\n", __func__, status); 561 return (EIO); 562 } 563 DELAY(WAIT_DELAY); 564 status = cf_inb_8(TF_STATUS); 565 } 566 break; 567 case CF_16: 568 default: 569 status = cf_inb_16(TF_STATUS); 570 while ((status & STATUS_BSY) == STATUS_BSY) { 571 if ((status & STATUS_DF) != 0) { 572 printf("%s: device fault (status=%x)\n", __func__, status); 573 return (EIO); 574 } 575 DELAY(WAIT_DELAY); 576 status = cf_inb_16(TF_STATUS); 577 } 578 break; 579 } 580 581 /* DRQ is only for when read data is actually available; check BSY */ 582 /* Some vendors do assert DRQ, but not all. Check BSY instead. */ 583 if (status & STATUS_BSY) { 584 printf("%s: device not ready (status=%x)\n", __func__, status); 585 return (ENXIO); 586 } 587
| 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
|
588#ifdef OCTEON_VISUAL_CF_2 589 octeon_led_write_char(2, ' '); 590#endif
| |
591 return (0); 592} 593 594/* ------------------------------------------------------------------- * 595 * cf_swap_ascii() * 596 * ------------------------------------------------------------------- * 597 * 598 * The ascii string returned by the controller specifying 599 * the model of the drive is byte-swaped. This routine 600 * corrects the byte ordering. 601 * 602 */ 603static void cf_swap_ascii (unsigned char str1[], char str2[]) 604{ 605 int i; 606 607 for(i = 0; i < MODEL_STR_SIZE; i++) 608 str2[i] = str1[i ^ 1]; 609} 610 611 612/* ------------------------------------------------------------------- * 613 * cf_probe() * 614 * ------------------------------------------------------------------- */ 615 616static int cf_probe (device_t dev) 617{ 618 if (octeon_is_simulation()) 619 return (ENXIO); 620 621 if (device_get_unit(dev) != 0) { 622 panic("can't attach more devices\n"); 623 } 624 625 device_set_desc(dev, "Octeon Compact Flash Driver"); 626 627 return (0); 628} 629 630/* ------------------------------------------------------------------- * 631 * cf_identify() * 632 * ------------------------------------------------------------------- * 633 * 634 * Find the bootbus region for the CF to determine 635 * 16 or 8 bit and check to see if device is 636 * inserted. 637 * 638 */ 639static void cf_identify (driver_t *drv, device_t parent) 640{ 641 int bus_region; 642 int count = 0; 643 cvmx_mio_boot_reg_cfgx_t cfg; 644 uint64_t phys_base; 645 646 if (octeon_is_simulation()) 647 return; 648 649 phys_base = cvmx_sysinfo_get()->compact_flash_common_base_addr; 650 base_addr = cvmx_phys_to_ptr(phys_base); 651 652 for (bus_region = 0; bus_region < 8; bus_region++) 653 { 654 cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(bus_region)); 655 if (cfg.s.base == phys_base >> 16) 656 { 657 if (cvmx_sysinfo_get()->compact_flash_attribute_base_addr == 0) 658 bus_type = CF_TRUE_IDE_8; 659 else 660 bus_type = (cfg.s.width) ? CF_16 : CF_8; 661 printf("Compact flash found in bootbus region %d (%s).\n", bus_region, cf_type[bus_type]); 662 break; 663 } 664 } 665 666 switch (bus_type) 667 { 668 case CF_8: 669 case CF_TRUE_IDE_8: 670 /* Check if CF is inserted */ 671 while (cf_inb_8(TF_STATUS) & STATUS_BSY) { 672 if ((count++) == NR_TRIES ) { 673 printf("Compact Flash not present\n"); 674 return; 675 } 676 DELAY(WAIT_DELAY); 677 } 678 break; 679 case CF_16: 680 default: 681 /* Check if CF is inserted */ 682 while (cf_inb_16(TF_STATUS) & STATUS_BSY) { 683 if ((count++) == NR_TRIES ) { 684 printf("Compact Flash not present\n"); 685 return; 686 } 687 DELAY(WAIT_DELAY); 688 } 689 break; 690 } 691 692 BUS_ADD_CHILD(parent, 0, "cf", 0); 693} 694 695 696/* ------------------------------------------------------------------- * 697 * cf_attach_geom() * 698 * ------------------------------------------------------------------- */ 699 700static void cf_attach_geom (void *arg, int flag) 701{ 702 struct cf_priv *cf_priv; 703 704 cf_priv = (struct cf_priv *) arg; 705 cf_priv->cf_geom = g_new_geomf(&g_cf_class, "cf%d", device_get_unit(cf_priv->dev)); 706 cf_priv->cf_geom->softc = cf_priv; 707 cf_priv->cf_provider = g_new_providerf(cf_priv->cf_geom, cf_priv->cf_geom->name); 708 cf_priv->cf_provider->sectorsize = cf_priv->drive_param.sector_size; 709 cf_priv->cf_provider->mediasize = cf_priv->drive_param.nr_sectors * cf_priv->cf_provider->sectorsize; 710 g_error_provider(cf_priv->cf_provider, 0); 711} 712 713/* ------------------------------------------------------------------- * 714 * cf_attach() * 715 * ------------------------------------------------------------------- */ 716 717static int cf_attach (device_t dev) 718{ 719 struct cf_priv *cf_priv; 720 int error; 721 722 if (octeon_is_simulation()) 723 return (ENXIO); 724 725 cf_priv = device_get_softc(dev); 726 cf_priv->dev = dev; 727 728 error = cf_cmd_identify(cf_priv); 729 if (error != 0) { 730 device_printf(dev, "cf_cmd_identify failed: %d\n", error); 731 return (error); 732 } 733 734 g_post_event(cf_attach_geom, cf_priv, M_WAITOK, NULL); 735 bioq_init(&cf_priv->cf_bq); 736 737 return 0; 738} 739 740 741static device_method_t cf_methods[] = { 742 /* Device interface */ 743 DEVMETHOD(device_probe, cf_probe), 744 DEVMETHOD(device_identify, cf_identify), 745 DEVMETHOD(device_attach, cf_attach), 746 DEVMETHOD(device_detach, bus_generic_detach), 747 DEVMETHOD(device_shutdown, bus_generic_shutdown), 748 749 { 0, 0 } 750}; 751 752static driver_t cf_driver = { 753 "cf", 754 cf_methods, 755 sizeof(struct cf_priv) 756}; 757 758static devclass_t cf_devclass; 759 760DRIVER_MODULE(cf, nexus, cf_driver, cf_devclass, 0, 0);
| 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 (octeon_is_simulation()) 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 (0); 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 (octeon_is_simulation()) 622 return; 623 624 phys_base = cvmx_sysinfo_get()->compact_flash_common_base_addr; 625 base_addr = cvmx_phys_to_ptr(phys_base); 626 627 for (bus_region = 0; bus_region < 8; bus_region++) 628 { 629 cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(bus_region)); 630 if (cfg.s.base == phys_base >> 16) 631 { 632 if (cvmx_sysinfo_get()->compact_flash_attribute_base_addr == 0) 633 bus_type = CF_TRUE_IDE_8; 634 else 635 bus_type = (cfg.s.width) ? CF_16 : CF_8; 636 printf("Compact flash found in bootbus region %d (%s).\n", bus_region, cf_type[bus_type]); 637 break; 638 } 639 } 640 641 switch (bus_type) 642 { 643 case CF_8: 644 case CF_TRUE_IDE_8: 645 /* Check if CF is inserted */ 646 while (cf_inb_8(TF_STATUS) & STATUS_BSY) { 647 if ((count++) == NR_TRIES ) { 648 printf("Compact Flash not present\n"); 649 return; 650 } 651 DELAY(WAIT_DELAY); 652 } 653 break; 654 case CF_16: 655 default: 656 /* Check if CF is inserted */ 657 while (cf_inb_16(TF_STATUS) & STATUS_BSY) { 658 if ((count++) == NR_TRIES ) { 659 printf("Compact Flash not present\n"); 660 return; 661 } 662 DELAY(WAIT_DELAY); 663 } 664 break; 665 } 666 667 BUS_ADD_CHILD(parent, 0, "cf", 0); 668} 669 670 671/* ------------------------------------------------------------------- * 672 * cf_attach_geom() * 673 * ------------------------------------------------------------------- */ 674 675static void cf_attach_geom (void *arg, int flag) 676{ 677 struct cf_priv *cf_priv; 678 679 cf_priv = (struct cf_priv *) arg; 680 cf_priv->cf_geom = g_new_geomf(&g_cf_class, "cf%d", device_get_unit(cf_priv->dev)); 681 cf_priv->cf_geom->softc = cf_priv; 682 cf_priv->cf_provider = g_new_providerf(cf_priv->cf_geom, cf_priv->cf_geom->name); 683 cf_priv->cf_provider->sectorsize = cf_priv->drive_param.sector_size; 684 cf_priv->cf_provider->mediasize = cf_priv->drive_param.nr_sectors * cf_priv->cf_provider->sectorsize; 685 g_error_provider(cf_priv->cf_provider, 0); 686} 687 688/* ------------------------------------------------------------------- * 689 * cf_attach() * 690 * ------------------------------------------------------------------- */ 691 692static int cf_attach (device_t dev) 693{ 694 struct cf_priv *cf_priv; 695 int error; 696 697 if (octeon_is_simulation()) 698 return (ENXIO); 699 700 cf_priv = device_get_softc(dev); 701 cf_priv->dev = dev; 702 703 error = cf_cmd_identify(cf_priv); 704 if (error != 0) { 705 device_printf(dev, "cf_cmd_identify failed: %d\n", error); 706 return (error); 707 } 708 709 g_post_event(cf_attach_geom, cf_priv, M_WAITOK, NULL); 710 bioq_init(&cf_priv->cf_bq); 711 712 return 0; 713} 714 715 716static device_method_t cf_methods[] = { 717 /* Device interface */ 718 DEVMETHOD(device_probe, cf_probe), 719 DEVMETHOD(device_identify, cf_identify), 720 DEVMETHOD(device_attach, cf_attach), 721 DEVMETHOD(device_detach, bus_generic_detach), 722 DEVMETHOD(device_shutdown, bus_generic_shutdown), 723 724 { 0, 0 } 725}; 726 727static driver_t cf_driver = { 728 "cf", 729 cf_methods, 730 sizeof(struct cf_priv) 731}; 732 733static devclass_t cf_devclass; 734 735DRIVER_MODULE(cf, nexus, cf_driver, cf_devclass, 0, 0);
|