1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
/* CF-mips driver
This is a block driver for the direct (mmaped) interface to the CF-slot,
found in Routerboard.com's RB532 board
See SDK provided from routerboard.com.
Module adapted By P.Christeas <p_christeas@yahoo.com>, 2005-6.
Cleaned up and adapted to platform_device by Felix Fietkau <nbd@openwrt.org>
This work is redistributed under the terms of the GNU General Public License.
*/
#ifndef __CFMIPS_ATA_H__
#define __CFMIPS_ATA_H__
#include <linux/interrupt.h>
#define CFG_DC_DEV1 (void*)0xb8010010
#define CFG_DC_DEVBASE 0x0
#define CFG_DC_DEVMASK 0x4
#define CFG_DC_DEVC 0x8
#define CFG_DC_DEVTC 0xC
#define CFDEV_BUF_SIZE 0x1000
#define ATA_CIS_OFFSET 0x200
#define ATA_REG_OFFSET 0x800
#define ATA_DBUF_OFFSET 0xC00
#define ATA_REG_FEAT 0x1
#define ATA_REG_SC 0x2
#define ATA_REG_SN 0x3
#define ATA_REG_CL 0x4
#define ATA_REG_CH 0x5
#define ATA_REG_DH 0x6
#define ATA_REG_DH_BASE 0xa0
#define ATA_REG_DH_LBA 0x40
#define ATA_REG_DH_DRV 0x10
#define ATA_REG_CMD 0x7
#define ATA_REG_ST 0x7
#define ATA_REG_ST_BUSY 0x80
#define ATA_REG_ST_RDY 0x40
#define ATA_REG_ST_DWF 0x20
#define ATA_REG_ST_DSC 0x10
#define ATA_REG_ST_DRQ 0x08
#define ATA_REG_ST_CORR 0x04
#define ATA_REG_ST_ERR 0x01
#define ATA_REG_ERR 0xd
#define ATA_REG_DC 0xe
#define ATA_REG_DC_IEN 0x02
#define ATA_REG_DC_SRST 0x04
#define ATA_CMD_READ_SECTORS 0x20
#define ATA_CMD_WRITE_SECTORS 0x30
#define ATA_CMD_EXEC_DRIVE_DIAG 0x90
#define ATA_CMD_READ_MULTIPLE 0xC4
#define ATA_CMD_WRITE_MULTIPLE 0xC5
#define ATA_CMD_SET_MULTIPLE 0xC6
#define ATA_CMD_IDENTIFY_DRIVE 0xEC
#define ATA_CMD_SET_FEATURES 0xEF
#define ATA_FEATURE_ENABLE_APM 0x05
#define ATA_FEATURE_DISABLE_APM 0x85
#define ATA_APM_DISABLED 0x00
#define ATA_APM_MIN_POWER 0x01
#define ATA_APM_WITH_STANDBY 0x7f
#define ATA_APM_WITHOUT_STANDBY 0x80
#define ATA_APM_MAX_PERFORMANCE 0xfe
#define CF_SECT_SIZE 0x200
/* That is the ratio CF_SECT_SIZE/512 (the kernel sector size) */
#define CF_KERNEL_MUL 1
#define ATA_MAX_SECT_PER_CMD 0x100
#define CF_TRANS_FAILED 0
#define CF_TRANS_OK 1
#define CF_TRANS_IN_PROGRESS 2
enum trans_state {
TS_IDLE = 0,
TS_AFTER_RESET,
TS_READY,
TS_CMD,
TS_TRANS
};
//
// #if DEBUG
// static unsigned long busy_time;
// #endif
/** Struct to hold the cfdev
Actually, all the data here only has one instance. However, for
reasons of programming conformity, it is passed around as a pointer
*/
struct cf_mips_dev {
void *base; /* base address for I/O */
void *baddr; /* remapped address */
int pin; /* gpio pin */
int irq; /* gpio irq */
unsigned head;
unsigned cyl;
unsigned spt;
unsigned sectors;
unsigned short block_size;
unsigned dtype ; // ATA or CF
struct request_queue *queue;
struct gendisk *gd;
/* Transaction state */
enum trans_state tstate;
char *tbuf;
unsigned long tbuf_size;
sector_t tsect_start;
unsigned tsector_count;
unsigned tsectors_left;
int tread;
unsigned tcmd;
int async_mode;
unsigned long irq_enable_time;
struct request *active_req; /* A request is being carried out. Is that different from tstate? */
int users;
struct timer_list to_timer;
struct tasklet_struct tasklet;
/** This lock ensures that the requests to this device are all done
atomically. Transfers can run in parallel, requests are all queued
one-by-one */
spinlock_t lock;
};
int cf_do_transfer(struct cf_mips_dev* dev,sector_t sector, unsigned long nsect,
char* buffer, int is_write);
int cf_init(struct cf_mips_dev* dev);
void cf_cleanup(struct cf_mips_dev* dev);
void cf_async_trans_done(struct cf_mips_dev* dev, int result);
// void *cf_get_next_buf(unsigned long *buf_size);
#endif
|