2
* (C) Copyright 2009 mGine co.
3
* unsik Kim <donari75@gmail.com>
5
* See file CREDITS for list of people who contributed to this
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2 of
11
* the License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29
#include "mg_disk_prv.h"
31
#ifndef CONFIG_MG_DISK_RES
32
#define CONFIG_MG_DISK_RES 0
35
#define MG_RES_SEC ((CONFIG_MG_DISK_RES) << 1)
37
static struct mg_host host;
39
static inline u32 mg_base(void)
41
return host.drv_data->base;
44
static block_dev_desc_t mg_disk_dev = {
45
.if_type = IF_TYPE_ATAPI,
46
.part_type = PART_TYPE_UNKNOWN,
47
.type = DEV_TYPE_HARDDISK,
48
.blksz = MG_SECTOR_SIZE,
51
static void mg_dump_status (const char *msg, unsigned int stat, unsigned err)
53
char *name = MG_DEV_NAME;
55
printf("%s: %s: status=0x%02x { ", name, msg, stat & 0xff);
56
if (stat & MG_REG_STATUS_BIT_BUSY)
58
if (stat & MG_REG_STATUS_BIT_READY)
59
printf("DriveReady ");
60
if (stat & MG_REG_STATUS_BIT_WRITE_FAULT)
61
printf("WriteFault ");
62
if (stat & MG_REG_STATUS_BIT_SEEK_DONE)
63
printf("SeekComplete ");
64
if (stat & MG_REG_STATUS_BIT_DATA_REQ)
65
printf("DataRequest ");
66
if (stat & MG_REG_STATUS_BIT_CORRECTED_ERROR)
67
printf("CorrectedError ");
68
if (stat & MG_REG_STATUS_BIT_ERROR)
72
if ((stat & MG_REG_STATUS_BIT_ERROR)) {
73
printf("%s: %s: error=0x%02x { ", name, msg, err & 0xff);
74
if (err & MG_REG_ERR_BBK)
76
if (err & MG_REG_ERR_UNC)
77
printf("UncorrectableError ");
78
if (err & MG_REG_ERR_IDNF)
79
printf("SectorIdNotFound ");
80
if (err & MG_REG_ERR_ABRT)
81
printf("DriveStatusError ");
82
if (err & MG_REG_ERR_AMNF)
83
printf("AddrMarkNotFound ");
88
static unsigned int mg_wait (u32 expect, u32 msec)
97
status = readb(mg_base() + MG_REG_STATUS);
99
cur = get_timer(from);
100
if (status & MG_REG_STATUS_BIT_BUSY) {
101
if (expect == MG_REG_STATUS_BIT_BUSY)
104
/* Check the error condition! */
105
if (status & MG_REG_STATUS_BIT_ERROR) {
106
err = readb(mg_base() + MG_REG_ERROR);
107
mg_dump_status("mg_wait", status, err);
111
if (expect == MG_STAT_READY)
112
if (MG_READY_OK(status))
115
if (expect == MG_REG_STATUS_BIT_DATA_REQ)
116
if (status & MG_REG_STATUS_BIT_DATA_REQ)
119
status = readb(mg_base() + MG_REG_STATUS);
120
} while (cur < msec);
123
err = MG_ERR_TIMEOUT;
128
static int mg_get_disk_id (void)
130
u16 id[(MG_SECTOR_SIZE / sizeof(u16))];
131
hd_driveid_t *iop = (hd_driveid_t *)id;
134
writeb(MG_CMD_ID, mg_base() + MG_REG_COMMAND);
135
err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000);
139
for(i = 0; i < (MG_SECTOR_SIZE / sizeof(u16)); i++)
140
id[i] = readw(mg_base() + MG_BUFF_OFFSET + i * 2);
142
writeb(MG_CMD_RD_CONF, mg_base() + MG_REG_COMMAND);
143
err = mg_wait(MG_STAT_READY, 3000);
147
ata_swap_buf_le16(id, MG_SECTOR_SIZE / sizeof(u16));
149
if((iop->field_valid & 1) == 0)
150
return MG_ERR_TRANSLATION;
152
ata_id_c_string(id, (unsigned char *)mg_disk_dev.revision,
153
ATA_ID_FW_REV, sizeof(mg_disk_dev.revision));
154
ata_id_c_string(id, (unsigned char *)mg_disk_dev.vendor,
155
ATA_ID_PROD, sizeof(mg_disk_dev.vendor));
156
ata_id_c_string(id, (unsigned char *)mg_disk_dev.product,
157
ATA_ID_SERNO, sizeof(mg_disk_dev.product));
160
iop->lba_capacity = (iop->lba_capacity << 16) |
161
(iop->lba_capacity >> 16);
162
#endif /* __BIG_ENDIAN */
165
MG_DBG("MG_RES_SEC=%d\n", MG_RES_SEC);
166
iop->cyls = (iop->lba_capacity - MG_RES_SEC) /
167
iop->sectors / iop->heads;
168
res = iop->lba_capacity -
169
iop->cyls * iop->heads * iop->sectors;
170
iop->lba_capacity -= res;
171
printf("mg_disk: %d sectors reserved\n", res);
174
mg_disk_dev.lba = iop->lba_capacity;
178
static int mg_disk_reset (void)
180
struct mg_drv_data *prv_data = host.drv_data;
185
prv_data->mg_hdrst_pin(0);
186
err = mg_wait(MG_REG_STATUS_BIT_BUSY, 300);
191
prv_data->mg_hdrst_pin(1);
192
err = mg_wait(MG_STAT_READY, 3000);
197
writeb(MG_REG_CTRL_RESET | MG_REG_CTRL_INTR_DISABLE,
198
mg_base() + MG_REG_DRV_CTRL);
199
err = mg_wait(MG_REG_STATUS_BIT_BUSY, 3000);
204
writeb(MG_REG_CTRL_INTR_DISABLE, mg_base() + MG_REG_DRV_CTRL);
205
err = mg_wait(MG_STAT_READY, 3000);
209
init_status = readb(mg_base() + MG_REG_STATUS) & 0xf;
211
if (init_status == 0xf)
212
return MG_ERR_INIT_STAT;
218
static unsigned int mg_out(unsigned int sect_num,
219
unsigned int sect_cnt,
222
u32 err = MG_ERR_NONE;
224
err = mg_wait(MG_STAT_READY, 3000);
228
writeb((u8)sect_cnt, mg_base() + MG_REG_SECT_CNT);
229
writeb((u8)sect_num, mg_base() + MG_REG_SECT_NUM);
230
writeb((u8)(sect_num >> 8), mg_base() + MG_REG_CYL_LOW);
231
writeb((u8)(sect_num >> 16), mg_base() + MG_REG_CYL_HIGH);
232
writeb((u8)((sect_num >> 24) | MG_REG_HEAD_LBA_MODE),
233
mg_base() + MG_REG_DRV_HEAD);
234
writeb(cmd, mg_base() + MG_REG_COMMAND);
239
static unsigned int mg_do_read_sects(void *buff, u32 sect_num, u32 sect_cnt)
243
union mg_uniwb uniwb;
245
err = mg_out(sect_num, sect_cnt, MG_CMD_RD);
249
for (i = 0; i < sect_cnt; i++) {
250
err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000);
254
if ((u32)buff_ptr & 1) {
255
for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
256
uniwb.w = readw(mg_base() + MG_BUFF_OFFSET
258
*buff_ptr++ = uniwb.b[0];
259
*buff_ptr++ = uniwb.b[1];
262
for(j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
263
*(u16 *)buff_ptr = readw(mg_base() +
264
MG_BUFF_OFFSET + (j << 1));
268
writeb(MG_CMD_RD_CONF, mg_base() + MG_REG_COMMAND);
270
MG_DBG("%u (0x%8.8x) sector read", sect_num + i,
271
(sect_num + i) * MG_SECTOR_SIZE);
277
unsigned int mg_disk_read_sects(void *buff, u32 sect_num, u32 sect_cnt)
279
u32 quotient, residue, i, err;
282
quotient = sect_cnt >> 8;
283
residue = sect_cnt % 256;
285
for (i = 0; i < quotient; i++) {
286
MG_DBG("sect num : %u buff : 0x%8.8x", sect_num, (u32)buff_ptr);
287
err = mg_do_read_sects(buff_ptr, sect_num, 256);
291
buff_ptr += 256 * MG_SECTOR_SIZE;
295
MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);
296
err = mg_do_read_sects(buff_ptr, sect_num, residue);
302
unsigned long mg_block_read (int dev, unsigned long start,
303
lbaint_t blkcnt, void *buffer)
306
if (! mg_disk_read_sects(buffer, start, blkcnt))
312
unsigned int mg_disk_read (u32 addr, u8 *buff, u32 len)
314
u8 *sect_buff, *buff_ptr = buff;
315
u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num;
316
u32 err = MG_ERR_NONE;
318
/* TODO : sanity chk */
321
end_addr = addr + len;
323
sect_buff = malloc(MG_SECTOR_SIZE);
325
if (cur_addr & MG_SECTOR_SIZE_MASK) {
326
next_sec_addr = (cur_addr + MG_SECTOR_SIZE) &
327
~MG_SECTOR_SIZE_MASK;
328
sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
329
err = mg_disk_read_sects(sect_buff, sect_num, 1);
333
if (end_addr < next_sec_addr) {
335
sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK),
336
end_addr - cur_addr);
337
MG_DBG("copies %u byte from sector offset 0x%8.8x",
338
end_addr - cur_addr, cur_addr);
342
sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK),
343
next_sec_addr - cur_addr);
344
MG_DBG("copies %u byte from sector offset 0x%8.8x",
345
next_sec_addr - cur_addr, cur_addr);
346
buff_ptr += (next_sec_addr - cur_addr);
347
cur_addr = next_sec_addr;
351
if (cur_addr < end_addr) {
352
sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
353
cnt = ((end_addr & ~MG_SECTOR_SIZE_MASK) - cur_addr) >>
354
MG_SECTOR_SIZE_SHIFT;
357
err = mg_disk_read_sects(buff_ptr, sect_num, cnt);
361
buff_ptr += cnt * MG_SECTOR_SIZE;
362
cur_addr += cnt * MG_SECTOR_SIZE;
364
if (cur_addr < end_addr) {
365
sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
366
err = mg_disk_read_sects(sect_buff, sect_num, 1);
369
memcpy(buff_ptr, sect_buff, end_addr - cur_addr);
370
MG_DBG("copies %u byte", end_addr - cur_addr);
379
static int mg_do_write_sects(void *buff, u32 sect_num, u32 sect_cnt)
383
union mg_uniwb uniwb;
385
err = mg_out(sect_num, sect_cnt, MG_CMD_WR);
389
for (i = 0; i < sect_cnt; i++) {
390
err = mg_wait(MG_REG_STATUS_BIT_DATA_REQ, 3000);
394
if ((u32)buff_ptr & 1) {
395
uniwb.b[0] = *buff_ptr++;
396
uniwb.b[1] = *buff_ptr++;
397
writew(uniwb.w, mg_base() + MG_BUFF_OFFSET + (j << 1));
399
for(j = 0; j < MG_SECTOR_SIZE >> 1; j++) {
400
writew(*(u16 *)buff_ptr,
401
mg_base() + MG_BUFF_OFFSET +
406
writeb(MG_CMD_WR_CONF, mg_base() + MG_REG_COMMAND);
408
MG_DBG("%u (0x%8.8x) sector write",
409
sect_num + i, (sect_num + i) * MG_SECTOR_SIZE);
415
unsigned int mg_disk_write_sects(void *buff, u32 sect_num, u32 sect_cnt)
417
u32 quotient, residue, i;
418
u32 err = MG_ERR_NONE;
421
quotient = sect_cnt >> 8;
422
residue = sect_cnt % 256;
424
for (i = 0; i < quotient; i++) {
425
MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);
426
err = mg_do_write_sects(buff_ptr, sect_num, 256);
430
buff_ptr += 256 * MG_SECTOR_SIZE;
434
MG_DBG("sect num : %u buff : %8.8x", sect_num, (u32)buff_ptr);
435
err = mg_do_write_sects(buff_ptr, sect_num, residue);
441
unsigned long mg_block_write (int dev, unsigned long start,
442
lbaint_t blkcnt, const void *buffer)
445
if (!mg_disk_write_sects((void *)buffer, start, blkcnt))
451
unsigned int mg_disk_write(u32 addr, u8 *buff, u32 len)
453
u8 *sect_buff, *buff_ptr = buff;
454
u32 cur_addr, next_sec_addr, end_addr, cnt, sect_num;
455
u32 err = MG_ERR_NONE;
457
/* TODO : sanity chk */
460
end_addr = addr + len;
462
sect_buff = malloc(MG_SECTOR_SIZE);
464
if (cur_addr & MG_SECTOR_SIZE_MASK) {
466
next_sec_addr = (cur_addr + MG_SECTOR_SIZE) &
467
~MG_SECTOR_SIZE_MASK;
468
sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
469
err = mg_disk_read_sects(sect_buff, sect_num, 1);
473
if (end_addr < next_sec_addr) {
474
memcpy(sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK),
475
buff_ptr, end_addr - cur_addr);
476
MG_DBG("copies %u byte to sector offset 0x%8.8x",
477
end_addr - cur_addr, cur_addr);
480
memcpy(sect_buff + (cur_addr & MG_SECTOR_SIZE_MASK),
481
buff_ptr, next_sec_addr - cur_addr);
482
MG_DBG("copies %u byte to sector offset 0x%8.8x",
483
next_sec_addr - cur_addr, cur_addr);
484
buff_ptr += (next_sec_addr - cur_addr);
485
cur_addr = next_sec_addr;
488
err = mg_disk_write_sects(sect_buff, sect_num, 1);
493
if (cur_addr < end_addr) {
495
sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
496
cnt = ((end_addr & ~MG_SECTOR_SIZE_MASK) - cur_addr) >>
497
MG_SECTOR_SIZE_SHIFT;
500
err = mg_disk_write_sects(buff_ptr, sect_num, cnt);
504
buff_ptr += cnt * MG_SECTOR_SIZE;
505
cur_addr += cnt * MG_SECTOR_SIZE;
507
if (cur_addr < end_addr) {
508
sect_num = cur_addr >> MG_SECTOR_SIZE_SHIFT;
509
err = mg_disk_read_sects(sect_buff, sect_num, 1);
512
memcpy(sect_buff, buff_ptr, end_addr - cur_addr);
513
MG_DBG("copies %u byte", end_addr - cur_addr);
514
err = mg_disk_write_sects(sect_buff, sect_num, 1);
525
block_dev_desc_t *mg_disk_get_dev(int dev)
527
return ((block_dev_desc_t *) & mg_disk_dev);
530
/* must override this function */
531
struct mg_drv_data * __attribute__((weak)) mg_get_drv_data (void)
533
puts ("### WARNING ### port mg_get_drv_data function\n");
537
unsigned int mg_disk_init (void)
539
struct mg_drv_data *prv_data;
540
u32 err = MG_ERR_NONE;
542
prv_data = mg_get_drv_data();
544
printf("%s:%d fail (no driver_data)\n", __func__, __LINE__);
545
err = MG_ERR_NO_DRV_DATA;
549
((struct mg_host *)mg_disk_dev.priv)->drv_data = prv_data;
552
if (prv_data->mg_ctrl_pin_init)
553
prv_data->mg_ctrl_pin_init();
555
if (! prv_data->mg_hdrst_pin) {
556
err = MG_ERR_CTRL_RST;
561
err = mg_disk_reset();
563
printf("%s:%d fail (err code : %d)\n", __func__, __LINE__, err);
568
err = mg_get_disk_id();
570
printf("%s:%d fail (err code : %d)\n", __func__, __LINE__, err);
574
mg_disk_dev.block_read = mg_block_read;
575
mg_disk_dev.block_write = mg_block_write;
577
init_part(&mg_disk_dev);
579
dev_print(&mg_disk_dev);