-
Notifications
You must be signed in to change notification settings - Fork 0
/
p90mb.c
159 lines (131 loc) · 3.66 KB
/
p90mb.c
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
* Board support for P90MB
*
* No conditional includes to avoid bad dependencies.
*/
#include <stdint.h>
#include "proto.h"
#ifdef CONFIG_BOARD_p90mb
#define IDE_BASE 0xffe000UL
#define IDE_DATA16 REG16(IDE_BASE + 0x00)
#define IDE_ERROR REG8(IDE_BASE + 0x03)
#define IDE_ERROR_ID_NOT_FOUND 0x10
#define IDE_ERROR_UNCORRECTABLE 0x40
#define IDE_FEATURE REG8(IDE_BASE + 0x03)
#define IDE_SECTOR_COUNT REG8(IDE_BASE + 0x05)
#define IDE_LBA_0 REG8(IDE_BASE + 0x07)
#define IDE_LBA_1 REG8(IDE_BASE + 0x09)
#define IDE_LBA_2 REG8(IDE_BASE + 0x0b)
#define IDE_LBA_3 REG8(IDE_BASE + 0x0d)
#define IDE_LBA_3_DEV1 0x10
#define IDE_LBA_3_LBA 0xe0 // incl. bits 7/5 for compat
#define IDE_STATUS REG8(IDE_BASE + 0x0f)
#define IDE_STATUS_ERR 0x01
#define IDE_STATUS_DRQ 0x08
#define IDE_STATUS_DF 0x20
#define IDE_STATUS_DRDY 0x40
#define IDE_STATUS_BSY 0x80
#define IDE_COMMAND REG8(IDE_BASE + 0x0f)
#define IDE_CMD_READ_SECTORS 0x20
#define IDE_CMD_WRITE_SECTORS 0x30
#define IDE_CMD_IDENTIFY_DEVICE 0xec
/**********************************************************************/
#define RX_BUF_SIZE 128
static char board_rx_buf[RX_BUF_SIZE];
static uint16_t board_rx_head;
static uint16_t board_rx_tail;
const char *board_name = "P90MB";
/**********************************************************************
* board_init
*/
void
board_init()
{
/* Configure UART */
board_status(2);
}
/**********************************************************************
* board_deinit
*/
void
board_deinit()
{
// XXX could wait to drain TXA?
interrupt_disable();
// mask interrupts / reset peripherals
}
/**********************************************************************
* board_status
*/
uint8_t
board_status(uint8_t code)
{
static uint8_t prev_code;
uint8_t ret_code = prev_code;
/* no board status indicator */
prev_code = code;
return ret_code;
}
/**********************************************************************
* board_putc
*/
void
board_putc(char c)
{
if (c == '\n') {
board_putc('\r');
}
for (;;) {
if (1/* ready to transmit */) {
/* transmit c */
break;
}
}
board_status(3);
}
/**********************************************************************
* board_getc
*/
int
board_getc()
{
if (board_rx_head != board_rx_tail) {
char c = board_rx_buf[board_rx_tail % RX_BUF_SIZE];
board_rx_tail++;
return c;
}
return -1;
}
/**********************************************************************
* board_diskread
*/
int
board_diskread(void *buffer, uint32_t lba)
{
// XXX should check for busy here?
IDE_LBA_3 = ((lba >> 24) & 0x3f) | IDE_LBA_3_LBA;
IDE_LBA_2 = (lba >> 16) & 0xff;
IDE_LBA_1 = (lba >> 8) & 0xff;
IDE_LBA_0 = lba & 0xff;
IDE_SECTOR_COUNT = 1;
IDE_COMMAND = IDE_CMD_READ_SECTORS;
// XXX timeout
for (;;) {
uint8_t status = IDE_STATUS;
if (status & IDE_STATUS_ERR) {
fmt("CF: READ error 0x%b\n", IDE_ERROR);
return -1;
}
if (status & IDE_STATUS_DRQ) {
uint16_t *bp = (uint16_t *)buffer;
for (unsigned idx = 0; idx < DISK_SECTOR_SIZE; idx += 2) {
*bp++ = swap16(IDE_DATA16);
}
return 0;
}
}
}
/**********************************************************************
* interrupt handlers
*/
#endif /* CONFIG_BOARD_p90mb */