summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/asm/thread.h10
-rw-r--r--firmware/common/devicedata.c88
-rw-r--r--firmware/common/disk.c98
-rw-r--r--firmware/common/rb-loader.c8
-rw-r--r--firmware/drivers/ata-common.c238
-rw-r--r--firmware/drivers/ata.c346
-rw-r--r--firmware/drivers/audio/erosqlinux_codec.c81
-rw-r--r--firmware/drivers/lcd-scroll.c8
-rw-r--r--firmware/drivers/ramdisk.c3
-rw-r--r--firmware/drivers/rtc/rtc_pcf50606.c4
-rw-r--r--firmware/drivers/tuner/rda5802.c32
-rw-r--r--firmware/export/ata.h22
-rw-r--r--firmware/export/config.h17
-rw-r--r--firmware/export/config/erosqnative.h16
-rw-r--r--firmware/export/config/hibylinux.h2
-rw-r--r--firmware/export/config/ipod6g.h15
-rw-r--r--firmware/export/config/vibe500.h11
-rw-r--r--firmware/export/devicedata.h94
-rw-r--r--firmware/export/disk.h4
-rw-r--r--firmware/export/storage.h2
-rw-r--r--firmware/export/usb_ch9.h2
-rw-r--r--firmware/include/string-extra.h2
-rw-r--r--firmware/kernel/include/queue.h1
-rw-r--r--firmware/kernel/queue.c6
-rw-r--r--firmware/libc/include/stdlib.h3
-rw-r--r--firmware/rolo.c13
-rw-r--r--firmware/scroll_engine.c4
-rw-r--r--firmware/storage.c2
-rw-r--r--firmware/target/arm/as3525/system-as3525.c2
-rw-r--r--firmware/target/arm/imx233/clkctrl-imx233.c28
-rw-r--r--firmware/target/arm/imx233/clkctrl-imx233.h2
-rw-r--r--firmware/target/arm/ipod/button-clickwheel.c8
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c15
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c580
-rw-r--r--firmware/target/arm/tms320dm320/system-dm320.c2
-rw-r--r--firmware/target/coldfire/system-coldfire.c5
-rw-r--r--firmware/target/hosted/agptek/debug-agptek.c6
-rw-r--r--firmware/target/hosted/aigo/power-erosq.c55
-rw-r--r--firmware/target/hosted/alsa-controls.h2
-rw-r--r--firmware/target/hosted/power-linux.c5
-rw-r--r--firmware/target/hosted/sdl/app/button-application.c26
-rw-r--r--firmware/target/hosted/sdl/button-sdl.c86
-rw-r--r--firmware/target/hosted/sdl/kernel-sdl.c12
-rw-r--r--firmware/target/hosted/sdl/key_to_touch-sdl.c19
-rw-r--r--firmware/target/hosted/sdl/lcd-bitmap.c9
-rw-r--r--firmware/target/hosted/sdl/lcd-sdl.c13
-rw-r--r--firmware/target/hosted/sdl/lcd-sdl.h4
-rw-r--r--firmware/target/hosted/sdl/pcm-sdl.c88
-rw-r--r--firmware/target/hosted/sdl/system-sdl.c116
-rw-r--r--firmware/target/hosted/sdl/thread-sdl.c4
-rw-r--r--firmware/target/mips/ingenic_jz47xx/xduoo_x3/power-xduoo_x3.c12
-rw-r--r--firmware/target/mips/ingenic_x1000/crt0.S7
-rw-r--r--firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c146
-rw-r--r--firmware/target/mips/ingenic_x1000/system-x1000.c19
-rw-r--r--firmware/target/mips/ingenic_x1000/x1000boot.make2
-rw-r--r--firmware/usbstack/usb_core.c17
-rw-r--r--firmware/usbstack/usb_storage.c217
58 files changed, 1762 insertions, 881 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 4e6fcbf70c..192cdb711d 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -62,6 +62,10 @@ common/bootdata.c
62#endif 62#endif
63#endif 63#endif
64 64
65#if defined(HAVE_DEVICEDATA)
66common/devicedata.c
67#endif
68
65#ifdef HAVE_SDL 69#ifdef HAVE_SDL
66target/hosted/sdl/button-sdl.c 70target/hosted/sdl/button-sdl.c
67target/hosted/sdl/kernel-sdl.c 71target/hosted/sdl/kernel-sdl.c
diff --git a/firmware/asm/thread.h b/firmware/asm/thread.h
index 5372be73ab..831de9ae8d 100644
--- a/firmware/asm/thread.h
+++ b/firmware/asm/thread.h
@@ -46,10 +46,16 @@ struct regs
46 * give a decent amount of space and hope for the best... 46 * give a decent amount of space and hope for the best...
47 * FIXME: this isn't a great solution. */ 47 * FIXME: this isn't a great solution. */
48 #undef MINSIGSTKSZ 48 #undef MINSIGSTKSZ
49 #define MINSIGSTKSZ 16384
50 #endif 49 #endif
51 /* MINSIGSTKSZ for the OS to deliver the signal + 0x3000 for us */ 50 #ifndef MINSIGSTKSZ
51 #define MINSIGSTKSZ 16384
52 #endif
53 /* MINSIGSTKSZ for the OS to deliver the signal, plus more for us */
54#if defined(SIMULATOR) || defined(__aarch64__)
55 #define DEFAULT_STACK_SIZE (MINSIGSTKSZ+0x6000) /* Bytes */
56#else
52 #define DEFAULT_STACK_SIZE (MINSIGSTKSZ+0x3000) /* Bytes */ 57 #define DEFAULT_STACK_SIZE (MINSIGSTKSZ+0x3000) /* Bytes */
58#endif
53 #elif defined(HAVE_WIN32_FIBER_THREADS) 59 #elif defined(HAVE_WIN32_FIBER_THREADS)
54 #define DEFAULT_STACK_SIZE 0x1000 /* Bytes */ 60 #define DEFAULT_STACK_SIZE 0x1000 /* Bytes */
55 #endif 61 #endif
diff --git a/firmware/common/devicedata.c b/firmware/common/devicedata.c
new file mode 100644
index 0000000000..75fe79d7fa
--- /dev/null
+++ b/firmware/common/devicedata.c
@@ -0,0 +1,88 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2024 by William Wilgus
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include "devicedata.h"
22#include "crc32.h"
23#include <stddef.h>
24#include <string.h>
25#include "debug.h"
26
27#ifndef BOOTLOADER
28void verify_device_data(void) INIT_ATTR;
29void verify_device_data(void)
30{
31 DEBUGF("%s", __func__);
32 /* verify payload with checksum */
33 uint32_t crc = crc_32(device_data.payload, device_data.length, 0xffffffff);
34 if (crc == device_data.crc)
35 return; /* return if data is valid */
36
37 /* Write the default if data is invalid */
38 memset(device_data.payload, 0xff, DEVICE_DATA_PAYLOAD_SIZE); /* Invalid data */
39 device_data.length = DEVICE_DATA_PAYLOAD_SIZE;
40 device_data.crc = crc_32(device_data.payload, device_data.length, 0xffffffff);
41
42}
43
44/******************************************************************************/
45#endif /* ndef BOOTLOADER ******************************************************/
46/******************************************************************************/
47
48#if defined(HAVE_DEVICEDATA)
49void __attribute__((weak)) fill_devicedata(struct device_data_t *data)
50{
51 memset(data->payload, 0xff, data->length);
52}
53#endif
54
55/* Write bootdata into location in FIRMWARE marked by magic header
56 * Assumes buffer is already loaded with the firmware image
57 * We just need to find the location and write data into the
58 * payload region along with the crc for later verification and use.
59 * Returns payload len on success,
60 * On error returns false
61 */
62bool write_devicedata(unsigned char* buf, int len)
63{
64 int search_len = MIN(len, DEVICE_DATA_SEARCH_SIZE) - sizeof(struct device_data_t);
65
66 /* search for decvice data header prior to search_len */
67 for(int i = 0; i < search_len; i++)
68 {
69 struct device_data_t *data = (struct device_data_t *)&buf[i];
70 if (data->magic[0] != DEVICE_DATA_MAGIC0 ||
71 data->magic[1] != DEVICE_DATA_MAGIC1)
72 continue;
73
74 /* Ignore it if the length extends past the end of the buffer. */
75 int data_len = offsetof(struct device_data_t, payload) + data->length;
76 if (i + data_len > len)
77 continue;
78
79 fill_devicedata(data);
80
81 /* Calculate payload CRC */
82 data->crc = crc_32(data->payload, data->length, 0xffffffff);
83 return true;
84 }
85
86 return false;
87}
88
diff --git a/firmware/common/disk.c b/firmware/common/disk.c
index 576eede143..958f09755a 100644
--- a/firmware/common/disk.c
+++ b/firmware/common/disk.c
@@ -29,6 +29,7 @@
29#include "dir.h" 29#include "dir.h"
30#include "rb_namespace.h" 30#include "rb_namespace.h"
31#include "disk.h" 31#include "disk.h"
32#include "panic.h"
32 33
33#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) && !defined(BOOTLOADER) 34#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) && !defined(BOOTLOADER)
34#include "bootdata.h" 35#include "bootdata.h"
@@ -110,7 +111,7 @@ static void init_volume(struct volumeinfo *vi, int drive, int part)
110} 111}
111 112
112#ifdef MAX_LOG_SECTOR_SIZE 113#ifdef MAX_LOG_SECTOR_SIZE
113static int disk_sector_multiplier[NUM_DRIVES] = 114static uint16_t disk_sector_multiplier[NUM_DRIVES] =
114 { [0 ... NUM_DRIVES-1] = 1 }; 115 { [0 ... NUM_DRIVES-1] = 1 };
115 116
116int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)) 117int disk_get_sector_multiplier(IF_MD_NONVOID(int drive))
@@ -125,6 +126,33 @@ int disk_get_sector_multiplier(IF_MD_NONVOID(int drive))
125} 126}
126#endif /* MAX_LOG_SECTOR_SIZE */ 127#endif /* MAX_LOG_SECTOR_SIZE */
127 128
129#if (CONFIG_STORAGE & STORAGE_ATA) // XXX make this more generic?
130static uint16_t disk_log_sector_size[NUM_DRIVES] =
131 { [0 ... NUM_DRIVES-1] = SECTOR_SIZE }; /* Updated from STORAGE_INFO */
132int disk_get_log_sector_size(IF_MD_NONVOID(int drive))
133{
134 if (!CHECK_DRV(drive))
135 return 0;
136
137 disk_reader_lock();
138 int size = disk_log_sector_size[IF_MD_DRV(drive)];
139 disk_reader_unlock();
140 return size;
141}
142#ifdef HAVE_MULTIDRIVE
143#define LOG_SECTOR_SIZE(__drive) disk_log_sector_size[__drive]
144#else
145#define LOG_SECTOR_SIZE(__drive) disk_log_sector_size[0]
146#endif /* HAVE_MULTIDRIVE */
147#else /* !STORAGE_ATA */
148#define LOG_SECTOR_SIZE(__drive) SECTOR_SIZE
149int disk_get_log_sector_size(IF_MD_NONVOID(int drive))
150{
151 IF_MD((void)drive);
152 return SECTOR_SIZE;
153}
154#endif /* !CONFIG_STORAGE & STORAGE_ATA */
155
128bool disk_init(IF_MD_NONVOID(int drive)) 156bool disk_init(IF_MD_NONVOID(int drive))
129{ 157{
130 if (!CHECK_DRV(drive)) 158 if (!CHECK_DRV(drive))
@@ -134,7 +162,30 @@ bool disk_init(IF_MD_NONVOID(int drive))
134 if (!sector) 162 if (!sector)
135 return false; 163 return false;
136 164
137 memset(sector, 0, SECTOR_SIZE); 165#if (CONFIG_STORAGE & STORAGE_ATA)
166 /* Query logical sector size */
167 struct storage_info *info = (struct storage_info*) sector;
168 storage_get_info(IF_MD_DRV(drive), info);
169 disk_writer_lock();
170#ifdef MAX_LOG_SECTOR_SIZE
171 disk_log_sector_size[IF_MD_DRV(drive)] = info->sector_size;
172#endif
173 disk_writer_unlock();
174
175#ifdef MAX_LOG_SECTOR_SIZE
176 if (info->sector_size > MAX_LOG_SECTOR_SIZE) {
177 panicf("Unsupported logical sector size: %d",
178 info->sector_size);
179 }
180#else
181 if (info->sector_size != SECTOR_SIZE) {
182 panicf("Unsupported logical sector size: %d",
183 info->sector_size);
184 }
185#endif
186#endif /* CONFIG_STORAGE & STORAGE_ATA */
187
188 memset(sector, 0, LOG_SECTOR_SIZE(drive));
138 storage_read_sectors(IF_MD(drive,) 0, 1, sector); 189 storage_read_sectors(IF_MD(drive,) 0, 1, sector);
139 190
140 bool init = false; 191 bool init = false;
@@ -213,11 +264,11 @@ bool disk_init(IF_MD_NONVOID(int drive))
213reload: 264reload:
214 storage_read_sectors(IF_MD(drive,) part_lba, 1, sector); 265 storage_read_sectors(IF_MD(drive,) part_lba, 1, sector);
215 uint8_t *pptr = ptr; 266 uint8_t *pptr = ptr;
216 while (part < MAX_PARTITIONS_PER_DRIVE && part_entries) { 267 while (part < MAX_PARTITIONS_PER_DRIVE && part_entries) {
217 if (pptr - ptr >= SECTOR_SIZE) { 268 if (pptr - ptr >= LOG_SECTOR_SIZE(drive)) {
218 part_lba++; 269 part_lba++;
219 goto reload; 270 goto reload;
220 } 271 }
221 272
222 /* Parse GPT entry. We only care about the "General Data" type, ie: 273 /* Parse GPT entry. We only care about the "General Data" type, ie:
223 EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 274 EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
@@ -331,19 +382,18 @@ int disk_mount(int drive)
331 disk_sector_multiplier[IF_MD_DRV(drive)] = 1; 382 disk_sector_multiplier[IF_MD_DRV(drive)] = 1;
332#endif 383#endif
333 384
334 /* try "superfloppy" mode */ 385 /* try "superfloppy" mode */
335 DEBUGF("Trying to mount sector 0.\n"); 386 DEBUGF("Trying to mount sector 0.\n");
336 387
337 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) 0)) 388 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) 0))
338 { 389 {
339 #ifdef MAX_LOG_SECTOR_SIZE 390#ifdef MAX_LOG_SECTOR_SIZE
340 disk_sector_multiplier[drive] = 391 disk_sector_multiplier[drive] = fat_get_bytes_per_sector(IF_MV(volume)) / LOG_SECTOR_SIZE(drive);
341 fat_get_bytes_per_sector(IF_MV(volume)) / SECTOR_SIZE; 392#endif
342 #endif 393 mounted = 1;
343 mounted = 1; 394 init_volume(&volumes[volume], drive, 0);
344 init_volume(&volumes[volume], drive, 0); 395 volume_onmount_internal(IF_MV(volume));
345 volume_onmount_internal(IF_MV(volume)); 396 }
346 }
347 397
348 if (mounted == 0 && volume != -1) /* not a "superfloppy"? */ 398 if (mounted == 0 && volume != -1) /* not a "superfloppy"? */
349 { 399 {
@@ -354,10 +404,10 @@ int disk_mount(int drive)
354 if (pinfo[i].type == 0 || pinfo[i].type == 5) 404 if (pinfo[i].type == 0 || pinfo[i].type == 5)
355 continue; /* skip free/extended partitions */ 405 continue; /* skip free/extended partitions */
356 406
357 DEBUGF("Trying to mount partition %d.\n", i); 407 DEBUGF("Trying to mount partition %d.\n", i);
358 408
359 #ifdef MAX_LOG_SECTOR_SIZE 409#ifdef MAX_LOG_SECTOR_SIZE
360 for (int j = 1; j <= (MAX_LOG_SECTOR_SIZE/SECTOR_SIZE); j <<= 1) 410 for (int j = 1; j <= (MAX_LOG_SECTOR_SIZE/LOG_SECTOR_SIZE(drive)); j <<= 1)
361 { 411 {
362 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start * j)) 412 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start * j))
363 { 413 {
@@ -371,7 +421,7 @@ int disk_mount(int drive)
371 break; 421 break;
372 } 422 }
373 } 423 }
374 #else /* ndef MAX_LOG_SECTOR_SIZE */ 424#else /* ndef MAX_LOG_SECTOR_SIZE */
375 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start)) 425 if (!fat_mount(IF_MV(volume,) IF_MD(drive,) pinfo[i].start))
376 { 426 {
377 mounted++; 427 mounted++;
@@ -379,7 +429,7 @@ int disk_mount(int drive)
379 volume_onmount_internal(IF_MV(volume)); 429 volume_onmount_internal(IF_MV(volume));
380 volume = get_free_volume(); /* prepare next entry */ 430 volume = get_free_volume(); /* prepare next entry */
381 } 431 }
382 #endif /* MAX_LOG_SECTOR_SIZE */ 432#endif /* MAX_LOG_SECTOR_SIZE */
383 } 433 }
384 } 434 }
385 435
diff --git a/firmware/common/rb-loader.c b/firmware/common/rb-loader.c
index 61d8b1ddd2..2f5e06e165 100644
--- a/firmware/common/rb-loader.c
+++ b/firmware/common/rb-loader.c
@@ -30,6 +30,9 @@
30#include "multiboot.h" 30#include "multiboot.h"
31#endif 31#endif
32 32
33#ifdef HAVE_DEVICEDATA
34#include "devicedata.h"
35#endif
33/* loads a firmware file from supplied filename 36/* loads a firmware file from supplied filename
34 * file opened, checks firmware size and checksum 37 * file opened, checks firmware size and checksum
35 * if no error, firmware loaded to supplied buffer 38 * if no error, firmware loaded to supplied buffer
@@ -118,7 +121,6 @@ int load_firmware(unsigned char* buf, const char* firmware, int buffer_size)
118 /* if ret is valid breaks from loop to continue loading */ 121 /* if ret is valid breaks from loop to continue loading */
119 } 122 }
120#endif 123#endif
121
122 if (ret < 0) /* Check default volume, no valid firmware file loaded yet */ 124 if (ret < 0) /* Check default volume, no valid firmware file loaded yet */
123 { 125 {
124 /* First check in BOOTDIR */ 126 /* First check in BOOTDIR */
@@ -141,5 +143,9 @@ int load_firmware(unsigned char* buf, const char* firmware, int buffer_size)
141 else /* full path passed ROLO etc.*/ 143 else /* full path passed ROLO etc.*/
142 ret = load_firmware_filename(buf, firmware, buffer_size); 144 ret = load_firmware_filename(buf, firmware, buffer_size);
143 145
146#ifdef HAVE_DEVICEDATA
147 write_devicedata(buf, ret);
148#endif
149
144 return ret; 150 return ret;
145} 151}
diff --git a/firmware/drivers/ata-common.c b/firmware/drivers/ata-common.c
new file mode 100644
index 0000000000..53a7780262
--- /dev/null
+++ b/firmware/drivers/ata-common.c
@@ -0,0 +1,238 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2024 Solomon Peachy
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21/* This is intended to be #included into the ATA driver */
22
23#ifdef MAX_PHYS_SECTOR_SIZE
24
25struct sector_cache_entry {
26 unsigned char data[MAX_PHYS_SECTOR_SIZE];
27 sector_t sectornum; /* logical sector */
28 bool inuse;
29};
30/* buffer for reading and writing large physical sectors */
31static struct sector_cache_entry sector_cache STORAGE_ALIGN_ATTR;
32static int phys_sector_mult = 1;
33
34static int cache_sector(sector_t sector)
35{
36 int rc;
37
38 /* round down to physical sector boundary */
39 sector &= ~(phys_sector_mult - 1);
40
41 /* check whether the sector is already cached */
42 if (sector_cache.inuse && (sector_cache.sectornum == sector))
43 return 0;
44
45 /* not found: read the sector */
46 sector_cache.inuse = false;
47 rc = ata_transfer_sectors(sector, phys_sector_mult, sector_cache.data, false);
48 if (!rc)
49 {
50 sector_cache.sectornum = sector;
51 sector_cache.inuse = true;
52 }
53 return rc;
54}
55
56static inline int flush_current_sector(void)
57{
58 return ata_transfer_sectors(sector_cache.sectornum, phys_sector_mult,
59 sector_cache.data, true);
60}
61
62int ata_read_sectors(IF_MD(int drive,)
63 sector_t start,
64 int incount,
65 void* inbuf)
66{
67 int rc = 0;
68 int offset;
69
70#ifdef HAVE_MULTIDRIVE
71 (void)drive; /* unused for now */
72#endif
73 mutex_lock(&ata_mutex);
74
75 offset = start & (phys_sector_mult - 1);
76
77 if (offset) /* first partial sector */
78 {
79 int partcount = MIN(incount, phys_sector_mult - offset);
80
81 rc = cache_sector(start);
82 if (rc)
83 {
84 rc = rc * 10 - 1;
85 goto error;
86 }
87 memcpy(inbuf, sector_cache.data + offset * SECTOR_SIZE,
88 partcount * SECTOR_SIZE);
89
90 start += partcount;
91 inbuf += partcount * SECTOR_SIZE;
92 incount -= partcount;
93 }
94 if (incount)
95 {
96 offset = incount & (phys_sector_mult - 1);
97 incount -= offset;
98
99 if (incount)
100 {
101 rc = ata_transfer_sectors(start, incount, inbuf, false);
102 if (rc)
103 {
104 rc = rc * 10 - 2;
105 goto error;
106 }
107 start += incount;
108 inbuf += incount * SECTOR_SIZE;
109 }
110 if (offset)
111 {
112 rc = cache_sector(start);
113 if (rc)
114 {
115 rc = rc * 10 - 3;
116 goto error;
117 }
118 memcpy(inbuf, sector_cache.data, offset * SECTOR_SIZE);
119 }
120 }
121
122 error:
123 mutex_unlock(&ata_mutex);
124
125 return rc;
126}
127
128int ata_write_sectors(IF_MD(int drive,)
129 sector_t start,
130 int count,
131 const void* buf)
132{
133 int rc = 0;
134 int offset;
135
136#ifdef HAVE_MULTIDRIVE
137 (void)drive; /* unused for now */
138#endif
139 mutex_lock(&ata_mutex);
140
141 offset = start & (phys_sector_mult - 1);
142
143 if (offset) /* first partial sector */
144 {
145 int partcount = MIN(count, phys_sector_mult - offset);
146
147 rc = cache_sector(start);
148 if (rc)
149 {
150 rc = rc * 10 - 1;
151 goto error;
152 }
153 memcpy(sector_cache.data + offset * SECTOR_SIZE, buf,
154 partcount * SECTOR_SIZE);
155 rc = flush_current_sector();
156 if (rc)
157 {
158 rc = rc * 10 - 2;
159 goto error;
160 }
161 start += partcount;
162 buf += partcount * SECTOR_SIZE;
163 count -= partcount;
164 }
165 if (count)
166 {
167 offset = count & (phys_sector_mult - 1);
168 count -= offset;
169
170 if (count)
171 {
172 rc = ata_transfer_sectors(start, count, (void*)buf, true);
173 if (rc)
174 {
175 rc = rc * 10 - 3;
176 goto error;
177 }
178 start += count;
179 buf += count * SECTOR_SIZE;
180 }
181 if (offset)
182 {
183 rc = cache_sector(start);
184 if (rc)
185 {
186 rc = rc * 10 - 4;
187 goto error;
188 }
189 memcpy(sector_cache.data, buf, offset * SECTOR_SIZE);
190 rc = flush_current_sector();
191 if (rc)
192 {
193 rc = rc * 10 - 5;
194 goto error;
195 }
196 }
197 }
198
199 error:
200 mutex_unlock(&ata_mutex);
201
202 return rc;
203}
204
205static int ata_get_phys_sector_mult(void)
206{
207 int rc = 0;
208
209 /* Find out the physical sector size */
210 if((identify_info[106] & 0xe000) == 0x6000) /* B14, B13 */
211 phys_sector_mult = BIT_N(identify_info[106] & 0x000f);
212 else
213 phys_sector_mult = 1;
214
215 DEBUGF("ata: %d logical sectors per phys sector", phys_sector_mult);
216
217 if (phys_sector_mult > 1)
218 {
219 /* Check if drive really needs emulation - if we can access
220 sector 1 then assume the drive supports "512e" and will handle
221 it better than us, so ignore the large physical sectors.
222 */
223 char throwaway[SECTOR_SIZE];
224 rc = ata_transfer_sectors(1, 1, &throwaway, false);
225 if (rc == 0)
226 phys_sector_mult = 1;
227 }
228
229 if (phys_sector_mult > (MAX_PHYS_SECTOR_SIZE/SECTOR_SIZE))
230 panicf("Unsupported physical sector size: %d",
231 phys_sector_mult * SECTOR_SIZE);
232
233 memset(&sector_cache, 0, sizeof(sector_cache));
234
235 return 0;
236}
237
238#endif /* MAX_PHYS_SECTOR_SIZE */
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 7b9c4910cf..7b43d3c536 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -90,7 +90,7 @@ enum {
90 90
91static int ata_state = ATA_BOOT; 91static int ata_state = ATA_BOOT;
92 92
93static struct mutex ata_mtx SHAREDBSS_ATTR; 93static struct mutex ata_mutex SHAREDBSS_ATTR;
94static int ata_device; /* device 0 (master) or 1 (slave) */ 94static int ata_device; /* device 0 (master) or 1 (slave) */
95 95
96static int spinup_time = 0; 96static int spinup_time = 0;
@@ -101,8 +101,9 @@ static bool ata_led_on = false;
101 101
102static long sleep_timeout = 5*HZ; 102static long sleep_timeout = 5*HZ;
103#ifdef HAVE_LBA48 103#ifdef HAVE_LBA48
104static bool lba48 = false; /* set for 48 bit addressing */ 104static bool ata_lba48 = false; /* set for 48 bit addressing */
105#endif 105#endif
106static bool canflush = true;
106 107
107static long last_disk_activity = -1; 108static long last_disk_activity = -1;
108#ifdef HAVE_ATA_POWER_OFF 109#ifdef HAVE_ATA_POWER_OFF
@@ -111,20 +112,8 @@ static long power_off_tick = 0;
111 112
112static sector_t total_sectors; 113static sector_t total_sectors;
113static int multisectors; /* number of supported multisectors */ 114static int multisectors; /* number of supported multisectors */
114static unsigned short identify_info[ATA_IDENTIFY_WORDS];
115 115
116#ifdef MAX_PHYS_SECTOR_SIZE 116static unsigned short identify_info[ATA_IDENTIFY_WORDS] STORAGE_ALIGN_ATTR;
117
118struct sector_cache_entry {
119 bool inuse;
120 sector_t sectornum; /* logical sector */
121 unsigned char data[MAX_PHYS_SECTOR_SIZE];
122};
123/* buffer for reading and writing large physical sectors */
124#define NUMCACHES 2
125static struct sector_cache_entry sector_cache;
126static int phys_sector_mult = 1;
127#endif
128 117
129#ifdef HAVE_ATA_DMA 118#ifdef HAVE_ATA_DMA
130static int dma_mode = 0; 119static int dma_mode = 0;
@@ -142,11 +131,6 @@ static inline void keep_ata_active(void)
142 last_disk_activity = current_tick; 131 last_disk_activity = current_tick;
143} 132}
144 133
145static inline void schedule_ata_sleep(long from_now)
146{
147 last_disk_activity = current_tick - sleep_timeout + from_now;
148}
149
150static inline bool ata_sleep_timed_out(void) 134static inline bool ata_sleep_timed_out(void)
151{ 135{
152 return sleep_timeout && 136 return sleep_timeout &&
@@ -224,7 +208,7 @@ static int ata_perform_wakeup(int state)
224static int ata_perform_sleep(void) 208static int ata_perform_sleep(void)
225{ 209{
226 /* If device doesn't support PM features, don't try to sleep. */ 210 /* If device doesn't support PM features, don't try to sleep. */
227 if (!ata_disk_can_poweroff()) 211 if (!ata_disk_can_sleep())
228 return 0; // XXX or return a failure? 212 return 0; // XXX or return a failure?
229 213
230 logf("ata SLEEP %ld", current_tick); 214 logf("ata SLEEP %ld", current_tick);
@@ -258,13 +242,18 @@ static int ata_perform_flush_cache(void)
258{ 242{
259 uint8_t cmd; 243 uint8_t cmd;
260 244
261 if (identify_info[83] & (1 << 13)) { 245 if (!canflush) {
262 cmd = CMD_FLUSH_CACHE_EXT; 246 return 0;
247 } else if (ata_lba48 && identify_info[83] & (1 << 13)) {
248 cmd = CMD_FLUSH_CACHE_EXT; /* Flag, optional, ATA-6 and up, for use with LBA48 devices */
263 } else if (identify_info[83] & (1 << 12)) { 249 } else if (identify_info[83] & (1 << 12)) {
264 cmd = CMD_FLUSH_CACHE; 250 cmd = CMD_FLUSH_CACHE; /* Flag, mandatory, ATA-6 and up */
251 } else if (identify_info[80] >= (1 << 5)) { /* Use >= instead of '&' because bits lower than the latest standard we support don't have to be set */
252 cmd = CMD_FLUSH_CACHE; /* No flag, mandatory, ATA-5 (Optional for ATA-4) */
265 } else { 253 } else {
266 /* If neither (mandatory!) command is supported 254 /* If neither (mandatory!) command is supported
267 then don't issue it. */ 255 then don't issue it. */
256 canflush = 0;
268 return 0; 257 return 0;
269 } 258 }
270 259
@@ -287,6 +276,16 @@ static int ata_perform_flush_cache(void)
287 return 0; 276 return 0;
288} 277}
289 278
279int ata_flush(void)
280{
281 if (ata_state >= ATA_SPINUP) {
282 mutex_lock(&ata_mutex);
283 ata_perform_flush_cache();
284 mutex_unlock(&ata_mutex);
285 }
286 return 0;
287}
288
290static ICODE_ATTR int wait_for_start_of_transfer(void) 289static ICODE_ATTR int wait_for_start_of_transfer(void)
291{ 290{
292 if (!wait_for_bsy()) 291 if (!wait_for_bsy())
@@ -437,7 +436,7 @@ static int ata_transfer_sectors(uint64_t start,
437#endif 436#endif
438 437
439#ifdef HAVE_LBA48 438#ifdef HAVE_LBA48
440 if (lba48) 439 if (ata_lba48)
441 { 440 {
442 ATA_OUT8(ATA_NSECTOR, count >> 8); 441 ATA_OUT8(ATA_NSECTOR, count >> 8);
443 ATA_OUT8(ATA_NSECTOR, count & 0xff); 442 ATA_OUT8(ATA_NSECTOR, count & 0xff);
@@ -464,7 +463,7 @@ static int ata_transfer_sectors(uint64_t start,
464 ATA_OUT8(ATA_SECTOR, start & 0xff); 463 ATA_OUT8(ATA_SECTOR, start & 0xff);
465 ATA_OUT8(ATA_LCYL, (start >> 8) & 0xff); 464 ATA_OUT8(ATA_LCYL, (start >> 8) & 0xff);
466 ATA_OUT8(ATA_HCYL, (start >> 16) & 0xff); 465 ATA_OUT8(ATA_HCYL, (start >> 16) & 0xff);
467 ATA_OUT8(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); 466 ATA_OUT8(ATA_SELECT, ((start >> 24) & 0xf) | SELECT_LBA | ata_device); /* LBA28, mask off upper 4 bits of 32-bit sector address */
468#ifdef HAVE_ATA_DMA 467#ifdef HAVE_ATA_DMA
469 if (write) 468 if (write)
470 ATA_OUT8(ATA_COMMAND, usedma ? CMD_WRITE_DMA : CMD_WRITE_MULTIPLE); 469 ATA_OUT8(ATA_COMMAND, usedma ? CMD_WRITE_DMA : CMD_WRITE_MULTIPLE);
@@ -590,6 +589,8 @@ static int ata_transfer_sectors(uint64_t start,
590 return ret; 589 return ret;
591} 590}
592 591
592#include "ata-common.c"
593
593#ifndef MAX_PHYS_SECTOR_SIZE 594#ifndef MAX_PHYS_SECTOR_SIZE
594int ata_read_sectors(IF_MD(int drive,) 595int ata_read_sectors(IF_MD(int drive,)
595 sector_t start, 596 sector_t start,
@@ -600,9 +601,9 @@ int ata_read_sectors(IF_MD(int drive,)
600 (void)drive; /* unused for now */ 601 (void)drive; /* unused for now */
601#endif 602#endif
602 603
603 mutex_lock(&ata_mtx); 604 mutex_lock(&ata_mutex);
604 int rc = ata_transfer_sectors(start, incount, inbuf, false); 605 int rc = ata_transfer_sectors(start, incount, inbuf, false);
605 mutex_unlock(&ata_mtx); 606 mutex_unlock(&ata_mutex);
606 return rc; 607 return rc;
607} 608}
608 609
@@ -615,186 +616,13 @@ int ata_write_sectors(IF_MD(int drive,)
615 (void)drive; /* unused for now */ 616 (void)drive; /* unused for now */
616#endif 617#endif
617 618
618 mutex_lock(&ata_mtx); 619 mutex_lock(&ata_mutex);
619 int rc = ata_transfer_sectors(start, count, (void*)buf, true); 620 int rc = ata_transfer_sectors(start, count, (void*)buf, true);
620 mutex_unlock(&ata_mtx); 621 mutex_unlock(&ata_mutex);
621 return rc; 622 return rc;
622} 623}
623#endif /* ndef MAX_PHYS_SECTOR_SIZE */ 624#endif /* ndef MAX_PHYS_SECTOR_SIZE */
624 625
625#ifdef MAX_PHYS_SECTOR_SIZE
626static int cache_sector(sector_t sector)
627{
628 int rc;
629
630 sector &= ~(phys_sector_mult - 1);
631 /* round down to physical sector boundary */
632
633 /* check whether the sector is already cached */
634 if (sector_cache.inuse && (sector_cache.sectornum == sector))
635 return 0;
636
637 /* not found: read the sector */
638 sector_cache.inuse = false;
639 rc = ata_transfer_sectors(sector, phys_sector_mult, sector_cache.data, false);
640 if (!rc)
641 {
642 sector_cache.sectornum = sector;
643 sector_cache.inuse = true;
644 }
645 return rc;
646}
647
648static inline int flush_current_sector(void)
649{
650 return ata_transfer_sectors(sector_cache.sectornum, phys_sector_mult,
651 sector_cache.data, true);
652}
653
654int ata_read_sectors(IF_MD(int drive,)
655 sector_t start,
656 int incount,
657 void* inbuf)
658{
659 int rc = 0;
660 int offset;
661
662#ifdef HAVE_MULTIDRIVE
663 (void)drive; /* unused for now */
664#endif
665 mutex_lock(&ata_mtx);
666
667 offset = start & (phys_sector_mult - 1);
668
669 if (offset) /* first partial sector */
670 {
671 int partcount = MIN(incount, phys_sector_mult - offset);
672
673 rc = cache_sector(start);
674 if (rc)
675 {
676 rc = rc * 10 - 1;
677 goto error;
678 }
679 memcpy(inbuf, sector_cache.data + offset * SECTOR_SIZE,
680 partcount * SECTOR_SIZE);
681
682 start += partcount;
683 inbuf += partcount * SECTOR_SIZE;
684 incount -= partcount;
685 }
686 if (incount)
687 {
688 offset = incount & (phys_sector_mult - 1);
689 incount -= offset;
690
691 if (incount)
692 {
693 rc = ata_transfer_sectors(start, incount, inbuf, false);
694 if (rc)
695 {
696 rc = rc * 10 - 2;
697 goto error;
698 }
699 start += incount;
700 inbuf += incount * SECTOR_SIZE;
701 }
702 if (offset)
703 {
704 rc = cache_sector(start);
705 if (rc)
706 {
707 rc = rc * 10 - 3;
708 goto error;
709 }
710 memcpy(inbuf, sector_cache.data, offset * SECTOR_SIZE);
711 }
712 }
713
714 error:
715 mutex_unlock(&ata_mtx);
716
717 return rc;
718}
719
720int ata_write_sectors(IF_MD(int drive,)
721 sector_t start,
722 int count,
723 const void* buf)
724{
725 int rc = 0;
726 int offset;
727
728#ifdef HAVE_MULTIDRIVE
729 (void)drive; /* unused for now */
730#endif
731 mutex_lock(&ata_mtx);
732
733 offset = start & (phys_sector_mult - 1);
734
735 if (offset) /* first partial sector */
736 {
737 int partcount = MIN(count, phys_sector_mult - offset);
738
739 rc = cache_sector(start);
740 if (rc)
741 {
742 rc = rc * 10 - 1;
743 goto error;
744 }
745 memcpy(sector_cache.data + offset * SECTOR_SIZE, buf,
746 partcount * SECTOR_SIZE);
747 rc = flush_current_sector();
748 if (rc)
749 {
750 rc = rc * 10 - 2;
751 goto error;
752 }
753 start += partcount;
754 buf += partcount * SECTOR_SIZE;
755 count -= partcount;
756 }
757 if (count)
758 {
759 offset = count & (phys_sector_mult - 1);
760 count -= offset;
761
762 if (count)
763 {
764 rc = ata_transfer_sectors(start, count, (void*)buf, true);
765 if (rc)
766 {
767 rc = rc * 10 - 3;
768 goto error;
769 }
770 start += count;
771 buf += count * SECTOR_SIZE;
772 }
773 if (offset)
774 {
775 rc = cache_sector(start);
776 if (rc)
777 {
778 rc = rc * 10 - 4;
779 goto error;
780 }
781 memcpy(sector_cache.data, buf, offset * SECTOR_SIZE);
782 rc = flush_current_sector();
783 if (rc)
784 {
785 rc = rc * 10 - 5;
786 goto error;
787 }
788 }
789 }
790
791 error:
792 mutex_unlock(&ata_mtx);
793
794 return rc;
795}
796#endif /* MAX_PHYS_SECTOR_SIZE */
797
798static int STORAGE_INIT_ATTR check_registers(void) 626static int STORAGE_INIT_ATTR check_registers(void)
799{ 627{
800 int i; 628 int i;
@@ -845,24 +673,25 @@ void ata_spindown(int seconds)
845 673
846bool ata_disk_is_active(void) 674bool ata_disk_is_active(void)
847{ 675{
848 return ata_state >= ATA_SPINUP; 676 return (ata_state >= ATA_SPINUP);
849} 677}
850 678
851void ata_sleepnow(void) 679void ata_sleepnow(void)
852{ 680{
853 if (ata_state >= ATA_SPINUP) { 681 if (ata_state >= ATA_SPINUP) {
854 logf("ata SLEEPNOW %ld", current_tick); 682 logf("ata SLEEPNOW %ld", current_tick);
855 mutex_lock(&ata_mtx); 683 mutex_lock(&ata_mutex);
856 if (ata_state == ATA_ON) { 684 if (ata_state == ATA_ON) {
857 if (!ata_perform_flush_cache() && !ata_perform_sleep()) { 685 if (!ata_perform_flush_cache() && !ata_perform_sleep()) {
858 ata_state = ATA_SLEEPING; 686 ata_state = ATA_SLEEPING;
859#ifdef HAVE_ATA_POWER_OFF 687#ifdef HAVE_ATA_POWER_OFF
860 if (ata_disk_can_poweroff()) 688 if (ata_disk_can_sleep() || canflush) {
861 power_off_tick = current_tick + ATA_POWER_OFF_TIMEOUT; 689 power_off_tick = current_tick + ATA_POWER_OFF_TIMEOUT;
690 }
862#endif 691#endif
863 } 692 }
864 } 693 }
865 mutex_unlock(&ata_mtx); 694 mutex_unlock(&ata_mutex);
866 } 695 }
867} 696}
868 697
@@ -880,7 +709,7 @@ static int STORAGE_INIT_ATTR ata_hard_reset(void)
880{ 709{
881 int ret; 710 int ret;
882 711
883 mutex_lock(&ata_mtx); 712 mutex_lock(&ata_mutex);
884 713
885 ata_reset(); 714 ata_reset();
886 715
@@ -891,7 +720,7 @@ static int STORAGE_INIT_ATTR ata_hard_reset(void)
891 /* Massage the return code so it is 0 on success and -1 on failure */ 720 /* Massage the return code so it is 0 on success and -1 on failure */
892 ret = ret?0:-1; 721 ret = ret?0:-1;
893 722
894 mutex_unlock(&ata_mtx); 723 mutex_unlock(&ata_mutex);
895 724
896 return ret; 725 return ret;
897} 726}
@@ -968,6 +797,9 @@ static int perform_soft_reset(void)
968 if (set_multiple_mode(multisectors)) 797 if (set_multiple_mode(multisectors))
969 return -3; 798 return -3;
970 799
800 if (identify())
801 return -2;
802
971 if (freeze_lock()) 803 if (freeze_lock())
972 return -4; 804 return -4;
973 805
@@ -978,13 +810,13 @@ int ata_soft_reset(void)
978{ 810{
979 int ret = -6; 811 int ret = -6;
980 812
981 mutex_lock(&ata_mtx); 813 mutex_lock(&ata_mutex);
982 814
983 if (ata_state > ATA_OFF) { 815 if (ata_state > ATA_OFF) {
984 ret = perform_soft_reset(); 816 ret = perform_soft_reset();
985 } 817 }
986 818
987 mutex_unlock(&ata_mtx); 819 mutex_unlock(&ata_mutex);
988 return ret; 820 return ret;
989} 821}
990 822
@@ -1018,6 +850,9 @@ static int ata_power_on(void)
1018 if (set_multiple_mode(multisectors)) 850 if (set_multiple_mode(multisectors))
1019 return -3; 851 return -3;
1020 852
853 if (identify())
854 return -2;
855
1021 if (freeze_lock()) 856 if (freeze_lock())
1022 return -4; 857 return -4;
1023 858
@@ -1068,7 +903,7 @@ static int set_multiple_mode(int sectors)
1068} 903}
1069 904
1070#ifdef HAVE_ATA_DMA 905#ifdef HAVE_ATA_DMA
1071static int get_best_mode(unsigned short identword, int max, int modetype) 906static int ata_get_best_mode(unsigned short identword, int max, int modetype)
1072{ 907{
1073 unsigned short testbit = BIT_N(max); 908 unsigned short testbit = BIT_N(max);
1074 909
@@ -1117,13 +952,18 @@ static int set_features(void)
1117 952
1118#ifdef HAVE_ATA_DMA 953#ifdef HAVE_ATA_DMA
1119 if (identify_info[53] & (1<<2)) { 954 if (identify_info[53] & (1<<2)) {
955 int max_udma = ATA_MAX_UDMA;
956#if ATA_MAX_UDMA > 2
957 if (!(identify_info[93] & (1<<13)))
958 max_udma = 2;
959#endif
1120 /* Ultra DMA mode info present, find a mode */ 960 /* Ultra DMA mode info present, find a mode */
1121 dma_mode = get_best_mode(identify_info[88], ATA_MAX_UDMA, 0x40); 961 dma_mode = ata_get_best_mode(identify_info[88], max_udma, 0x40);
1122 } 962 }
1123 963
1124 if (!dma_mode) { 964 if (!dma_mode) {
1125 /* No UDMA mode found, try to find a multi-word DMA mode */ 965 /* No UDMA mode found, try to find a multi-word DMA mode */
1126 dma_mode = get_best_mode(identify_info[63], ATA_MAX_MWDMA, 0x20); 966 dma_mode = ata_get_best_mode(identify_info[63], ATA_MAX_MWDMA, 0x20);
1127 features[1].id_word = 63; 967 features[1].id_word = 63;
1128 } else { 968 } else {
1129 features[1].id_word = 88; 969 features[1].id_word = 88;
@@ -1210,19 +1050,16 @@ int STORAGE_INIT_ATTR ata_init(void)
1210 bool coldstart; 1050 bool coldstart;
1211 1051
1212 if (ata_state == ATA_BOOT) { 1052 if (ata_state == ATA_BOOT) {
1213 mutex_init(&ata_mtx); 1053 mutex_init(&ata_mutex);
1214 } 1054 }
1215 1055
1216 mutex_lock(&ata_mtx); 1056 mutex_lock(&ata_mutex);
1217 1057
1218 /* must be called before ata_device_init() */ 1058 /* must be called before ata_device_init() */
1219 coldstart = ata_is_coldstart(); 1059 coldstart = ata_is_coldstart();
1220 ata_led(false); 1060 ata_led(false);
1221 ata_device_init(); 1061 ata_device_init();
1222 ata_enable(true); 1062 ata_enable(true);
1223#ifdef MAX_PHYS_SECTOR_SIZE
1224 memset(&sector_cache, 0, sizeof(sector_cache));
1225#endif
1226 1063
1227 if (ata_state == ATA_BOOT) { 1064 if (ata_state == ATA_BOOT) {
1228 ata_state = ATA_OFF; 1065 ata_state = ATA_OFF;
@@ -1251,7 +1088,6 @@ int STORAGE_INIT_ATTR ata_init(void)
1251 } 1088 }
1252 1089
1253 rc = identify(); 1090 rc = identify();
1254
1255 if (rc) { 1091 if (rc) {
1256 rc = -40 + rc; 1092 rc = -40 + rc;
1257 goto error; 1093 goto error;
@@ -1263,57 +1099,37 @@ int STORAGE_INIT_ATTR ata_init(void)
1263 1099
1264 DEBUGF("ata: %d sectors per ata request\n",multisectors); 1100 DEBUGF("ata: %d sectors per ata request\n",multisectors);
1265 1101
1266 total_sectors = identify_info[60] | (identify_info[61] << 16); 1102 total_sectors = (identify_info[61] << 16) | identify_info[60];
1267 1103
1268#ifdef HAVE_LBA48 1104#ifdef HAVE_LBA48
1269 if (identify_info[83] & 0x0400 /* 48 bit address support */ 1105 if (identify_info[83] & 0x0400 && total_sectors == 0x0FFFFFFF) {
1270 && total_sectors == 0x0FFFFFFF) /* and disk size >= 128 GiB */ 1106 total_sectors = ((uint64_t)identify_info[103] << 48) |
1271 { /* (needs BigLBA addressing) */ 1107 ((uint64_t)identify_info[102] << 32) |
1272 total_sectors = identify_info[100] | (identify_info[101] << 16) | ((uint64_t)identify_info[102] << 32) | ((uint64_t)identify_info[103] << 48); 1108 ((uint64_t)identify_info[101] << 16) |
1273 1109 identify_info[100];
1274 lba48 = true; /* use BigLBA */ 1110 ata_lba48 = true; /* use BigLBA */
1275 } 1111 }
1276#endif /* HAVE_LBA48 */ 1112#endif /* HAVE_LBA48 */
1277 1113
1278 rc = freeze_lock(); 1114 rc = freeze_lock();
1279
1280 if (rc) { 1115 if (rc) {
1281 rc = -50 + rc; 1116 rc = -50 + rc;
1282 goto error; 1117 goto error;
1283 } 1118 }
1284 1119
1285 rc = set_features(); // rror codes are between -1 and -49 1120 rc = set_features(); // error codes are between -1 and -49
1286 if (rc) { 1121 if (rc) {
1287 rc = -60 + rc; 1122 rc = -60 + rc;
1288 goto error; 1123 goto error;
1289 } 1124 }
1290 1125
1291#ifdef MAX_PHYS_SECTOR_SIZE 1126#ifdef MAX_PHYS_SECTOR_SIZE
1292 /* Find out the physical sector size */ 1127 rc = ata_get_phys_sector_mult();
1293 if((identify_info[106] & 0xe000) == 0x6000) 1128 if (rc) {
1294 phys_sector_mult = BIT_N(identify_info[106] & 0x000f); 1129 rc = -70 + rc;
1295 else 1130 goto error;
1296 phys_sector_mult = 1;
1297
1298 DEBUGF("ata: %d logical sectors per phys sector", phys_sector_mult);
1299
1300 if (phys_sector_mult > 1)
1301 {
1302 /* Check if drive really needs emulation - if we can access
1303 * sector 1 then assume the drive will handle it better than
1304 * us, and ignore the large physical sectors.
1305 */
1306 char throwaway[SECTOR_SIZE];
1307 rc = ata_transfer_sectors(1, 1, &throwaway, false);
1308 if (rc == 0)
1309 phys_sector_mult = 1;
1310 } 1131 }
1311 1132#endif
1312 if (phys_sector_mult > (MAX_PHYS_SECTOR_SIZE/SECTOR_SIZE))
1313 panicf("Unsupported physical sector size: %d",
1314 phys_sector_mult * SECTOR_SIZE);
1315#endif /* MAX_PHYS_SECTOR_SIZE */
1316
1317 ata_state = ATA_ON; 1133 ata_state = ATA_ON;
1318 keep_ata_active(); 1134 keep_ata_active();
1319 } 1135 }
@@ -1321,8 +1137,14 @@ int STORAGE_INIT_ATTR ata_init(void)
1321 if (rc) 1137 if (rc)
1322 rc = -100 + rc; 1138 rc = -100 + rc;
1323 1139
1140 rc = identify();
1141 if (rc) {
1142 rc = -40 + rc;
1143 goto error;
1144 }
1145
1324error: 1146error:
1325 mutex_unlock(&ata_mtx); 1147 mutex_unlock(&ata_mutex);
1326 return rc; 1148 return rc;
1327} 1149}
1328 1150
@@ -1359,9 +1181,9 @@ void ata_get_info(IF_MD(int drive,)struct storage_info *info)
1359#endif 1181#endif
1360 int i; 1182 int i;
1361 1183
1362 /* Logical sector size */ 1184 /* Logical sector size > 512B ? */
1363 if ((identify_info[106] & 0xd000) == 0x5000) 1185 if ((identify_info[106] & 0xd000) == 0x5000) /* B14, B12 */
1364 info->sector_size = identify_info[117] | (identify_info[118] << 16); 1186 info->sector_size = (identify_info[117] | (identify_info[118] << 16)) * 2;
1365 else 1187 else
1366 info->sector_size = SECTOR_SIZE; 1188 info->sector_size = SECTOR_SIZE;
1367 1189
@@ -1422,11 +1244,11 @@ int ata_event(long id, intptr_t data)
1422#ifdef HAVE_ATA_POWER_OFF 1244#ifdef HAVE_ATA_POWER_OFF
1423 if (ata_state == ATA_SLEEPING && ata_power_off_timed_out()) { 1245 if (ata_state == ATA_SLEEPING && ata_power_off_timed_out()) {
1424 power_off_tick = 0; 1246 power_off_tick = 0;
1425 mutex_lock(&ata_mtx); 1247 mutex_lock(&ata_mutex);
1426 logf("ata OFF %ld", current_tick); 1248 logf("ata OFF %ld", current_tick);
1427 ide_power_enable(false); 1249 ide_power_enable(false);
1428 ata_state = ATA_OFF; 1250 ata_state = ATA_OFF;
1429 mutex_unlock(&ata_mtx); 1251 mutex_unlock(&ata_mutex);
1430 } 1252 }
1431#endif 1253#endif
1432 STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); 1254 STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA);
@@ -1436,7 +1258,7 @@ int ata_event(long id, intptr_t data)
1436 ata_sleepnow(); 1258 ata_sleepnow();
1437 } 1259 }
1438 else if (id == Q_STORAGE_SLEEP) { 1260 else if (id == Q_STORAGE_SLEEP) {
1439 schedule_ata_sleep(HZ/5); 1261 last_disk_activity = current_tick - sleep_timeout + HZ / 5;
1440 } 1262 }
1441#ifndef USB_NONE 1263#ifndef USB_NONE
1442 else if (id == SYS_USB_CONNECTED) { 1264 else if (id == SYS_USB_CONNECTED) {
@@ -1446,7 +1268,7 @@ int ata_event(long id, intptr_t data)
1446 STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA); 1268 STG_EVENT_ASSERT_ACTIVE(STORAGE_ATA);
1447 } 1269 }
1448 else { 1270 else {
1449 mutex_lock(&ata_mtx); 1271 mutex_lock(&ata_mutex);
1450 if (ata_state < ATA_ON) { 1272 if (ata_state < ATA_ON) {
1451 ata_led(true); 1273 ata_led(true);
1452 if (!(rc = ata_perform_wakeup(ata_state))) { 1274 if (!(rc = ata_perform_wakeup(ata_state))) {
@@ -1454,7 +1276,7 @@ int ata_event(long id, intptr_t data)
1454 } 1276 }
1455 ata_led(false); 1277 ata_led(false);
1456 } 1278 }
1457 mutex_unlock(&ata_mtx); 1279 mutex_unlock(&ata_mutex);
1458 } 1280 }
1459 } 1281 }
1460#endif /* ndef USB_NONE */ 1282#endif /* ndef USB_NONE */
diff --git a/firmware/drivers/audio/erosqlinux_codec.c b/firmware/drivers/audio/erosqlinux_codec.c
index 02c35e3c00..d1b3e884d3 100644
--- a/firmware/drivers/audio/erosqlinux_codec.c
+++ b/firmware/drivers/audio/erosqlinux_codec.c
@@ -53,11 +53,29 @@
53 BUFFER_BYTES: [4096 524288] 53 BUFFER_BYTES: [4096 524288]
54 TICK_TIME: ALL 54 TICK_TIME: ALL
55 55
56 Mixer controls: 56 Mixer controls (v1):
57 57
58 numid=1,iface=MIXER,name='Output Port Switch' 58 numid=1,iface=MIXER,name='Output Port Switch'
59 ; type=INTEGER,access=rw------,values=1,min=0,max=5,step=0 59 ; type=INTEGER,access=rw------,values=1,min=0,max=5,step=0
60 : values=4 60 : values=4
61
62 Mixer controls (v2+):
63
64 numid=3,iface=MIXER,name='ES9018_K2M Digital Filter'
65 ; type=INTEGER,access=rw------,values=1,min=0,max=4,step=0
66 : values=0
67 numid=1,iface=MIXER,name='Left Playback Volume'
68 ; type=INTEGER,access=rw------,values=1,min=0,max=255,step=0
69 : values=0
70 numid=4,iface=MIXER,name='Output Port Switch'
71 ; type=INTEGER,access=rw------,values=1,min=0,max=5,step=0
72 : values=0
73 numid=2,iface=MIXER,name='Right Playback Volume'
74 ; type=INTEGER,access=rw------,values=1,min=0,max=255,step=0
75 : values=0
76 numid=5,iface=MIXER,name='isDSD'
77 ; type=BOOLEAN,access=rw------,values=1
78 : values=off
61*/ 79*/
62 80
63static int hw_init = 0; 81static int hw_init = 0;
@@ -68,6 +86,8 @@ static long int last_ps = -1;
68 86
69static int muted = -1; 87static int muted = -1;
70 88
89extern int hwver;
90
71void audiohw_mute(int mute) 91void audiohw_mute(int mute)
72{ 92{
73 logf("mute %d", mute); 93 logf("mute %d", mute);
@@ -129,6 +149,13 @@ void audiohw_preinit(void)
129 logf("hw preinit"); 149 logf("hw preinit");
130 alsa_controls_init("default"); 150 alsa_controls_init("default");
131 hw_init = 1; 151 hw_init = 1;
152
153 /* See if we have hw2 or later */
154 if (alsa_controls_find("Left Playback Volume") == -1)
155 hwver = 1;
156 else if (hwver == 1)
157 hwver = 23;
158
132 audiohw_mute(false); /* No need to stay muted */ 159 audiohw_mute(false); /* No need to stay muted */
133} 160}
134 161
@@ -154,10 +181,8 @@ void audiohw_set_frequency(int fsel)
154const int min_pcm = -740; 181const int min_pcm = -740;
155const int max_pcm = 0; 182const int max_pcm = 0;
156 183
157void audiohw_set_volume(int vol_l, int vol_r) 184static void audiohw_set_volume_v1(int vol_l, int vol_r)
158{ 185{
159 logf("hw vol %d %d", vol_l, vol_r);
160
161 long l,r; 186 long l,r;
162 187
163 vol_l_hw = vol_l; 188 vol_l_hw = vol_l;
@@ -180,6 +205,39 @@ void audiohw_set_volume(int vol_l, int vol_r)
180 pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); 205 pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20);
181} 206}
182 207
208static void audiohw_set_volume_v2(int vol_l, int vol_r)
209{
210 long l,r;
211
212 if (lineout_inserted()) {
213 vol_l_hw = vol_r_hw = global_settings.volume_limit * 10;
214 } else {
215 vol_l_hw = -vol_l;
216 vol_r_hw = -vol_r;
217 }
218
219 if (!hw_init)
220 return;
221
222 l = vol_l_hw / 5;
223 r = vol_l_hw / 5;
224
225 alsa_controls_set_ints("Left Playback Volume", 1, &l);
226 alsa_controls_set_ints("Right Playback Volume", 1, &r);
227
228 /* Dial back PCM mixer to avoid compression */
229 pcm_set_mixer_volume(global_settings.volume_limit / 2, global_settings.volume_limit / 2);
230}
231
232void audiohw_set_volume(int vol_l, int vol_r)
233{
234 if (hwver >= 2) {
235 audiohw_set_volume_v2(vol_l, vol_r);
236 } else {
237 audiohw_set_volume_v1(vol_l, vol_r);
238 }
239}
240
183void audiohw_set_lineout_volume(int vol_l, int vol_r) 241void audiohw_set_lineout_volume(int vol_l, int vol_r)
184{ 242{
185 long l,r; 243 long l,r;
@@ -196,7 +254,16 @@ void audiohw_set_lineout_volume(int vol_l, int vol_r)
196 r = vol_r_hw; 254 r = vol_r_hw;
197 } 255 }
198 256
199 int sw_volume_l = l <= min_pcm ? min_pcm : MIN(l, max_pcm); 257 if (hwver >= 2) {
200 int sw_volume_r = r <= min_pcm ? min_pcm : MIN(r, max_pcm); 258 if (hw_init) {
201 pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); 259 l /= 5;
260 r /= 5;
261 alsa_controls_set_ints("Left Playback Volume", 1, &l);
262 alsa_controls_set_ints("Right Playback Volume", 1, &r);
263 }
264 } else {
265 int sw_volume_l = l <= min_pcm ? min_pcm : MIN(l, max_pcm);
266 int sw_volume_r = r <= min_pcm ? min_pcm : MIN(r, max_pcm);
267 pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20);
268 }
202} 269}
diff --git a/firmware/drivers/lcd-scroll.c b/firmware/drivers/lcd-scroll.c
index 895cf98cba..2a58d6ff21 100644
--- a/firmware/drivers/lcd-scroll.c
+++ b/firmware/drivers/lcd-scroll.c
@@ -195,8 +195,14 @@ static void LCDFN(scroll_worker)(void)
195 s = &si->scroll[index]; 195 s = &si->scroll[index];
196 196
197 /* check pause */ 197 /* check pause */
198 if (TIME_BEFORE(current_tick, s->start_tick)) 198 if (TIME_BEFORE(current_tick, s->start_tick)) {
199 continue; 199 continue;
200 }
201
202 if (global_settings.disable_mainmenu_scrolling && get_current_activity() == ACTIVITY_MAINMENU) {
203 // No scrolling on the main menu if disabled (to not break themes with lockscreens)
204 continue;
205 }
200 206
201 s->start_tick = current_tick; 207 s->start_tick = current_tick;
202 208
diff --git a/firmware/drivers/ramdisk.c b/firmware/drivers/ramdisk.c
index cecc943352..5798de252e 100644
--- a/firmware/drivers/ramdisk.c
+++ b/firmware/drivers/ramdisk.c
@@ -22,9 +22,10 @@
22#include <stdbool.h> 22#include <stdbool.h>
23#include <string.h> 23#include <string.h>
24 24
25#include "config.h"
26#include "fs_defines.h"
25#include "storage.h" 27#include "storage.h"
26 28
27#define SECTOR_SIZE 512
28#define NUM_SECTORS 16384 29#define NUM_SECTORS 16384
29 30
30static unsigned char ramdisk[SECTOR_SIZE * NUM_SECTORS]; 31static unsigned char ramdisk[SECTOR_SIZE * NUM_SECTORS];
diff --git a/firmware/drivers/rtc/rtc_pcf50606.c b/firmware/drivers/rtc/rtc_pcf50606.c
index 16ae5a3e9c..8f5371635c 100644
--- a/firmware/drivers/rtc/rtc_pcf50606.c
+++ b/firmware/drivers/rtc/rtc_pcf50606.c
@@ -57,7 +57,7 @@ int rtc_read_datetime(struct tm *tm)
57 tm->tm_mday = buf[4]; 57 tm->tm_mday = buf[4];
58 tm->tm_mon = buf[5] - 1; 58 tm->tm_mon = buf[5] - 1;
59 59
60#ifdef IRIVER_H300_SERIES 60#ifdef IRIVER_H300_SERIES
61 /* Special kludge to coexist with the iriver firmware. The iriver firmware 61 /* Special kludge to coexist with the iriver firmware. The iriver firmware
62 stores the date as 1965+nn, and allows a range of 1980..2064. We use 62 stores the date as 1965+nn, and allows a range of 1980..2064. We use
63 1964+nn here to make leap years work correctly, so the date will be one 63 1964+nn here to make leap years work correctly, so the date will be one
@@ -158,7 +158,7 @@ bool rtc_check_alarm_started(bool release_alarm)
158 158
159 if (run_before) { 159 if (run_before) {
160 rc = alarm_state; 160 rc = alarm_state;
161 alarm_state &= ~release_alarm; 161 alarm_state &= !release_alarm;
162 } else { 162 } else {
163 char rt[3], at[3]; 163 char rt[3], at[3];
164 /* The Ipod bootloader seems to read (and thus clear) the PCF interrupt 164 /* The Ipod bootloader seems to read (and thus clear) the PCF interrupt
diff --git a/firmware/drivers/tuner/rda5802.c b/firmware/drivers/tuner/rda5802.c
index 377bdd1e6f..55e775e985 100644
--- a/firmware/drivers/tuner/rda5802.c
+++ b/firmware/drivers/tuner/rda5802.c
@@ -42,17 +42,17 @@
42#define RSSI_MAX 70 42#define RSSI_MAX 70
43 43
44/** Registers and bits **/ 44/** Registers and bits **/
45#define CHIPID 0x0
45#define POWERCFG 0x2 46#define POWERCFG 0x2
46#define CHANNEL 0x3 47#define CHANNEL 0x3
47#define SYSCONFIG1 0x4 48#define SYSCONFIG1 0x4
48#define SYSCONFIG2 0x5 49#define SYSCONFIG2 0x5
49#define SYSCONFIG3 0x6 50#define SYSCONFIG3 0x6
50#define SYSCONFIG4 0x7 /* undocumented */ 51#define SYSCONFIG4 0x7
51#define SYSCONFIG5 0x8 /* undocumented */ 52#define SYSCONFIG5 0x8
52#define SYSCONFIG6 0x9 /* undocumented */ 53#define SYSCONFIG6 0x9 /* suspected not to exists */
53#define READCHAN 0xA 54#define READCHAN 0xA
54#define STATUSRSSI 0xB 55#define STATUSRSSI 0xB
55#define IDENT 0xC
56 56
57 57
58/* POWERCFG (0x2) */ 58/* POWERCFG (0x2) */
@@ -81,7 +81,7 @@
81 81
82/* SYSCONFIG1 (0x4) */ 82/* SYSCONFIG1 (0x4) */
83#define SYSCONFIG1_DE (0x1 << 11) 83#define SYSCONFIG1_DE (0x1 << 11)
84 #define SYSCONFIG1_SOFTMUTE_EN (0x1 << 9) 84#define SYSCONFIG1_SOFTMUTE_EN (0x1 << 9)
85 85
86/* SYSCONFIG2 (0x5) */ 86/* SYSCONFIG2 (0x5) */
87#define SYSCONFIG2_VOLUME (0xF << 0) 87#define SYSCONFIG2_VOLUME (0xF << 0)
@@ -105,9 +105,9 @@ static uint16_t cache[16] = {
105 [SYSCONFIG1] = 0x0200, /* SYSCONFIG1_SOFTMUTE_EN */ 105 [SYSCONFIG1] = 0x0200, /* SYSCONFIG1_SOFTMUTE_EN */
106 [SYSCONFIG2] = 0x867F, /* INT_MODE (def), SEEKTH=1100b, LNA_PORT_SEL=LNAN, 106 [SYSCONFIG2] = 0x867F, /* INT_MODE (def), SEEKTH=1100b, LNA_PORT_SEL=LNAN,
107 LNA_ICSEL=3.0mA, VOLUME=max */ 107 LNA_ICSEL=3.0mA, VOLUME=max */
108 [SYSCONFIG3] = 0x8000, /* I2S slave mode */ 108 [SYSCONFIG3] = 0x8000, /* RSVD */
109 [SYSCONFIG4] = 0x4712, /* undocumented, affects stereo blend */ 109 [SYSCONFIG4] = 0x4712, /* TH_SOFRBLEND=34dB, 65M_50M MODE=65~76MHz, RSVD, SEEK_TH_OLD=4, SOFTBLEND_EN */
110 [SYSCONFIG5] = 0x5EC6, /* undocumented */ 110 [SYSCONFIG5] = 0x5EC6, /* FREQ_DIRECT=24262kHz (unused) */
111 [SYSCONFIG6] = 0x0000 /* undocumented */ 111 [SYSCONFIG6] = 0x0000 /* undocumented */
112}; 112};
113 113
@@ -190,7 +190,21 @@ static void rda5802_sleep(int snooze)
190 190
191bool rda5802_detect(void) 191bool rda5802_detect(void)
192{ 192{
193 return ((rda5802_read_reg(IDENT) & 0xFF00) == 0x5800); 193 /* The RDA5802 has a weird wrap-around at 0x40. Upon initialisation, it will copy the Chip ID
194 * to register 0xC but since this register is also used for RDS, we cannot rely on its content
195 * until we softreset. But we cannot soft-reset until we confirm the tuner type... So we really
196 * need to register 0, which means reading 0x40 registers.
197 * NOTE: the datasheet says that it wraps around at 0x3A but this is wrong. */
198
199 /* we want to read registers 0x00/0x01, aka 0x40/0x41 because of wrapping, tuner starts reading
200 * at 0xA so we need to read 0x40 - 0xA + 2 registers, each register is two bytes. Thats
201 * (0x40 - 0xA + 2) * 2 = 0x6e bytes */
202 unsigned char buf[0x70];
203 fmradio_i2c_read(I2C_ADR, buf, sizeof(buf));
204 cache[CHIPID] = buf[0x6c] << 8 | buf[0x6d];
205 cache[1] = buf[0x6e] << 8 | buf[0x6f]; /* unknown register, maybe firmware ID or related */
206
207 return ((cache[CHIPID] & 0xFF00) == 0x5800);
194 } 208 }
195 209
196void rda5802_init(void) 210void rda5802_init(void)
diff --git a/firmware/export/ata.h b/firmware/export/ata.h
index 6165eaf633..dfa73eebf5 100644
--- a/firmware/export/ata.h
+++ b/firmware/export/ata.h
@@ -101,7 +101,7 @@ struct ata_smart_values
101 unsigned char reserved_375_385[11]; 101 unsigned char reserved_375_385[11];
102 unsigned char vendor_specific_386_510[125]; 102 unsigned char vendor_specific_386_510[125];
103 unsigned char chksum; 103 unsigned char chksum;
104} __attribute__((packed)); 104} __attribute__((packed)) __attribute__((aligned(2)));
105 105
106/* Raw attribute value print formats */ 106/* Raw attribute value print formats */
107enum ata_attr_raw_format 107enum ata_attr_raw_format
@@ -176,7 +176,6 @@ static inline int ata_disk_isssd(void)
176 0x0401 -> 0xffe == RPM 176 0x0401 -> 0xffe == RPM
177 All others reserved 177 All others reserved
178 178
179 Some CF cards return 0x0100 (ie byteswapped 0x0001) so accept either.
180 However, this is a relatively recent change, and we can't rely on it, 179 However, this is a relatively recent change, and we can't rely on it,
181 especially for the FC1307A CF->SD adapters! 180 especially for the FC1307A CF->SD adapters!
182 181
@@ -199,19 +198,18 @@ static inline int ata_disk_isssd(void)
199 then device is standard flash CF. However this is not foolproof 198 then device is standard flash CF. However this is not foolproof
200 as newer CF cards (and those CF->SD adapters) may report this. 199 as newer CF cards (and those CF->SD adapters) may report this.
201 200
202
203 */ 201 */
204 return ( (identify_info[217] == 0x0001 || identify_info[217] == 0x0100) /* "Solid state" rotational rate */ 202 return ( (identify_info[217] == 0x0001) /* "Solid state" rotational rate */
205 || ((identify_info[168] & 0x0f) >= 0x06) /* Explicit SSD form factors */ 203 || ((identify_info[168] & 0x0f) >= 0x06) /* Explicit SSD form factors */
206 || (identify_info[169] & (1<<0)) /* TRIM supported */ 204 || (identify_info[169] & (1<<0)) /* TRIM supported */
207 || (identify_info[163] > 0) /* CF Advanced timing modes */ 205 || (identify_info[163] > 0) /* CF Advanced timing modes */
208 || ((identify_info[83] & (1<<2)) && /* CFA compliant */ 206 || ((identify_info[83] & (1<<2)) && /* CFA compliant */
209 ((identify_info[160] & (1<<15)) == 0)) /* CF power level 0 */ 207 ((identify_info[160] & (1<<15)) == 0)) /* CF power level 0 */
210 ); 208 );
211} 209}
212 210
213/* Returns 1 if the drive can be powered off safely */ 211/* Returns 1 if the drive supports power management commands */
214static inline int ata_disk_can_poweroff(void) 212static inline int ata_disk_can_sleep(void)
215{ 213{
216 unsigned short *identify_info = ata_get_identify(); 214 unsigned short *identify_info = ata_get_identify();
217 /* Only devices that claim to support PM can be safely powered off. 215 /* Only devices that claim to support PM can be safely powered off.
@@ -219,6 +217,8 @@ static inline int ata_disk_can_poweroff(void)
219 return (identify_info[82] & (1<<3) && identify_info[85] & (1<<3)); 217 return (identify_info[82] & (1<<3) && identify_info[85] & (1<<3));
220} 218}
221 219
220int ata_flush(void);
221
222#ifdef HAVE_ATA_DMA 222#ifdef HAVE_ATA_DMA
223/* Returns current DMA mode */ 223/* Returns current DMA mode */
224int ata_get_dma_mode(void); 224int ata_get_dma_mode(void);
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 37ea9a1dd7..65f05b3e8e 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -635,6 +635,12 @@ Lyre prototype 1 */
635#endif 635#endif
636#endif 636#endif
637 637
638#if defined(__PCTOOL__) || defined(SIMULATOR)
639#ifndef CONFIG_PLATFORM
640#define CONFIG_PLATFORM PLATFORM_HOSTED
641#endif
642#endif
643
638#ifndef CONFIG_PLATFORM 644#ifndef CONFIG_PLATFORM
639#define CONFIG_PLATFORM PLATFORM_NATIVE 645#define CONFIG_PLATFORM PLATFORM_NATIVE
640#endif 646#endif
@@ -893,7 +899,8 @@ Lyre prototype 1 */
893#endif 899#endif
894 900
895/* Bootloaders don't need multivolume awareness */ 901/* Bootloaders don't need multivolume awareness */
896#if defined(BOOTLOADER) && defined(HAVE_MULTIVOLUME) && !(CONFIG_PLATFORM & PLATFORM_HOSTED) 902#if defined(BOOTLOADER) && defined(HAVE_MULTIVOLUME) \
903 && !(CONFIG_PLATFORM & PLATFORM_HOSTED) && !defined(BOOT_REDIR)
897#undef HAVE_MULTIVOLUME 904#undef HAVE_MULTIVOLUME
898#endif 905#endif
899 906
@@ -1252,10 +1259,14 @@ Lyre prototype 1 */
1252# define INCLUDE_TIMEOUT_API 1259# define INCLUDE_TIMEOUT_API
1253#endif 1260#endif
1254 1261
1255#ifndef SIMULATOR 1262#if (!defined(SIMULATOR) && !defined(HAVE_HOSTFS) && !(CONFIG_STORAGE & STORAGE_HOSTFS))
1256#if defined(HAVE_USBSTACK) || (CONFIG_STORAGE & STORAGE_NAND) || (CONFIG_STORAGE & STORAGE_RAMDISK)
1257#define STORAGE_GET_INFO 1263#define STORAGE_GET_INFO
1258#endif 1264#endif
1265
1266#if defined(HAVE_SIGALTSTACK_THREADS)
1267#ifndef _XOPEN_SOURCE
1268#define _XOPEN_SOURCE 600 /* For sigaltstack */
1269#endif
1259#endif 1270#endif
1260 1271
1261#ifdef CPU_MIPS 1272#ifdef CPU_MIPS
diff --git a/firmware/export/config/erosqnative.h b/firmware/export/config/erosqnative.h
index 26073a5f34..adb1b29e01 100644
--- a/firmware/export/config/erosqnative.h
+++ b/firmware/export/config/erosqnative.h
@@ -9,6 +9,19 @@
9#define BOOTFILE "rockbox." BOOTFILE_EXT 9#define BOOTFILE "rockbox." BOOTFILE_EXT
10#define BOOTDIR "/.rockbox" 10#define BOOTDIR "/.rockbox"
11 11
12/* Define EROSQN_VER as an "extradefine" in the configure script -
13 * v1, v2 players: "1"
14 * v3 players: "3"
15 * Only bootloader will be affected.
16 *
17 * This allows us to fix the LCD init issues with v3 players.
18 */
19#ifdef BOOTLOADER
20#ifndef EROSQN_VER
21#error "Must define EROSQN_VER"
22#endif
23#endif
24
12/* CPU defines */ 25/* CPU defines */
13#define CONFIG_CPU X1000 26#define CONFIG_CPU X1000
14#define X1000_EXCLK_FREQ 24000000 27#define X1000_EXCLK_FREQ 24000000
@@ -106,6 +119,9 @@
106#define HAVE_BOOTDATA 119#define HAVE_BOOTDATA
107#define BOOT_REDIR "rockbox_main.aigo_erosqn" 120#define BOOT_REDIR "rockbox_main.aigo_erosqn"
108 121
122/* DeviceData */
123#define HAVE_DEVICEDATA
124
109/* USB support */ 125/* USB support */
110#ifndef SIMULATOR 126#ifndef SIMULATOR
111#define CONFIG_USBOTG USBOTG_DESIGNWARE 127#define CONFIG_USBOTG USBOTG_DESIGNWARE
diff --git a/firmware/export/config/hibylinux.h b/firmware/export/config/hibylinux.h
index ad168c9c01..2da7633389 100644
--- a/firmware/export/config/hibylinux.h
+++ b/firmware/export/config/hibylinux.h
@@ -86,5 +86,7 @@
86#define ROOTDRIVE_DEV "/sys/block/mmcblk0" 86#define ROOTDRIVE_DEV "/sys/block/mmcblk0"
87 87
88/* More common stuff */ 88/* More common stuff */
89#ifndef EROS_Q
89#define BATTERY_DEV_NAME "battery" 90#define BATTERY_DEV_NAME "battery"
91#endif
90#define POWER_DEV_NAME "usb" 92#define POWER_DEV_NAME "usb"
diff --git a/firmware/export/config/ipod6g.h b/firmware/export/config/ipod6g.h
index 50aa5d8e8c..7eb92f86db 100644
--- a/firmware/export/config/ipod6g.h
+++ b/firmware/export/config/ipod6g.h
@@ -12,7 +12,7 @@
12/* define this if you use an ATA controller */ 12/* define this if you use an ATA controller */
13#define CONFIG_STORAGE STORAGE_ATA 13#define CONFIG_STORAGE STORAGE_ATA
14 14
15#define HAVE_ATA_DMA 15#define HAVE_ATA_DMA
16#define ATA_MAX_UDMA 4 16#define ATA_MAX_UDMA 4
17#define ATA_MAX_MWDMA 2 17#define ATA_MAX_MWDMA 2
18 18
@@ -139,7 +139,7 @@
139 139
140/* 6g has a standard battery of 550mAh, except for the thick 6g (2007 160gb) 140/* 6g has a standard battery of 550mAh, except for the thick 6g (2007 160gb)
141 * which has a standard battery of 850mAh. 141 * which has a standard battery of 850mAh.
142 * 142 *
143 * It's possible to buy 3rd party batteries up to 3000mAh. 143 * It's possible to buy 3rd party batteries up to 3000mAh.
144 */ 144 */
145#define BATTERY_CAPACITY_DEFAULT 550 /* default battery capacity */ 145#define BATTERY_CAPACITY_DEFAULT 550 /* default battery capacity */
@@ -189,17 +189,12 @@
189/* Define this if you can read an absolute wheel position */ 189/* Define this if you can read an absolute wheel position */
190#define HAVE_WHEEL_POSITION 190#define HAVE_WHEEL_POSITION
191 191
192#define SECTOR_SIZE 4096
193
194#define HAVE_ATA_SMART 192#define HAVE_ATA_SMART
195 193
196/* define this if the device has larger sectors when accessed via USB */ 194/* define this if the device has larger sectors when accessed via USB */
197/* (only relevant in disk.c, fat.c now always supports large virtual sectors) */ 195#define MAX_LOG_SECTOR_SIZE 4096
198//#define MAX_LOG_SECTOR_SIZE 4096 196/* This is the minimum access size for the device, even if it's larger than the logical sector size */
199 197#define MAX_PHYS_SECTOR_SIZE 4096
200/* define this if the hard drive uses large physical sectors (ATA-7 feature) */
201/* and doesn't handle them in the drive firmware */
202//#define MAX_PHYS_SECTOR_SIZE 4096
203 198
204#define HAVE_HARDWARE_CLICK 199#define HAVE_HARDWARE_CLICK
205 200
diff --git a/firmware/export/config/vibe500.h b/firmware/export/config/vibe500.h
index b6d2e5082a..48140e7a4a 100644
--- a/firmware/export/config/vibe500.h
+++ b/firmware/export/config/vibe500.h
@@ -170,14 +170,6 @@
170/* Define this if you have adjustable CPU frequency */ 170/* Define this if you have adjustable CPU frequency */
171#define HAVE_ADJUSTABLE_CPU_FREQ 171#define HAVE_ADJUSTABLE_CPU_FREQ
172 172
173/* define this if the device has larger sectors when accessed via USB */
174/* (only relevant in disk.c, fat.c now always supports large virtual sectors) */
175/* #define MAX_LOG_SECTOR_SIZE 2048 */
176
177/* define this if the hard drive uses large physical sectors (ATA-7 feature) */
178/* and doesn't handle them in the drive firmware */
179/* #define MAX_PHYS_SECTOR_SIZE 1024 */
180
181#define MI4_FORMAT 173#define MI4_FORMAT
182#define BOOTFILE_EXT "mi4" 174#define BOOTFILE_EXT "mi4"
183#define BOOTFILE "rockbox." BOOTFILE_EXT 175#define BOOTFILE "rockbox." BOOTFILE_EXT
@@ -185,9 +177,6 @@
185 177
186#define ICODE_ATTR_TREMOR_NOT_MDCT 178#define ICODE_ATTR_TREMOR_NOT_MDCT
187 179
188/* DMA is used only for reading on PP502x because although reads are ~8x faster
189 * writes appear to be ~25% slower.
190 */
191#ifndef BOOTLOADER 180#ifndef BOOTLOADER
192#define HAVE_ATA_DMA 181#define HAVE_ATA_DMA
193#endif 182#endif
diff --git a/firmware/export/devicedata.h b/firmware/export/devicedata.h
new file mode 100644
index 0000000000..c19b0ca25d
--- /dev/null
+++ b/firmware/export/devicedata.h
@@ -0,0 +1,94 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2017 by Amaury Pouly
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20#ifndef __RB_DEVICEDATA__
21#define __RB_DEVICEDATA__
22
23#ifndef __ASSEMBLER__
24#include <stdint.h>
25#include "system.h"
26#endif
27
28/* /!\ This file can be included in assembly files /!\ */
29
30/** The device data will be filled by the bootloader with information that might
31 * be relevant for Rockbox. The bootloader will search for the structure using
32 * the magic header within the first DEVICE_DATA_SEARCH_SIZE bytes of the binary.
33 * Typically, this structure should be as close as possible to the entry point */
34
35/* Search size for the data structure after entry point */
36#define DEVICE_DATA_SEARCH_SIZE 1024
37
38#define DEVICE_DATA_MAGIC0 ('r' | 'b' << 8 | 'd' << 16 | 'e' << 24)
39#define DEVICE_DATA_MAGIC1 ('v' | 'i' << 8 | 'c' << 16 | 'e' << 24)
40
41/* maximum size of payload */
42#define DEVICE_DATA_PAYLOAD_SIZE 4
43
44#ifndef __ASSEMBLER__
45/* This is the C structure */
46struct device_data_t
47{
48 union
49 {
50 uint32_t crc; /* crc of payload data (CRC32 with 0xffffffff for initial value) */
51 uint32_t magic[2]; /* DEVICE_DATA_MAGIC0/1 */
52 };
53
54 uint32_t length; /* length of the payload */
55
56 /* add fields here */
57 union
58 {
59 struct
60 {
61#if defined(EROS_QN)
62 uint8_t lcd_version;
63#endif
64 };
65 uint8_t payload[DEVICE_DATA_PAYLOAD_SIZE];
66 };
67} __attribute__((packed));
68
69
70void fill_devicedata(struct device_data_t *data);
71bool write_devicedata(unsigned char* buf, int len);
72#ifndef BOOTLOADER
73extern struct device_data_t device_data;
74
75void verify_device_data(void) INIT_ATTR;
76
77#endif
78
79#else /* __ASSEMBLER__ */
80
81/* This assembler macro implements an empty device data structure with just the magic
82 * string and payload size */
83.macro put_device_data_here
84.global device_data
85device_data:
86 .word DEVICE_DATA_MAGIC0
87 .word DEVICE_DATA_MAGIC1
88 .word DEVICE_DATA_PAYLOAD_SIZE
89 .space BOOT_DATA_PAYLOAD_SIZE, 0xff /* payload, initialised with value 0xff */
90.endm
91
92#endif
93
94#endif /* __RB_DEVICEDATA__ */
diff --git a/firmware/export/disk.h b/firmware/export/disk.h
index a19e011170..4f11438b1b 100644
--- a/firmware/export/disk.h
+++ b/firmware/export/disk.h
@@ -47,10 +47,12 @@ int disk_mount(int drive);
47int disk_unmount_all(void); 47int disk_unmount_all(void);
48int disk_unmount(int drive); 48int disk_unmount(int drive);
49 49
50/* The number of 512-byte sectors in a "logical" sector. Needed for ipod 5.5G */ 50/* Used when the drive's logical sector size is smaller than the sector size used by the partition table and filesystem. Notably needed for ipod 5.5G/6G. */
51#ifdef MAX_LOG_SECTOR_SIZE 51#ifdef MAX_LOG_SECTOR_SIZE
52int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)); 52int disk_get_sector_multiplier(IF_MD_NONVOID(int drive));
53#endif 53#endif
54/* The size of the drive's smallest addressible unit */
55int disk_get_log_sector_size(IF_MD_NONVOID(int drive));
54 56
55bool disk_present(IF_MD_NONVOID(int drive)); 57bool disk_present(IF_MD_NONVOID(int drive));
56 58
diff --git a/firmware/export/storage.h b/firmware/export/storage.h
index e2ae4056be..f97cbf34d5 100644
--- a/firmware/export/storage.h
+++ b/firmware/export/storage.h
@@ -174,7 +174,7 @@ static inline void storage_sleep(void) {};
174 #define storage_disk_is_active() ata_disk_is_active() 174 #define storage_disk_is_active() ata_disk_is_active()
175 #define storage_soft_reset() ata_soft_reset() 175 #define storage_soft_reset() ata_soft_reset()
176 #ifdef HAVE_STORAGE_FLUSH 176 #ifdef HAVE_STORAGE_FLUSH
177 #define storage_flush() (void)0 177 #define storage_flush() ata_flush()
178 #endif 178 #endif
179 #define storage_last_disk_activity() ata_last_disk_activity() 179 #define storage_last_disk_activity() ata_last_disk_activity()
180 #define storage_spinup_time() ata_spinup_time() 180 #define storage_spinup_time() ata_spinup_time()
diff --git a/firmware/export/usb_ch9.h b/firmware/export/usb_ch9.h
index 659bcca101..db311c592e 100644
--- a/firmware/export/usb_ch9.h
+++ b/firmware/export/usb_ch9.h
@@ -292,7 +292,7 @@ struct usb_string_descriptor {
292 uint8_t bDescriptorType; 292 uint8_t bDescriptorType;
293 293
294 uint16_t wString[]; /* UTF-16LE encoded */ 294 uint16_t wString[]; /* UTF-16LE encoded */
295} __attribute__ ((packed)); 295} __attribute__ ((packed)) __attribute__((aligned(2)));
296 296
297/* note that "string" zero is special, it holds language codes that 297/* note that "string" zero is special, it holds language codes that
298 * the device supports, not Unicode characters. 298 * the device supports, not Unicode characters.
diff --git a/firmware/include/string-extra.h b/firmware/include/string-extra.h
index a9b34661a7..9572638e23 100644
--- a/firmware/include/string-extra.h
+++ b/firmware/include/string-extra.h
@@ -30,7 +30,7 @@
30#include "memset16.h" 30#include "memset16.h"
31 31
32#if defined(WIN32) || defined(APPLICATION) \ 32#if defined(WIN32) || defined(APPLICATION) \
33 || defined(__PCTOOL__) 33 || defined(__PCTOOL__) || defined(SIMULATOR)
34#ifndef mempcpy 34#ifndef mempcpy
35#define mempcpy __builtin_mempcpy 35#define mempcpy __builtin_mempcpy
36#endif 36#endif
diff --git a/firmware/kernel/include/queue.h b/firmware/kernel/include/queue.h
index a9c3b5a93a..da03f5312e 100644
--- a/firmware/kernel/include/queue.h
+++ b/firmware/kernel/include/queue.h
@@ -141,6 +141,7 @@ extern void queue_reply(struct event_queue *q, intptr_t retval);
141extern bool queue_in_queue_send(struct event_queue *q); 141extern bool queue_in_queue_send(struct event_queue *q);
142#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ 142#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */
143extern bool queue_empty(const struct event_queue* q); 143extern bool queue_empty(const struct event_queue* q);
144extern bool queue_full(const struct event_queue* q);
144extern bool queue_peek(struct event_queue *q, struct queue_event *ev); 145extern bool queue_peek(struct event_queue *q, struct queue_event *ev);
145 146
146#define QPEEK_FILTER_COUNT_MASK (0xffu) /* 0x00=1 filter, 0xff=256 filters */ 147#define QPEEK_FILTER_COUNT_MASK (0xffu) /* 0x00=1 filter, 0xff=256 filters */
diff --git a/firmware/kernel/queue.c b/firmware/kernel/queue.c
index 5566604c5d..29611e34c7 100644
--- a/firmware/kernel/queue.c
+++ b/firmware/kernel/queue.c
@@ -701,6 +701,12 @@ bool queue_empty(const struct event_queue* q)
701 return ( q->read == q->write ); 701 return ( q->read == q->write );
702} 702}
703 703
704/* Poll queue to see if it is full */
705bool queue_full(const struct event_queue* q)
706{
707 return ((q->write - q->read) >= QUEUE_LENGTH);
708}
709
704void queue_clear(struct event_queue* q) 710void queue_clear(struct event_queue* q)
705{ 711{
706 int oldlevel; 712 int oldlevel;
diff --git a/firmware/libc/include/stdlib.h b/firmware/libc/include/stdlib.h
index e24d6a579f..855663efac 100644
--- a/firmware/libc/include/stdlib.h
+++ b/firmware/libc/include/stdlib.h
@@ -50,7 +50,8 @@ int rand(void);
50#endif 50#endif
51 51
52#define abs(x) ((int)ABS(x)) 52#define abs(x) ((int)ABS(x))
53#define labs(x) ((long)abs(x)) 53#define labs(x) ((long)ABS(x))
54#define llabs(x) ((long long)ABS(x))
54 55
55#ifdef SIMULATOR 56#ifdef SIMULATOR
56void exit(int status); 57void exit(int status);
diff --git a/firmware/rolo.c b/firmware/rolo.c
index f9b0cc9e61..38d350d432 100644
--- a/firmware/rolo.c
+++ b/firmware/rolo.c
@@ -56,6 +56,10 @@
56#include "crc32.h" 56#include "crc32.h"
57#endif 57#endif
58 58
59#if defined(HAVE_DEVICEDATA) && !defined(SIMULATOR)
60#include "devicedata.h"
61#endif
62
59#if CONFIG_CPU == AS3525v2 63#if CONFIG_CPU == AS3525v2
60#include "ascodec.h" 64#include "ascodec.h"
61#endif 65#endif
@@ -250,9 +254,8 @@ int rolo_load(const char* filename)
250 254
251 err = LOAD_FIRMWARE(filebuf, filename, filebuf_size); 255 err = LOAD_FIRMWARE(filebuf, filename, filebuf_size);
252#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) 256#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR)
253 /* write the bootdata as if rolo were the bootloader 257 // Write bootdata as long as the existing bootdata is valid
254 * FIXME: this won't work for root redirect... */ 258 if (boot_data_valid)
255 if (!strcmp(filename, BOOTDIR "/" BOOTFILE) && boot_data_valid)
256 { 259 {
257 int volume = 0; 260 int volume = 0;
258 261
@@ -275,6 +278,10 @@ int rolo_load(const char* filename)
275 } 278 }
276#endif 279#endif
277 280
281#if defined(HAVE_DEVICEDATA)
282 write_devicedata(filebuf, filebuf_size);
283#endif
284
278 if (err <= 0) 285 if (err <= 0)
279 { 286 {
280 rolo_error(loader_strerror(err)); 287 rolo_error(loader_strerror(err));
diff --git a/firmware/scroll_engine.c b/firmware/scroll_engine.c
index c32f4632e2..74c08c1da5 100644
--- a/firmware/scroll_engine.c
+++ b/firmware/scroll_engine.c
@@ -32,6 +32,10 @@
32#include "usb.h" 32#include "usb.h"
33#include "lcd.h" 33#include "lcd.h"
34#include "font.h" 34#include "font.h"
35#if !defined(BOOTLOADER)
36#include "misc.h"
37#include "settings.h"
38#endif
35#ifdef HAVE_REMOTE_LCD 39#ifdef HAVE_REMOTE_LCD
36#include "lcd-remote.h" 40#include "lcd-remote.h"
37#endif 41#endif
diff --git a/firmware/storage.c b/firmware/storage.c
index da3e06146d..2d4490369e 100644
--- a/firmware/storage.c
+++ b/firmware/storage.c
@@ -555,7 +555,7 @@ int storage_flush(void)
555 int rc=0; 555 int rc=0;
556 556
557#if (CONFIG_STORAGE & STORAGE_ATA) 557#if (CONFIG_STORAGE & STORAGE_ATA)
558 //if ((rc=ata_flush())) return rc; 558 if ((rc=ata_flush())) return rc;
559#endif 559#endif
560 560
561#if (CONFIG_STORAGE & STORAGE_MMC) 561#if (CONFIG_STORAGE & STORAGE_MMC)
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c
index 0450c8b410..26a228cddf 100644
--- a/firmware/target/arm/as3525/system-as3525.c
+++ b/firmware/target/arm/as3525/system-as3525.c
@@ -92,7 +92,7 @@ void INT_GPIOA(void);
92default_interrupt(INT_GPIOB); 92default_interrupt(INT_GPIOB);
93default_interrupt(INT_GPIOC); 93default_interrupt(INT_GPIOC);
94 94
95static const char const irqname[][9] = 95static const char irqname[][9] =
96{ 96{
97 "WATCHDOG", "TIMER1", "TIMER2", "USB", "DMAC", "NAND", 97 "WATCHDOG", "TIMER1", "TIMER2", "USB", "DMAC", "NAND",
98 "IDE", "MCI0", "MCI1", "AUDIO", "SSP", "I2C_MS", 98 "IDE", "MCI0", "MCI1", "AUDIO", "SSP", "I2C_MS",
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.c b/firmware/target/arm/imx233/clkctrl-imx233.c
index 59c23c1a76..1a8f523d5a 100644
--- a/firmware/target/arm/imx233/clkctrl-imx233.c
+++ b/firmware/target/arm/imx233/clkctrl-imx233.c
@@ -87,7 +87,9 @@ void imx233_clkctrl_set_div(enum imx233_clock_t clk, int div)
87 case CLK_EMI: BF_WR(CLKCTRL_EMI, DIV(div)); break; 87 case CLK_EMI: BF_WR(CLKCTRL_EMI, DIV(div)); break;
88#endif 88#endif
89 case CLK_SSP: BF_WR(CLKCTRL_SSP, DIV(div)); break; 89 case CLK_SSP: BF_WR(CLKCTRL_SSP, DIV(div)); break;
90 case CLK_HBUS: BF_WR(CLKCTRL_HBUS, DIV(div)); break; 90 case CLK_HBUS:
91 /* make sure to switch to integer divide mode simulteanously */
92 BF_WR(CLKCTRL_HBUS, DIV_FRAC_EN(0), DIV(div)); break;
91 case CLK_XBUS: BF_WR(CLKCTRL_XBUS, DIV(div)); break; 93 case CLK_XBUS: BF_WR(CLKCTRL_XBUS, DIV(div)); break;
92 default: return; 94 default: return;
93 } 95 }
@@ -107,7 +109,12 @@ int imx233_clkctrl_get_div(enum imx233_clock_t clk)
107 case CLK_EMI: return BF_RD(CLKCTRL_EMI, DIV); 109 case CLK_EMI: return BF_RD(CLKCTRL_EMI, DIV);
108#endif 110#endif
109 case CLK_SSP: return BF_RD(CLKCTRL_SSP, DIV); 111 case CLK_SSP: return BF_RD(CLKCTRL_SSP, DIV);
110 case CLK_HBUS: return BF_RD(CLKCTRL_HBUS, DIV); 112 case CLK_HBUS:
113 /* since fractional and integer divider share the same field, clain it is disabled in frac mode */
114 if(BF_RD(CLKCTRL_HBUS, DIV_FRAC_EN))
115 return 0;
116 else
117 return BF_RD(CLKCTRL_HBUS, DIV);
111 case CLK_XBUS: return BF_RD(CLKCTRL_XBUS, DIV); 118 case CLK_XBUS: return BF_RD(CLKCTRL_XBUS, DIV);
112 default: return 0; 119 default: return 0;
113 } 120 }
@@ -130,6 +137,14 @@ void imx233_clkctrl_set_frac_div(enum imx233_clock_t clk, int fracdiv)
130 handle_frac(IO) 137 handle_frac(IO)
131 handle_frac(CPU) 138 handle_frac(CPU)
132 handle_frac(EMI) 139 handle_frac(EMI)
140 case CLK_HBUS:
141 if(fracdiv == 0)
142 panicf("Don't set hbus fracdiv to 0!");
143 /* value 0 is forbidden because we can't simply disabble the divider, it's always
144 * active but either in integer or fractional mode
145 * make sure we write both the value and frac_en bit at the same time */
146 BF_WR(CLKCTRL_HBUS, DIV_FRAC_EN(1), DIV(fracdiv));
147 break;
133 default: break; 148 default: break;
134 } 149 }
135#undef handle_frac 150#undef handle_frac
@@ -151,6 +166,11 @@ int imx233_clkctrl_get_frac_div(enum imx233_clock_t clk)
151 handle_frac(IO) 166 handle_frac(IO)
152 handle_frac(CPU) 167 handle_frac(CPU)
153 handle_frac(EMI) 168 handle_frac(EMI)
169 case CLK_HBUS:
170 if(BF_RD(CLKCTRL_HBUS, DIV_FRAC_EN))
171 return BF_RD(CLKCTRL_HBUS, DIV);
172 else
173 return 0;
154 default: return 0; 174 default: return 0;
155 } 175 }
156#undef handle_frac 176#undef handle_frac
@@ -303,8 +323,12 @@ unsigned imx233_clkctrl_get_freq(enum imx233_clock_t clk)
303 /* Derived from clk_p via integer/fractional div */ 323 /* Derived from clk_p via integer/fractional div */
304 unsigned ref = imx233_clkctrl_get_freq(CLK_CPU); 324 unsigned ref = imx233_clkctrl_get_freq(CLK_CPU);
305#if IMX233_SUBTARGET >= 3700 325#if IMX233_SUBTARGET >= 3700
326 /* if divider is in fractional mode, integer divider does not take effect (in fact it's
327 * the same divider but in a different mode ). Also the fractiona value is encoded as
328 * a fraction, not a divider */
306 if(imx233_clkctrl_get_frac_div(CLK_HBUS) != 0) 329 if(imx233_clkctrl_get_frac_div(CLK_HBUS) != 0)
307 ref = (ref * imx233_clkctrl_get_frac_div(CLK_HBUS)) / 32; 330 ref = (ref * imx233_clkctrl_get_frac_div(CLK_HBUS)) / 32;
331 else
308#endif 332#endif
309 if(imx233_clkctrl_get_div(CLK_HBUS) != 0) 333 if(imx233_clkctrl_get_div(CLK_HBUS) != 0)
310 ref /= imx233_clkctrl_get_div(CLK_HBUS); 334 ref /= imx233_clkctrl_get_div(CLK_HBUS);
diff --git a/firmware/target/arm/imx233/clkctrl-imx233.h b/firmware/target/arm/imx233/clkctrl-imx233.h
index f12d181c50..d150912cfe 100644
--- a/firmware/target/arm/imx233/clkctrl-imx233.h
+++ b/firmware/target/arm/imx233/clkctrl-imx233.h
@@ -68,7 +68,7 @@ int imx233_clkctrl_get_div(enum imx233_clock_t clk);
68#if IMX233_SUBTARGET >= 3700 68#if IMX233_SUBTARGET >= 3700
69/* call with fracdiv=0 to disable it */ 69/* call with fracdiv=0 to disable it */
70void imx233_clkctrl_set_frac_div(enum imx233_clock_t clk, int fracdiv); 70void imx233_clkctrl_set_frac_div(enum imx233_clock_t clk, int fracdiv);
71/* 0 means fractional dividor disable */ 71/* 0 means fractional dividor disabled */
72int imx233_clkctrl_get_frac_div(enum imx233_clock_t clk); 72int imx233_clkctrl_get_frac_div(enum imx233_clock_t clk);
73void imx233_clkctrl_set_bypass(enum imx233_clock_t clk, bool bypass); 73void imx233_clkctrl_set_bypass(enum imx233_clock_t clk, bool bypass);
74bool imx233_clkctrl_get_bypass(enum imx233_clock_t clk); 74bool imx233_clkctrl_get_bypass(enum imx233_clock_t clk);
diff --git a/firmware/target/arm/ipod/button-clickwheel.c b/firmware/target/arm/ipod/button-clickwheel.c
index 8f238936e7..9308b7664e 100644
--- a/firmware/target/arm/ipod/button-clickwheel.c
+++ b/firmware/target/arm/ipod/button-clickwheel.c
@@ -327,7 +327,13 @@ void ipod_4g_button_int(void)
327void button_init_device(void) 327void button_init_device(void)
328{ 328{
329 opto_i2c_init(); 329 opto_i2c_init();
330 330
331 /* fixes first button press being ignored */
332#if defined(IPOD_4G) || defined(IPOD_COLOR)
333 outl(inl(0x7000c100) & ~0x60000000, 0x7000c100);
334 outl(inl(0x7000c104) | 0x04000000, 0x7000c104);
335 outl(inl(0x7000c100) | 0x60000000, 0x7000c100);
336#endif
331 /* hold button - enable as input */ 337 /* hold button - enable as input */
332 GPIOA_ENABLE |= 0x20; 338 GPIOA_ENABLE |= 0x20;
333 GPIOA_OUTPUT_EN &= ~0x20; 339 GPIOA_OUTPUT_EN &= ~0x20;
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
index 0d831a7167..7071d411b5 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
@@ -186,7 +186,6 @@ struct ftl_cxt_type
186 There is one of these per bank. */ 186 There is one of these per bank. */
187struct ftl_vfl_cxt_type 187struct ftl_vfl_cxt_type
188{ 188{
189
190 /* Cross-bank update sequence number, incremented on every VFL 189 /* Cross-bank update sequence number, incremented on every VFL
191 context commit on any bank. */ 190 context commit on any bank. */
192 uint32_t usn; 191 uint32_t usn;
@@ -525,18 +524,24 @@ static uint32_t ftl_vfl_verify_checksum(uint32_t bank)
525 return 1; 524 return 1;
526} 525}
527 526
528
529#ifndef FTL_READONLY 527#ifndef FTL_READONLY
528
529#if __GNUC__ >= 9
530#pragma GCC diagnostic push
531#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
532#endif
533
530/* Updates the checksums of the VFL context of the specified bank */ 534/* Updates the checksums of the VFL context of the specified bank */
531static void ftl_vfl_update_checksum(uint32_t bank) 535static void ftl_vfl_update_checksum(uint32_t bank)
532{ 536{
533 ftl_vfl_calculate_checksum(bank, &ftl_vfl_cxt[bank].checksum1, 537 ftl_vfl_calculate_checksum(bank, &ftl_vfl_cxt[bank].checksum1,
534 &ftl_vfl_cxt[bank].checksum2); 538 &ftl_vfl_cxt[bank].checksum2);
535} 539}
536#endif
537 540
541#if __GNUC__ >= 9
542#pragma GCC diagnostic pop
543#endif
538 544
539#ifndef FTL_READONLY
540/* Writes 8 copies of the VFL context of the specified bank to flash, 545/* Writes 8 copies of the VFL context of the specified bank to flash,
541 and succeeds if at least 4 can be read back properly. */ 546 and succeeds if at least 4 can be read back properly. */
542static uint32_t ftl_vfl_store_cxt(uint32_t bank) 547static uint32_t ftl_vfl_store_cxt(uint32_t bank)
@@ -2107,7 +2112,7 @@ uint32_t ftl_sync(void)
2107 if (ftl_cxt.clean_flag == 1) return 0; 2112 if (ftl_cxt.clean_flag == 1) return 0;
2108 2113
2109 mutex_lock(&ftl_mtx); 2114 mutex_lock(&ftl_mtx);
2110 2115
2111#ifdef FTL_TRACE 2116#ifdef FTL_TRACE
2112 DEBUGF("FTL: Syncing\n"); 2117 DEBUGF("FTL: Syncing\n");
2113#endif 2118#endif
diff --git a/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c b/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c
index 9629b3e30f..8cc5b44aca 100644
--- a/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/storage_ata-6g.c
@@ -29,6 +29,9 @@
29#include "mmcdefs-target.h" 29#include "mmcdefs-target.h"
30#include "s5l8702.h" 30#include "s5l8702.h"
31#include "led.h" 31#include "led.h"
32#include "debug.h"
33#include "panic.h"
34#include "fs_defines.h"
32 35
33#ifndef ATA_RETRIES 36#ifndef ATA_RETRIES
34#define ATA_RETRIES 3 37#define ATA_RETRIES 3
@@ -60,7 +63,7 @@
60 63
61/** static, private data **/ 64/** static, private data **/
62static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; 65static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR;
63static uint16_t ata_identify_data[ATA_IDENTIFY_WORDS] STORAGE_ALIGN_ATTR; 66static uint16_t identify_info[ATA_IDENTIFY_WORDS] STORAGE_ALIGN_ATTR;
64static bool ceata; 67static bool ceata;
65static bool ata_lba48; 68static bool ata_lba48;
66static bool ata_dma; 69static bool ata_dma;
@@ -69,18 +72,18 @@ static struct mutex ata_mutex;
69static struct semaphore ata_wakeup; 72static struct semaphore ata_wakeup;
70static uint32_t ata_dma_flags; 73static uint32_t ata_dma_flags;
71static long ata_last_activity_value = -1; 74static long ata_last_activity_value = -1;
72static long ata_sleep_timeout = 20 * HZ; 75static long ata_sleep_timeout = 7 * HZ;
73static bool ata_powered; 76static bool ata_powered;
74static const int ata_retries = ATA_RETRIES; 77static bool canflush = true;
75static const bool ata_error_srst = true;
76static struct semaphore mmc_wakeup; 78static struct semaphore mmc_wakeup;
77static struct semaphore mmc_comp_wakeup; 79static struct semaphore mmc_comp_wakeup;
78static int spinup_time = 0; 80static int spinup_time = 0;
79static int dma_mode = 0; 81static int dma_mode = 0;
80static char aligned_buffer[SECTOR_SIZE] STORAGE_ALIGN_ATTR;
81 82
82static int ata_reset(void); 83static const int ata_retries = ATA_RETRIES;
84static const bool ata_error_srst = true;
83 85
86static int ata_reset(void);
84 87
85static uint16_t ata_read_cbr(uint32_t volatile* reg) 88static uint16_t ata_read_cbr(uint32_t volatile* reg)
86{ 89{
@@ -102,8 +105,10 @@ static int ata_wait_for_not_bsy(long timeout)
102 while (true) 105 while (true)
103 { 106 {
104 uint8_t csd = ata_read_cbr(&ATA_PIO_CSD); 107 uint8_t csd = ata_read_cbr(&ATA_PIO_CSD);
105 if (!(csd & BIT(7))) return 0; 108 if (!(csd & BIT(7)))
106 if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(0); 109 return 0;
110 if (TIMEOUT_EXPIRED(startusec, timeout))
111 RET_ERR(0);
107 yield(); 112 yield();
108 } 113 }
109} 114}
@@ -115,8 +120,10 @@ static int ata_wait_for_rdy(long timeout)
115 while (true) 120 while (true)
116 { 121 {
117 uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); 122 uint8_t dad = ata_read_cbr(&ATA_PIO_DAD);
118 if (dad & BIT(6)) return 0; 123 if (dad & BIT(6))
119 if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(1); 124 return 0;
125 if (TIMEOUT_EXPIRED(startusec, timeout))
126 RET_ERR(1);
120 yield(); 127 yield();
121 } 128 }
122} 129}
@@ -128,9 +135,12 @@ static int ata_wait_for_start_of_transfer(long timeout)
128 while (true) 135 while (true)
129 { 136 {
130 uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); 137 uint8_t dad = ata_read_cbr(&ATA_PIO_DAD);
131 if (dad & BIT(0)) RET_ERR(1); 138 if (dad & BIT(0))
132 if ((dad & (BIT(7) | BIT(3))) == BIT(3)) return 0; 139 RET_ERR(1);
133 if (TIMEOUT_EXPIRED(startusec, timeout)) RET_ERR(2); 140 if ((dad & (BIT(7) | BIT(3))) == BIT(3))
141 return 0;
142 if (TIMEOUT_EXPIRED(startusec, timeout))
143 RET_ERR(2);
134 yield(); 144 yield();
135 } 145 }
136} 146}
@@ -139,8 +149,10 @@ static int ata_wait_for_end_of_transfer(long timeout)
139{ 149{
140 PASS_RC(ata_wait_for_not_bsy(timeout), 2, 0); 150 PASS_RC(ata_wait_for_not_bsy(timeout), 2, 0);
141 uint8_t dad = ata_read_cbr(&ATA_PIO_DAD); 151 uint8_t dad = ata_read_cbr(&ATA_PIO_DAD);
142 if (dad & BIT(0)) RET_ERR(1); 152 if (dad & BIT(0))
143 if ((dad & (BIT(3) | BITRANGE(5, 7))) == BIT(6)) return 0; 153 RET_ERR(1);
154 if ((dad & (BIT(3) | BITRANGE(5, 7))) == BIT(6))
155 return 0;
144 RET_ERR(2); 156 RET_ERR(2);
145} 157}
146 158
@@ -148,13 +160,17 @@ static int mmc_dsta_check_command_success(bool disable_crc)
148{ 160{
149 int rc = 0; 161 int rc = 0;
150 uint32_t dsta = SDCI_DSTA; 162 uint32_t dsta = SDCI_DSTA;
151 if (dsta & SDCI_DSTA_RESTOUTE) rc |= 1; 163 if (dsta & SDCI_DSTA_RESTOUTE)
152 if (dsta & SDCI_DSTA_RESENDE) rc |= 2; 164 rc |= 1;
153 if (dsta & SDCI_DSTA_RESINDE) rc |= 4; 165 if (dsta & SDCI_DSTA_RESENDE)
166 rc |= 2;
167 if (dsta & SDCI_DSTA_RESINDE)
168 rc |= 4;
154 if (!disable_crc) 169 if (!disable_crc)
155 if (dsta & SDCI_DSTA_RESCRCE) 170 if (dsta & SDCI_DSTA_RESCRCE)
156 rc |= 8; 171 rc |= 8;
157 if (rc) RET_ERR(rc); 172 if (rc)
173 RET_ERR(rc);
158 return 0; 174 return 0;
159} 175}
160 176
@@ -163,7 +179,8 @@ static bool mmc_send_command(uint32_t cmd, uint32_t arg, uint32_t* result, int t
163 long starttime = USEC_TIMER; 179 long starttime = USEC_TIMER;
164 while ((SDCI_STATE & SDCI_STATE_CMD_STATE_MASK) != SDCI_STATE_CMD_STATE_CMD_IDLE) 180 while ((SDCI_STATE & SDCI_STATE_CMD_STATE_MASK) != SDCI_STATE_CMD_STATE_CMD_IDLE)
165 { 181 {
166 if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(0); 182 if (TIMEOUT_EXPIRED(starttime, timeout))
183 RET_ERR(0);
167 yield(); 184 yield();
168 } 185 }
169 SDCI_STAC = SDCI_STAC_CLR_CMDEND | SDCI_STAC_CLR_BIT_3 186 SDCI_STAC = SDCI_STAC_CLR_CMDEND | SDCI_STAC_CLR_BIT_3
@@ -178,32 +195,38 @@ static bool mmc_send_command(uint32_t cmd, uint32_t arg, uint32_t* result, int t
178 | SDCI_STAC_CLR_RD_DATENDE6 | SDCI_STAC_CLR_RD_DATENDE7; 195 | SDCI_STAC_CLR_RD_DATENDE6 | SDCI_STAC_CLR_RD_DATENDE7;
179 SDCI_ARGU = arg; 196 SDCI_ARGU = arg;
180 SDCI_CMD = cmd; 197 SDCI_CMD = cmd;
181 if (!(SDCI_DSTA & SDCI_DSTA_CMDRDY)) RET_ERR(1); 198 if (!(SDCI_DSTA & SDCI_DSTA_CMDRDY))
199 RET_ERR(1);
182 SDCI_CMD = cmd | SDCI_CMD_CMDSTR; 200 SDCI_CMD = cmd | SDCI_CMD_CMDSTR;
183 long sleepbase = USEC_TIMER; 201 long sleepbase = USEC_TIMER;
184 while (TIMEOUT_EXPIRED(sleepbase, 1000)) yield(); 202 while (TIMEOUT_EXPIRED(sleepbase, 1000))
203 yield();
185 while (!(SDCI_DSTA & SDCI_DSTA_CMDEND)) 204 while (!(SDCI_DSTA & SDCI_DSTA_CMDEND))
186 { 205 {
187 if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(2); 206 if (TIMEOUT_EXPIRED(starttime, timeout))
207 RET_ERR(2);
188 yield(); 208 yield();
189 } 209 }
190 if ((cmd & SDCI_CMD_RES_TYPE_MASK) != SDCI_CMD_RES_TYPE_NONE) 210 if ((cmd & SDCI_CMD_RES_TYPE_MASK) != SDCI_CMD_RES_TYPE_NONE)
191 { 211 {
192 while (!(SDCI_DSTA & SDCI_DSTA_RESEND)) 212 while (!(SDCI_DSTA & SDCI_DSTA_RESEND))
193 { 213 {
194 if (TIMEOUT_EXPIRED(starttime, timeout)) RET_ERR(3); 214 if (TIMEOUT_EXPIRED(starttime, timeout))
215 RET_ERR(3);
195 yield(); 216 yield();
196 } 217 }
197 if (cmd & SDCI_CMD_RES_BUSY) 218 if (cmd & SDCI_CMD_RES_BUSY)
198 while (SDCI_DSTA & SDCI_DSTA_DAT_BUSY) 219 while (SDCI_DSTA & SDCI_DSTA_DAT_BUSY)
199 { 220 {
200 if (TIMEOUT_EXPIRED(starttime, CEATA_DAT_NONBUSY_TIMEOUT)) RET_ERR(4); 221 if (TIMEOUT_EXPIRED(starttime, CEATA_DAT_NONBUSY_TIMEOUT))
222 RET_ERR(4);
201 yield(); 223 yield();
202 } 224 }
203 } 225 }
204 bool nocrc = (cmd & SDCI_CMD_RES_SIZE_MASK) == SDCI_CMD_RES_SIZE_136; 226 bool nocrc = (cmd & SDCI_CMD_RES_SIZE_MASK) == SDCI_CMD_RES_SIZE_136;
205 PASS_RC(mmc_dsta_check_command_success(nocrc), 3, 5); 227 PASS_RC(mmc_dsta_check_command_success(nocrc), 3, 5);
206 if (result) *result = SDCI_RESP0; 228 if (result)
229 *result = SDCI_RESP0;
207 return 0; 230 return 0;
208} 231}
209 232
@@ -226,7 +249,8 @@ static int mmc_init(void)
226 uint32_t result; 249 uint32_t result;
227 do 250 do
228 { 251 {
229 if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT)) RET_ERR(1); 252 if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT))
253 RET_ERR(1);
230 sleep(HZ / 100); 254 sleep(HZ / 100);
231 PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SEND_OP_COND) 255 PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SEND_OP_COND)
232 | SDCI_CMD_CMD_TYPE_BCR | SDCI_CMD_RES_TYPE_R3 256 | SDCI_CMD_CMD_TYPE_BCR | SDCI_CMD_RES_TYPE_R3
@@ -251,7 +275,8 @@ static int mmc_init(void)
251 MMC_CMD_SELECT_CARD_RCA(CEATA_MMC_RCA), 275 MMC_CMD_SELECT_CARD_RCA(CEATA_MMC_RCA),
252 NULL, CEATA_COMMAND_TIMEOUT), 3, 5); 276 NULL, CEATA_COMMAND_TIMEOUT), 3, 5);
253 PASS_RC(mmc_get_card_status(&result), 3, 6); 277 PASS_RC(mmc_get_card_status(&result), 3, 6);
254 if ((result & MMC_STATUS_CURRENT_STATE_MASK) != MMC_STATUS_CURRENT_STATE_TRAN) RET_ERR(7); 278 if ((result & MMC_STATUS_CURRENT_STATE_MASK) != MMC_STATUS_CURRENT_STATE_TRAN)
279 RET_ERR(7);
255 return 0; 280 return 0;
256} 281}
257 282
@@ -285,7 +310,8 @@ static int ceata_soft_reset(void)
285 do 310 do
286 { 311 {
287 PASS_RC(mmc_fastio_read(0xf, &status), 2, 2); 312 PASS_RC(mmc_fastio_read(0xf, &status), 2, 2);
288 if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT)) RET_ERR(3); 313 if (TIMEOUT_EXPIRED(startusec, CEATA_POWERUP_TIMEOUT))
314 RET_ERR(3);
289 sleep(HZ / 100); 315 sleep(HZ / 100);
290 } 316 }
291 while (status & 0x80); 317 while (status & 0x80);
@@ -298,16 +324,21 @@ static int mmc_dsta_check_data_success(void)
298 uint32_t dsta = SDCI_DSTA; 324 uint32_t dsta = SDCI_DSTA;
299 if (dsta & (SDCI_DSTA_WR_DATCRCE | SDCI_DSTA_RD_DATCRCE)) 325 if (dsta & (SDCI_DSTA_WR_DATCRCE | SDCI_DSTA_RD_DATCRCE))
300 { 326 {
301 if (dsta & SDCI_DSTA_WR_DATCRCE) rc |= 1; 327 if (dsta & SDCI_DSTA_WR_DATCRCE)
302 if (dsta & SDCI_DSTA_RD_DATCRCE) rc |= 2; 328 rc |= 1;
303 if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_TXERR) rc |= 4; 329 if (dsta & SDCI_DSTA_RD_DATCRCE)
304 else if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_CARDERR) rc |= 8; 330 rc |= 2;
331 if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_TXERR)
332 rc |= 4;
333 else if ((dsta & SDCI_DSTA_WR_CRC_STATUS_MASK) == SDCI_DSTA_WR_CRC_STATUS_CARDERR)
334 rc |= 8;
305 } 335 }
306 if (dsta & (SDCI_DSTA_RD_DATENDE0 | SDCI_DSTA_RD_DATENDE1 | SDCI_DSTA_RD_DATENDE2 336 if (dsta & (SDCI_DSTA_RD_DATENDE0 | SDCI_DSTA_RD_DATENDE1 | SDCI_DSTA_RD_DATENDE2
307 | SDCI_DSTA_RD_DATENDE3 | SDCI_DSTA_RD_DATENDE4 | SDCI_DSTA_RD_DATENDE5 337 | SDCI_DSTA_RD_DATENDE3 | SDCI_DSTA_RD_DATENDE4 | SDCI_DSTA_RD_DATENDE5
308 | SDCI_DSTA_RD_DATENDE6 | SDCI_DSTA_RD_DATENDE7)) 338 | SDCI_DSTA_RD_DATENDE6 | SDCI_DSTA_RD_DATENDE7))
309 rc |= 16; 339 rc |= 16;
310 if (rc) RET_ERR(rc); 340 if (rc)
341 RET_ERR(rc);
311 return 0; 342 return 0;
312} 343}
313 344
@@ -320,7 +351,8 @@ static void mmc_discard_irq(void)
320 351
321static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size) 352static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size)
322{ 353{
323 if (size > 0x10) RET_ERR(0); 354 if (size > 0x10)
355 RET_ERR(0);
324 mmc_discard_irq(); 356 mmc_discard_irq();
325 SDCI_DMASIZE = size; 357 SDCI_DMASIZE = size;
326 SDCI_DMACOUNT = 1; 358 SDCI_DMACOUNT = 1;
@@ -334,8 +366,8 @@ static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size
334 | MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS(addr & 0xfc) 366 | MMC_CMD_CEATA_RW_MULTIPLE_REG_ADDRESS(addr & 0xfc)
335 | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc), 367 | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc),
336 NULL, CEATA_COMMAND_TIMEOUT), 2, 1); 368 NULL, CEATA_COMMAND_TIMEOUT), 2, 1);
337 if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) 369 if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) == OBJ_WAIT_TIMEDOUT)
338 == OBJ_WAIT_TIMEDOUT) RET_ERR(2); 370 RET_ERR(2);
339 PASS_RC(mmc_dsta_check_data_success(), 2, 3); 371 PASS_RC(mmc_dsta_check_data_success(), 2, 3);
340 return 0; 372 return 0;
341} 373}
@@ -343,7 +375,8 @@ static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size
343static int ceata_write_multiple_register(uint32_t addr, void* dest, uint32_t size) 375static int ceata_write_multiple_register(uint32_t addr, void* dest, uint32_t size)
344{ 376{
345 uint32_t i; 377 uint32_t i;
346 if (size > 0x10) RET_ERR(0); 378 if (size > 0x10)
379 RET_ERR(0);
347 mmc_discard_irq(); 380 mmc_discard_irq();
348 SDCI_DMASIZE = size; 381 SDCI_DMASIZE = size;
349 SDCI_DMACOUNT = 0; 382 SDCI_DMACOUNT = 0;
@@ -357,13 +390,15 @@ static int ceata_write_multiple_register(uint32_t addr, void* dest, uint32_t siz
357 | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc), 390 | MMC_CMD_CEATA_RW_MULTIPLE_REG_COUNT(size & 0xfc),
358 NULL, CEATA_COMMAND_TIMEOUT), 3, 1); 391 NULL, CEATA_COMMAND_TIMEOUT), 3, 1);
359 SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; 392 SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX;
360 for (i = 0; i < size / 4; i++) SDCI_DATA = ((uint32_t*)dest)[i]; 393 for (i = 0; i < size / 4; i++)
394 SDCI_DATA = ((uint32_t*)dest)[i];
361 long startusec = USEC_TIMER; 395 long startusec = USEC_TIMER;
362 if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) 396 if (semaphore_wait(&mmc_wakeup, CEATA_COMMAND_TIMEOUT * HZ / 1000000) == OBJ_WAIT_TIMEDOUT)
363 == OBJ_WAIT_TIMEDOUT) RET_ERR(2); 397 RET_ERR(2);
364 while ((SDCI_STATE & SDCI_STATE_DAT_STATE_MASK) != SDCI_STATE_DAT_STATE_IDLE) 398 while ((SDCI_STATE & SDCI_STATE_DAT_STATE_MASK) != SDCI_STATE_DAT_STATE_IDLE)
365 { 399 {
366 if (TIMEOUT_EXPIRED(startusec, CEATA_COMMAND_TIMEOUT)) RET_ERR(3); 400 if (TIMEOUT_EXPIRED(startusec, CEATA_COMMAND_TIMEOUT))
401 RET_ERR(3);
367 yield(); 402 yield();
368 } 403 }
369 PASS_RC(mmc_dsta_check_data_success(), 3, 4); 404 PASS_RC(mmc_dsta_check_data_success(), 3, 4);
@@ -380,13 +415,17 @@ static int ceata_init(int buswidth)
380 | MMC_CMD_SWITCH_INDEX(MMC_CMD_SWITCH_FIELD_HS_TIMING) 415 | MMC_CMD_SWITCH_INDEX(MMC_CMD_SWITCH_FIELD_HS_TIMING)
381 | MMC_CMD_SWITCH_VALUE(MMC_CMD_SWITCH_FIELD_HS_TIMING_HIGH_SPEED), 416 | MMC_CMD_SWITCH_VALUE(MMC_CMD_SWITCH_FIELD_HS_TIMING_HIGH_SPEED),
382 &result, CEATA_COMMAND_TIMEOUT), 3, 0); 417 &result, CEATA_COMMAND_TIMEOUT), 3, 0);
383 if (result & MMC_STATUS_SWITCH_ERROR) RET_ERR(1); 418 if (result & MMC_STATUS_SWITCH_ERROR)
419 RET_ERR(1);
384 if (buswidth > 1) 420 if (buswidth > 1)
385 { 421 {
386 int setting; 422 int setting;
387 if (buswidth == 4) setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_4BIT; 423 if (buswidth == 4)
388 else if (buswidth == 8) setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_8BIT; 424 setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_4BIT;
389 else setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_1BIT; 425 else if (buswidth == 8)
426 setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_8BIT;
427 else
428 setting = MMC_CMD_SWITCH_FIELD_BUS_WIDTH_1BIT;
390 PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SWITCH) | SDCI_CMD_RES_BUSY 429 PASS_RC(mmc_send_command(SDCI_CMD_CMD_NUM(MMC_CMD_SWITCH) | SDCI_CMD_RES_BUSY
391 | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R1 430 | SDCI_CMD_CMD_TYPE_AC | SDCI_CMD_RES_TYPE_R1
392 | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, 431 | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR,
@@ -394,7 +433,8 @@ static int ceata_init(int buswidth)
394 | MMC_CMD_SWITCH_INDEX(MMC_CMD_SWITCH_FIELD_BUS_WIDTH) 433 | MMC_CMD_SWITCH_INDEX(MMC_CMD_SWITCH_FIELD_BUS_WIDTH)
395 | MMC_CMD_SWITCH_VALUE(setting), 434 | MMC_CMD_SWITCH_VALUE(setting),
396 &result, CEATA_COMMAND_TIMEOUT), 3, 2); 435 &result, CEATA_COMMAND_TIMEOUT), 3, 2);
397 if (result & MMC_STATUS_SWITCH_ERROR) RET_ERR(3); 436 if (result & MMC_STATUS_SWITCH_ERROR)
437 RET_ERR(3);
398 if (buswidth == 4) 438 if (buswidth == 4)
399 SDCI_CTRL = (SDCI_CTRL & ~SDCI_CTRL_BUS_WIDTH_MASK) | SDCI_CTRL_BUS_WIDTH_4BIT; 439 SDCI_CTRL = (SDCI_CTRL & ~SDCI_CTRL_BUS_WIDTH_MASK) | SDCI_CTRL_BUS_WIDTH_4BIT;
400 else if (buswidth == 8) 440 else if (buswidth == 8)
@@ -402,7 +442,8 @@ static int ceata_init(int buswidth)
402 } 442 }
403 PASS_RC(ceata_soft_reset(), 3, 4); 443 PASS_RC(ceata_soft_reset(), 3, 4);
404 PASS_RC(ceata_read_multiple_register(0, ceata_taskfile, 0x10), 3, 5); 444 PASS_RC(ceata_read_multiple_register(0, ceata_taskfile, 0x10), 3, 5);
405 if (ceata_taskfile[0xc] != 0xce || ceata_taskfile[0xd] != 0xaa) RET_ERR(6); 445 if (ceata_taskfile[0xc] != 0xce || ceata_taskfile[0xd] != 0xaa)
446 RET_ERR(6);
406 PASS_RC(mmc_fastio_write(6, 0), 3, 7); 447 PASS_RC(mmc_fastio_write(6, 0), 3, 7);
407 return 0; 448 return 0;
408} 449}
@@ -426,8 +467,10 @@ static int ceata_wait_idle(void)
426 { 467 {
427 uint32_t status; 468 uint32_t status;
428 PASS_RC(mmc_fastio_read(0xf, &status), 1, 0); 469 PASS_RC(mmc_fastio_read(0xf, &status), 1, 0);
429 if (!(status & 0x88)) return 0; 470 if (!(status & 0x88))
430 if (TIMEOUT_EXPIRED(startusec, CEATA_DAT_NONBUSY_TIMEOUT)) RET_ERR(1); 471 return 0;
472 if (TIMEOUT_EXPIRED(startusec, CEATA_DAT_NONBUSY_TIMEOUT))
473 RET_ERR(1);
431 sleep(HZ / 20); 474 sleep(HZ / 20);
432 } 475 }
433} 476}
@@ -476,7 +519,8 @@ static int ceata_rw_multiple_block(bool write, void* buf, uint32_t count, long t
476 | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR, 519 | SDCI_CMD_RES_SIZE_48 | SDCI_CMD_NCR_NID_NCR,
477 direction | MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT(count), 520 direction | MMC_CMD_CEATA_RW_MULTIPLE_BLOCK_COUNT(count),
478 NULL, CEATA_COMMAND_TIMEOUT), 3, 0); 521 NULL, CEATA_COMMAND_TIMEOUT), 3, 0);
479 if (write) SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX; 522 if (write)
523 SDCI_DCTRL = SDCI_DCTRL_TRCONT_TX;
480 if (semaphore_wait(&mmc_wakeup, timeout) == OBJ_WAIT_TIMEDOUT) 524 if (semaphore_wait(&mmc_wakeup, timeout) == OBJ_WAIT_TIMEDOUT)
481 { 525 {
482 PASS_RC(ceata_cancel_command(), 3, 1); 526 PASS_RC(ceata_cancel_command(), 3, 1);
@@ -509,7 +553,8 @@ static int ata_identify(uint16_t* buf)
509 ata_write_cbr(&ATA_PIO_DVR, 0); 553 ata_write_cbr(&ATA_PIO_DVR, 0);
510 ata_write_cbr(&ATA_PIO_CSD, CMD_IDENTIFY); 554 ata_write_cbr(&ATA_PIO_CSD, CMD_IDENTIFY);
511 PASS_RC(ata_wait_for_start_of_transfer(10000000), 1, 1); 555 PASS_RC(ata_wait_for_start_of_transfer(10000000), 1, 1);
512 for (i = 0; i < ATA_IDENTIFY_WORDS; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); 556 for (i = 0; i < ATA_IDENTIFY_WORDS; i++)
557 buf[i] = ata_read_cbr(&ATA_PIO_DTR);
513 } 558 }
514 return 0; 559 return 0;
515} 560}
@@ -548,6 +593,41 @@ static int ata_set_feature(uint32_t feature, uint32_t param)
548 return 0; 593 return 0;
549} 594}
550 595
596#ifdef HAVE_ATA_DMA
597static int udmatimes[ATA_MAX_UDMA + 1] = {
598 0x4071152,
599 0x2050d52,
600#if ATA_MAX_UDMA >= 2
601 0x2030a52,
602#endif
603#if ATA_MAX_UDMA >= 3
604 0x1020a52,
605#endif
606#if ATA_MAX_UDMA >= 4
607 0x1010a52,
608#endif
609};
610static int mwdmatimes[ATA_MAX_MWDMA + 1] = {
611 0x1c175,
612 0x7083,
613 0x5072,
614};
615
616static int ata_get_best_mode(unsigned short identword, int max, int modetype)
617{
618 unsigned short testbit = BIT_N(max);
619
620 while (1) {
621 if (identword & testbit)
622 return max | modetype;
623 testbit >>= 1;
624 if (!testbit)
625 return 0;
626 max--;
627 }
628}
629#endif
630
551/* 631/*
552 * ATA_UDMA_TIME register is documented on s3c6400 datasheet, information 632 * ATA_UDMA_TIME register is documented on s3c6400 datasheet, information
553 * included in s5l8700 datasheet is wrong or not valid for s5l8702. 633 * included in s5l8700 datasheet is wrong or not valid for s5l8702.
@@ -572,10 +652,10 @@ static int ata_power_up(void)
572 ata_set_active(); 652 ata_set_active();
573 ide_power_enable(true); 653 ide_power_enable(true);
574 long spinup_start = current_tick; 654 long spinup_start = current_tick;
575 if (ceata) 655 if (ceata) {
576 {
577 ata_lba48 = true; 656 ata_lba48 = true;
578 ata_dma = true; 657 ata_dma = true;
658 dma_mode = 0xff; /* Canary */
579 PCON(8) = 0x33333333; 659 PCON(8) = 0x33333333;
580 PCON(9) = 0x00000033; 660 PCON(9) = 0x00000033;
581 PCON(11) |= 0xf; 661 PCON(11) |= 0xf;
@@ -595,11 +675,8 @@ static int ata_power_up(void)
595 SDCI_CDIV = SDCI_CDIV_CLKDIV(4); 675 SDCI_CDIV = SDCI_CDIV_CLKDIV(4);
596 sleep(HZ / 100); 676 sleep(HZ / 100);
597 PASS_RC(ceata_init(8), 3, 1); 677 PASS_RC(ceata_init(8), 3, 1);
598 PASS_RC(ata_identify(ata_identify_data), 3, 2); 678 PASS_RC(ata_identify(identify_info), 3, 2);
599 dma_mode = 0x44; 679 } else {
600 }
601 else
602 {
603 PCON(7) = 0x44444444; 680 PCON(7) = 0x44444444;
604 PCON(8) = 0x44444444; 681 PCON(8) = 0x44444444;
605 PCON(9) = 0x44444444; 682 PCON(9) = 0x44444444;
@@ -619,88 +696,71 @@ static int ata_power_up(void)
619 ATA_PIO_LHR = 0; 696 ATA_PIO_LHR = 0;
620 ATA_CFG = BIT(6); 697 ATA_CFG = BIT(6);
621 while (!(ATA_PIO_READY & BIT(1))) yield(); 698 while (!(ATA_PIO_READY & BIT(1))) yield();
622 PASS_RC(ata_identify(ata_identify_data), 3, 3); 699
623 uint32_t piotime = 0x11f3; 700 PASS_RC(ata_identify(identify_info), 3, 3);
624 uint32_t mdmatime = 0x1c175; 701
625 uint32_t udmatime = 0x4071152; 702 uint32_t piotime = 0x11f3; /* PIO0-2? */
626 uint32_t param = 0; 703 if (identify_info[53] & BIT(1)) /* Word 64..70 valid */
627 ata_dma_flags = 0;
628 ata_lba48 = ata_identify_data[83] & BIT(10) ? true : false;
629 if (ata_identify_data[53] & BIT(1))
630 {
631 if (ata_identify_data[64] & BIT(1)) piotime = 0x2072;
632 else if (ata_identify_data[64] & BIT(0)) piotime = 0x7083;
633 }
634 if (ata_identify_data[63] & BIT(2))
635 { 704 {
636 mdmatime = 0x5072; 705 if (identify_info[64] & BIT(1))
637 param = 0x22; 706 piotime = 0x2072; /* PIO mode 4 */
707 else if (identify_info[64] & BIT(0))
708 piotime = 0x7083; /* PIO mode 3 */
638 } 709 }
639 else if (ata_identify_data[63] & BIT(1)) 710 ATA_PIO_TIME = piotime;
711
712 uint32_t param = 0;
713 ata_dma_flags = 0;
714#ifdef HAVE_ATA_DMA
715 if ((identify_info[53] & BIT(2)) && (identify_info[88] & BITRANGE(0, 4))) /* Any UDMA */
640 { 716 {
641 mdmatime = 0x7083; 717 int max_udma = ATA_MAX_UDMA;
642 param = 0x21; 718#if ATA_MAX_UDMA > 2
719 if (!(identify_info[93] & BIT(13)))
720 max_udma = 2;
721#endif
722 param = ata_get_best_mode(identify_info[88], max_udma, 0x40);
723 ATA_UDMA_TIME = udmatimes[param & 0xf];
724 ata_dma_flags = BIT(2) | BIT(3) | BIT(9) | BIT(10);
643 } 725 }
644 if (ata_identify_data[63] & BITRANGE(0, 2)) 726 if (!param && identify_info[63] & BITRANGE(0, 2)) /* Fall back to any MWDMA */
645 { 727 {
728 param = ata_get_best_mode(identify_info[63], ATA_MAX_MWDMA, 0x20);
729 ATA_MDMA_TIME = mwdmatimes[param & 0xf];
646 ata_dma_flags = BIT(3) | BIT(10); 730 ata_dma_flags = BIT(3) | BIT(10);
647 param |= 0x20;
648 }
649 if (ata_identify_data[53] & BIT(2))
650 {
651 if (ata_identify_data[88] & BIT(4))
652 {
653 udmatime = 0x1010a52;
654 param = 0x44;
655 }
656 else if (ata_identify_data[88] & BIT(3))
657 {
658 udmatime = 0x1020a52;
659 param = 0x43;
660 }
661 else if (ata_identify_data[88] & BIT(2))
662 {
663 udmatime = 0x2030a52;
664 param = 0x42;
665 }
666 else if (ata_identify_data[88] & BIT(1))
667 {
668 udmatime = 0x2050d52;
669 param = 0x41;
670 }
671 else if (ata_identify_data[88] & BIT(0))
672 {
673 param = 0x40;
674 }
675 if (ata_identify_data[88] & BITRANGE(0, 4))
676 {
677 ata_dma_flags = BIT(2) | BIT(3) | BIT(9) | BIT(10);
678 }
679 } 731 }
732#endif /* HAVE_ATA_DMA */
680 ata_dma = param ? true : false; 733 ata_dma = param ? true : false;
681 dma_mode = param; 734 dma_mode = param;
682 PASS_RC(ata_set_feature(0x03, param), 3, 4); /* Transfer mode */ 735 PASS_RC(ata_set_feature(0x03, param), 3, 4); /* Transfer mode */
683 if (ata_identify_data[82] & BIT(5)) 736
737 /* SET_FEATURE only supported on PATA, not CE-ATA */
738 if (identify_info[82] & BIT(5))
684 PASS_RC(ata_set_feature(0x02, 0), 3, 5); /* Enable volatile write cache */ 739 PASS_RC(ata_set_feature(0x02, 0), 3, 5); /* Enable volatile write cache */
685 if (ata_identify_data[82] & BIT(6)) 740 if (identify_info[82] & BIT(6))
686 PASS_RC(ata_set_feature(0xaa, 0), 3, 6); /* Enable read lookahead */ 741 PASS_RC(ata_set_feature(0xaa, 0), 3, 6); /* Enable read lookahead */
687 if (ata_identify_data[83] & BIT(3)) 742 if (identify_info[83] & BIT(3))
688 PASS_RC(ata_set_feature(0x05, 0x80), 3, 7); /* Enable lowest power mode w/o standby */ 743 PASS_RC(ata_set_feature(0x05, 0x80), 3, 7); /* Enable lowest power mode w/o standby */
689 if (ata_identify_data[83] & BIT(9)) 744 if (identify_info[83] & BIT(9))
690 PASS_RC(ata_set_feature(0x42, 0x80), 3, 8); /* Enable lowest noise mode */ 745 PASS_RC(ata_set_feature(0x42, 0x80), 3, 8); /* Enable lowest noise mode */
691 ATA_PIO_TIME = piotime; 746
692 ATA_MDMA_TIME = mdmatime; 747 PASS_RC(ata_identify(identify_info), 3, 9); /* Finally, re-read identify info */
693 ATA_UDMA_TIME = udmatime;
694 } 748 }
749
695 spinup_time = current_tick - spinup_start; 750 spinup_time = current_tick - spinup_start;
696 if (ata_lba48) 751
697 ata_total_sectors = ata_identify_data[100] 752 ata_total_sectors = (identify_info[61] << 16) | identify_info[60];
698 | (((uint64_t)ata_identify_data[101]) << 16) 753 if ( identify_info[83] & BIT(10) && ata_total_sectors == 0x0FFFFFFF)
699 | (((uint64_t)ata_identify_data[102]) << 32) 754 {
700 | (((uint64_t)ata_identify_data[103]) << 48); 755 ata_total_sectors = ((uint64_t)identify_info[103] << 48) |
701 else 756 ((uint64_t)identify_info[102] << 32) |
702 ata_total_sectors = ata_identify_data[60] | (((uint32_t)ata_identify_data[61]) << 16); 757 ((uint64_t)identify_info[101] << 16) |
703 ata_total_sectors >>= 3; /* ie SECTOR_SIZE/512. */ 758 identify_info[100];
759 ata_lba48 = true;
760 } else {
761 ata_lba48 = false;
762 }
763
704 ata_powered = true; 764 ata_powered = true;
705 ata_set_active(); 765 ata_set_active();
706 return 0; 766 return 0;
@@ -708,28 +768,8 @@ static int ata_power_up(void)
708 768
709static void ata_power_down(void) 769static void ata_power_down(void)
710{ 770{
711 if (!ata_powered) return; 771 if (!ata_powered)
712 if (ceata) 772 return;
713 {
714 memset(ceata_taskfile, 0, 16);
715 ceata_taskfile[0xf] = CMD_STANDBY_IMMEDIATE;
716 ceata_wait_idle();
717 ceata_write_multiple_register(0, ceata_taskfile, 16);
718 ceata_wait_idle();
719 sleep(HZ);
720 PWRCON(0) |= (1 << 9);
721 }
722 else
723 {
724 ata_wait_for_rdy(1000000);
725 ata_write_cbr(&ATA_PIO_DVR, 0);
726 ata_write_cbr(&ATA_PIO_CSD, CMD_STANDBY_IMMEDIATE);
727 ata_wait_for_rdy(1000000);
728 sleep(HZ / 30);
729 ATA_CONTROL = 0;
730 while (!(ATA_CONTROL & BIT(1))) yield();
731 PWRCON(0) |= (1 << 5);
732 }
733 PCON(7) = 0; 773 PCON(7) = 0;
734 PCON(8) = 0; 774 PCON(8) = 0;
735 PCON(9) = 0; 775 PCON(9) = 0;
@@ -744,18 +784,18 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo
744 if (ceata) 784 if (ceata)
745 { 785 {
746 memset(ceata_taskfile, 0, 16); 786 memset(ceata_taskfile, 0, 16);
747 ceata_taskfile[0x2] = cnt >> 5; 787 ceata_taskfile[0x2] = cnt >> 8;
748 ceata_taskfile[0x3] = sector >> 21; 788 ceata_taskfile[0x3] = sector >> 24;
749 ceata_taskfile[0x4] = sector >> 29; 789 ceata_taskfile[0x4] = sector >> 32;
750 ceata_taskfile[0x5] = sector >> 37; 790 ceata_taskfile[0x5] = sector >> 40;
751 ceata_taskfile[0xa] = cnt << 3; 791 ceata_taskfile[0xa] = cnt;
752 ceata_taskfile[0xb] = sector << 3; 792 ceata_taskfile[0xb] = sector;
753 ceata_taskfile[0xc] = sector >> 5; 793 ceata_taskfile[0xc] = sector >> 8;
754 ceata_taskfile[0xd] = sector >> 13; 794 ceata_taskfile[0xd] = sector >> 16;
755 ceata_taskfile[0xf] = write ? CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT; 795 ceata_taskfile[0xf] = write ? CMD_WRITE_DMA_EXT : CMD_READ_DMA_EXT;
756 PASS_RC(ceata_wait_idle(), 2, 0); 796 PASS_RC(ceata_wait_idle(), 2, 0);
757 PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); 797 PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1);
758 PASS_RC(ceata_rw_multiple_block(write, buffer, cnt << 3, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 2, 2); 798 PASS_RC(ceata_rw_multiple_block(write, buffer, cnt, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 2, 2);
759 } 799 }
760 else 800 else
761 { 801 {
@@ -763,14 +803,14 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo
763 ata_write_cbr(&ATA_PIO_DVR, 0); 803 ata_write_cbr(&ATA_PIO_DVR, 0);
764 if (ata_lba48) 804 if (ata_lba48)
765 { 805 {
766 ata_write_cbr(&ATA_PIO_SCR, cnt >> 5); 806 ata_write_cbr(&ATA_PIO_SCR, (cnt >> 8) & 0xff);
767 ata_write_cbr(&ATA_PIO_SCR, (cnt << 3) & 0xff); 807 ata_write_cbr(&ATA_PIO_SCR, (cnt) & 0xff);
768 ata_write_cbr(&ATA_PIO_LHR, (sector >> 37) & 0xff); 808 ata_write_cbr(&ATA_PIO_LHR, (sector >> 40) & 0xff);
769 ata_write_cbr(&ATA_PIO_LMR, (sector >> 29) & 0xff); 809 ata_write_cbr(&ATA_PIO_LMR, (sector >> 32) & 0xff);
770 ata_write_cbr(&ATA_PIO_LLR, (sector >> 21) & 0xff); 810 ata_write_cbr(&ATA_PIO_LLR, (sector >> 24) & 0xff);
771 ata_write_cbr(&ATA_PIO_LHR, (sector >> 13) & 0xff); 811 ata_write_cbr(&ATA_PIO_LHR, (sector >> 16) & 0xff);
772 ata_write_cbr(&ATA_PIO_LMR, (sector >> 5) & 0xff); 812 ata_write_cbr(&ATA_PIO_LMR, (sector >> 8) & 0xff);
773 ata_write_cbr(&ATA_PIO_LLR, (sector << 3) & 0xff); 813 ata_write_cbr(&ATA_PIO_LLR, (sector) & 0xff);
774 ata_write_cbr(&ATA_PIO_DVR, BIT(6)); 814 ata_write_cbr(&ATA_PIO_DVR, BIT(6));
775 if (write) 815 if (write)
776 ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_WRITE_DMA_EXT : CMD_WRITE_MULTIPLE_EXT); 816 ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_WRITE_DMA_EXT : CMD_WRITE_MULTIPLE_EXT);
@@ -779,16 +819,17 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo
779 } 819 }
780 else 820 else
781 { 821 {
782 ata_write_cbr(&ATA_PIO_SCR, (cnt << 3) & 0xff); 822 ata_write_cbr(&ATA_PIO_SCR, (cnt) & 0xff);
783 ata_write_cbr(&ATA_PIO_LHR, (sector >> 13) & 0xff); 823 ata_write_cbr(&ATA_PIO_LHR, (sector >> 16) & 0xff);
784 ata_write_cbr(&ATA_PIO_LMR, (sector >> 5) & 0xff); 824 ata_write_cbr(&ATA_PIO_LMR, (sector >> 8) & 0xff);
785 ata_write_cbr(&ATA_PIO_LLR, (sector << 3) & 0xff); 825 ata_write_cbr(&ATA_PIO_LLR, (sector) & 0xff);
786 ata_write_cbr(&ATA_PIO_DVR, BIT(6) | ((sector >> 21) & 0xf)); 826 ata_write_cbr(&ATA_PIO_DVR, BIT(6) | ((sector >> 24) & 0xf)); /* LBA28, mask off upper 4 bits of 32-bit sector address */
787 if (write) 827 if (write)
788 ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_WRITE_DMA : CMD_WRITE_SECTORS); 828 ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_WRITE_DMA : CMD_WRITE_SECTORS);
789 else 829 else
790 ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_READ_DMA : CMD_READ_MULTIPLE); 830 ata_write_cbr(&ATA_PIO_CSD, ata_dma ? CMD_READ_DMA : CMD_READ_MULTIPLE);
791 } 831 }
832#ifdef HAVE_ATA_DMA
792 if (ata_dma) 833 if (ata_dma)
793 { 834 {
794 PASS_RC(ata_wait_for_start_of_transfer(500000), 2, 1); 835 PASS_RC(ata_wait_for_start_of_transfer(500000), 2, 1);
@@ -811,8 +852,7 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo
811 ATA_IRQ = BITRANGE(0, 4); 852 ATA_IRQ = BITRANGE(0, 4);
812 ATA_IRQ_MASK = BIT(0); 853 ATA_IRQ_MASK = BIT(0);
813 ATA_COMMAND = BIT(0); 854 ATA_COMMAND = BIT(0);
814 if (semaphore_wait(&ata_wakeup, 500000 * HZ / 1000000) 855 if (semaphore_wait(&ata_wakeup, 500000 * HZ / 1000000) == OBJ_WAIT_TIMEDOUT)
815 == OBJ_WAIT_TIMEDOUT)
816 { 856 {
817 ATA_COMMAND = BIT(1); 857 ATA_COMMAND = BIT(1);
818 ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12)); 858 ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12));
@@ -822,19 +862,19 @@ static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bo
822 ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12)); 862 ATA_CFG &= ~(BITRANGE(2, 3) | BIT(12));
823 } 863 }
824 else 864 else
865#endif // HAVE_ATA_DMA
825 { 866 {
826 cnt *= SECTOR_SIZE / 512;
827 while (cnt--) 867 while (cnt--)
828 { 868 {
829 int i; 869 int i;
830 PASS_RC(ata_wait_for_start_of_transfer(500000), 2, 1); 870 PASS_RC(ata_wait_for_start_of_transfer(500000), 2, 1);
831 if (write) 871 if (write)
832 for (i = 0; i < 256; i++) 872 for (i = 0; i < SECTOR_SIZE/2; i++)
833 ata_write_cbr(&ATA_PIO_DTR, ((uint16_t*)buffer)[i]); 873 ata_write_cbr(&ATA_PIO_DTR, ((uint16_t*)buffer)[i]);
834 else 874 else
835 for (i = 0; i < 256; i++) 875 for (i = 0; i < SECTOR_SIZE/2; i++)
836 ((uint16_t*)buffer)[i] = ata_read_cbr(&ATA_PIO_DTR); 876 ((uint16_t*)buffer)[i] = ata_read_cbr(&ATA_PIO_DTR);
837 buffer += 512; 877 buffer += SECTOR_SIZE;
838 } 878 }
839 } 879 }
840 PASS_RC(ata_wait_for_end_of_transfer(100000), 2, 3); 880 PASS_RC(ata_wait_for_end_of_transfer(100000), 2, 3);
@@ -850,40 +890,27 @@ static int ata_rw_chunk(uint64_t sector, uint32_t cnt, void* buffer, bool write)
850 return rc; 890 return rc;
851} 891}
852 892
853static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write) 893static int ata_transfer_sectors(uint64_t sector, uint32_t count, void* buffer, bool write)
854{ 894{
855 if (STORAGE_OVERLAP((uint32_t)buffer)) 895 if (!ata_powered)
856 { 896 ata_power_up();
857 while (count) 897 if (sector + count > ata_total_sectors)
858 { 898 RET_ERR(0);
859 if (write)
860 memcpy(aligned_buffer, buffer, SECTOR_SIZE);
861
862 PASS_RC(ata_rw_sectors(sector, 1, aligned_buffer, write), 0, 0);
863
864 if (!write)
865 memcpy(buffer, aligned_buffer, SECTOR_SIZE);
866
867 buffer += SECTOR_SIZE;
868 sector++;
869 count--;
870 }
871
872 return 0;
873 }
874
875 if (!ata_powered) ata_power_up();
876 if (sector + count > ata_total_sectors) RET_ERR(0);
877 ata_set_active(); 899 ata_set_active();
878 if (ata_dma && write) commit_dcache(); 900 if (ata_dma && write)
879 else if (ata_dma) commit_discard_dcache(); 901 commit_dcache();
880 if (!ceata) ATA_COMMAND = BIT(1); 902 else if (ata_dma)
903 commit_discard_dcache();
904 if (!ceata)
905 ATA_COMMAND = BIT(1);
906
881 while (count) 907 while (count)
882 { 908 {
883 uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count); 909 uint32_t cnt = MIN(ata_lba48 ? 65536 : 256, count);
884 int rc = -1; 910 int rc = -1;
885 rc = ata_rw_chunk(sector, cnt, buffer, write); 911 rc = ata_rw_chunk(sector, cnt, buffer, write);
886 if (rc && ata_error_srst) ata_reset(); 912 if (rc && ata_error_srst)
913 ata_reset();
887 if (rc && ata_retries) 914 if (rc && ata_retries)
888 { 915 {
889 void* buf = buffer; 916 void* buf = buffer;
@@ -895,9 +922,11 @@ static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool wr
895 while (tries-- && rc) 922 while (tries-- && rc)
896 { 923 {
897 rc = ata_rw_chunk(sect, 1, buf, write); 924 rc = ata_rw_chunk(sect, 1, buf, write);
898 if (rc && ata_error_srst) ata_reset(); 925 if (rc && ata_error_srst)
926 ata_reset();
899 } 927 }
900 if (rc) break; 928 if (rc)
929 break;
901 buf += SECTOR_SIZE; 930 buf += SECTOR_SIZE;
902 } 931 }
903 } 932 }
@@ -915,9 +944,13 @@ int ata_soft_reset(void)
915{ 944{
916 int rc; 945 int rc;
917 mutex_lock(&ata_mutex); 946 mutex_lock(&ata_mutex);
918 if (!ata_powered) PASS_RC(ata_power_up(), 1, 0); 947 if (!ata_powered)
948 PASS_RC(ata_power_up(), 1, 0);
919 ata_set_active(); 949 ata_set_active();
920 if (ceata) rc = ceata_soft_reset(); 950 if (ceata)
951 {
952 rc = ceata_soft_reset();
953 }
921 else 954 else
922 { 955 {
923 ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2)); 956 ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2));
@@ -944,7 +977,8 @@ static int ata_reset(void)
944{ 977{
945 int rc; 978 int rc;
946 mutex_lock(&ata_mutex); 979 mutex_lock(&ata_mutex);
947 if (!ata_powered) PASS_RC(ata_power_up(), 2, 0); 980 if (!ata_powered)
981 PASS_RC(ata_power_up(), 2, 0);
948 ata_set_active(); 982 ata_set_active();
949 rc = ata_soft_reset(); 983 rc = ata_soft_reset();
950 if (IS_ERR(rc)) 984 if (IS_ERR(rc))
@@ -956,7 +990,8 @@ static int ata_reset(void)
956 ata_power_down(); 990 ata_power_down();
957 sleep(HZ * 3); 991 sleep(HZ * 3);
958 int rc2 = ata_power_up(); 992 int rc2 = ata_power_up();
959 if (IS_ERR(rc2)) rc = ERR_RC((rc << 2) | 2); 993 if (IS_ERR(rc2))
994 rc = ERR_RC((rc << 2) | 2);
960 } 995 }
961 else rc = 1; 996 else rc = 1;
962 } 997 }
@@ -965,11 +1000,18 @@ static int ata_reset(void)
965 return rc; 1000 return rc;
966} 1001}
967 1002
1003#include "ata-common.c"
1004
1005#ifndef MAX_PHYS_SECTOR_SIZE
968int ata_read_sectors(IF_MD(int drive,) sector_t start, int incount, 1006int ata_read_sectors(IF_MD(int drive,) sector_t start, int incount,
969 void* inbuf) 1007 void* inbuf)
970{ 1008{
1009#ifdef HAVE_MULTIDRIVE
1010 (void)drive; /* unused for now */
1011#endif
1012
971 mutex_lock(&ata_mutex); 1013 mutex_lock(&ata_mutex);
972 int rc = ata_rw_sectors(start, incount, inbuf, false); 1014 int rc = ata_transfer_sectors(start, incount, inbuf, false);
973 mutex_unlock(&ata_mutex); 1015 mutex_unlock(&ata_mutex);
974 return rc; 1016 return rc;
975} 1017}
@@ -977,11 +1019,16 @@ int ata_read_sectors(IF_MD(int drive,) sector_t start, int incount,
977int ata_write_sectors(IF_MD(int drive,) sector_t start, int count, 1019int ata_write_sectors(IF_MD(int drive,) sector_t start, int count,
978 const void* outbuf) 1020 const void* outbuf)
979{ 1021{
1022#ifdef HAVE_MULTIDRIVE
1023 (void)drive; /* unused for now */
1024#endif
1025
980 mutex_lock(&ata_mutex); 1026 mutex_lock(&ata_mutex);
981 int rc = ata_rw_sectors(start, count, (void*)((uint32_t)outbuf), true); 1027 int rc = ata_transfer_sectors(start, count, (void*)((uint32_t)outbuf), true);
982 mutex_unlock(&ata_mutex); 1028 mutex_unlock(&ata_mutex);
983 return rc; 1029 return rc;
984} 1030}
1031#endif /* ndef MAX_PHYS_SECTOR_SIZE */
985 1032
986void ata_spindown(int seconds) 1033void ata_spindown(int seconds)
987{ 1034{
@@ -992,26 +1039,27 @@ static void ata_flush_cache(void)
992{ 1039{
993 uint8_t cmd; 1040 uint8_t cmd;
994 1041
995 if (ata_identify_data[83] & BIT(13)) { 1042 if (ceata) {
996 cmd = CMD_FLUSH_CACHE_EXT;
997 } else if (ata_identify_data[83] & BIT(12)) {
998 cmd = CMD_FLUSH_CACHE;
999 } else {
1000 /* If neither (mandatory!) command is supported
1001 then don't issue it. */
1002 return;
1003 }
1004
1005 if (ceata)
1006 {
1007 memset(ceata_taskfile, 0, 16); 1043 memset(ceata_taskfile, 0, 16);
1008 ceata_taskfile[0xf] = cmd; 1044 ceata_taskfile[0xf] = CMD_FLUSH_CACHE_EXT; /* CE-ATA only supports EXT */
1009 ceata_wait_idle(); 1045 ceata_wait_idle();
1010 ceata_write_multiple_register(0, ceata_taskfile, 16); 1046 ceata_write_multiple_register(0, ceata_taskfile, 16);
1011 ceata_wait_idle(); 1047 ceata_wait_idle();
1012 } 1048 } else {
1013 else 1049 if (!canflush) {
1014 { 1050 return;
1051 } else if (ata_lba48 && identify_info[83] & BIT(13)) {
1052 cmd = CMD_FLUSH_CACHE_EXT; /* Flag, optional, ATA-6 and up, for use with LBA48 devices. Mandatory for CE-ATA */
1053 } else if (identify_info[83] & BIT(12)) {
1054 cmd = CMD_FLUSH_CACHE; /* Flag, mandatory, ATA-6 and up */
1055 } else if (identify_info[80] >= BIT(5)) { /* Use >= instead of '&' because bits lower than the latest standard we support don't have to be set */
1056 cmd = CMD_FLUSH_CACHE; /* No flag, mandatory, ATA-5 (Optional for ATA-4) */
1057 } else {
1058 /* If neither command is supported then don't issue it. */
1059 canflush = 0;
1060 return;
1061 }
1062
1015 ata_wait_for_rdy(1000000); 1063 ata_wait_for_rdy(1000000);
1016 ata_write_cbr(&ATA_PIO_DVR, 0); 1064 ata_write_cbr(&ATA_PIO_DVR, 0);
1017 ata_write_cbr(&ATA_PIO_CSD, cmd); 1065 ata_write_cbr(&ATA_PIO_CSD, cmd);
@@ -1019,14 +1067,46 @@ static void ata_flush_cache(void)
1019 } 1067 }
1020} 1068}
1021 1069
1070int ata_flush(void)
1071{
1072 if (ata_powered) {
1073 mutex_lock(&ata_mutex);
1074 ata_flush_cache();
1075 mutex_unlock(&ata_mutex);
1076 }
1077 return 0;
1078}
1079
1022void ata_sleepnow(void) 1080void ata_sleepnow(void)
1023{ 1081{
1024 mutex_lock(&ata_mutex); 1082 mutex_lock(&ata_mutex);
1025 1083
1026 if (ata_disk_can_poweroff()) 1084 ata_flush_cache();
1027 ata_power_down(); 1085
1028 else 1086 if (ata_disk_can_sleep()) {
1029 ata_flush_cache(); 1087 if (ceata) {
1088 memset(ceata_taskfile, 0, 16);
1089 ceata_taskfile[0xf] = CMD_STANDBY_IMMEDIATE;
1090 ceata_wait_idle();
1091 ceata_write_multiple_register(0, ceata_taskfile, 16);
1092 ceata_wait_idle();
1093 sleep(HZ);
1094 PWRCON(0) |= (1 << 9);
1095 } else {
1096 ata_wait_for_rdy(1000000);
1097 ata_write_cbr(&ATA_PIO_DVR, 0);
1098 ata_write_cbr(&ATA_PIO_CSD, CMD_STANDBY_IMMEDIATE);
1099 ata_wait_for_rdy(1000000);
1100 sleep(HZ / 30);
1101 ATA_CONTROL = 0;
1102 while (!(ATA_CONTROL & BIT(1)))
1103 yield();
1104 PWRCON(0) |= (1 << 5);
1105 }
1106 }
1107
1108 if (ata_disk_can_sleep() || canflush)
1109 ata_power_down(); // XXX add a powerdown delay similar to main ATA driver?
1030 1110
1031 mutex_unlock(&ata_mutex); 1111 mutex_unlock(&ata_mutex);
1032} 1112}
@@ -1036,14 +1116,21 @@ void ata_spin(void)
1036 ata_set_active(); 1116 ata_set_active();
1037} 1117}
1038 1118
1119#ifdef STORAGE_GET_INFO
1039void ata_get_info(IF_MD(int drive,) struct storage_info *info) 1120void ata_get_info(IF_MD(int drive,) struct storage_info *info)
1040{ 1121{
1041 (*info).sector_size = SECTOR_SIZE; 1122 /* Logical sector size */
1123 if ((identify_info[106] & 0xd000) == 0x5000) /* B14, B12 */
1124 info->sector_size = (identify_info[117] | (identify_info[118] << 16)) * 2;
1125 else
1126 info->sector_size = SECTOR_SIZE;
1127
1042 (*info).num_sectors = ata_total_sectors; 1128 (*info).num_sectors = ata_total_sectors;
1043 (*info).vendor = "Apple"; 1129 (*info).vendor = "Apple";
1044 (*info).product = "iPod Classic"; 1130 (*info).product = "iPod Classic";
1045 (*info).revision = "1.0"; 1131 (*info).revision = "1.0";
1046} 1132}
1133#endif
1047 1134
1048long ata_last_disk_activity(void) 1135long ata_last_disk_activity(void)
1049{ 1136{
@@ -1060,11 +1147,18 @@ int ata_init(void)
1060 ata_powered = false; 1147 ata_powered = false;
1061 ata_total_sectors = 0; 1148 ata_total_sectors = 0;
1062 1149
1063 /* get ata_identify_data */ 1150 /* get identify_info */
1064 mutex_lock(&ata_mutex); 1151 mutex_lock(&ata_mutex);
1065 int rc = ata_power_up(); 1152 int rc = ata_power_up();
1066 mutex_unlock(&ata_mutex); 1153 mutex_unlock(&ata_mutex);
1067 if (IS_ERR(rc)) return rc; 1154 if (IS_ERR(rc))
1155 return rc;
1156
1157#ifdef MAX_PHYS_SECTOR_SIZE
1158 rc = ata_get_phys_sector_mult();
1159 if (IS_ERR(rc))
1160 return rc;
1161#endif
1068 1162
1069 return 0; 1163 return 0;
1070} 1164}
@@ -1081,7 +1175,7 @@ static int ata_smart(uint16_t* buf)
1081 ceata_taskfile[0xe] = BIT(6); 1175 ceata_taskfile[0xe] = BIT(6);
1082 ceata_taskfile[0xf] = CMD_SMART; 1176 ceata_taskfile[0xf] = CMD_SMART;
1083 PASS_RC(ceata_wait_idle(), 3, 1); 1177 PASS_RC(ceata_wait_idle(), 3, 1);
1084 if (((uint8_t*)ata_identify_data)[54] != 'A') /* Model != aAmsung */ 1178 if (((uint8_t*)identify_info)[54] != 'A') /* Model != aAmsung */
1085 { 1179 {
1086 ceata_taskfile[0x9] = 0xd8; /* SMART enable operations */ 1180 ceata_taskfile[0x9] = 0xd8; /* SMART enable operations */
1087 PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 2); 1181 PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 3, 2);
@@ -1101,7 +1195,8 @@ static int ata_smart(uint16_t* buf)
1101 ata_write_cbr(&ATA_PIO_DVR, BIT(6)); 1195 ata_write_cbr(&ATA_PIO_DVR, BIT(6));
1102 ata_write_cbr(&ATA_PIO_CSD, CMD_SMART); 1196 ata_write_cbr(&ATA_PIO_CSD, CMD_SMART);
1103 PASS_RC(ata_wait_for_start_of_transfer(10000000), 3, 7); 1197 PASS_RC(ata_wait_for_start_of_transfer(10000000), 3, 7);
1104 for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); 1198 for (i = 0; i < 0x100; i++)
1199 buf[i] = ata_read_cbr(&ATA_PIO_DTR);
1105 } 1200 }
1106 ata_set_active(); 1201 ata_set_active();
1107 return 0; 1202 return 0;
@@ -1128,7 +1223,7 @@ static int ata_num_drives(int first_drive)
1128 1223
1129unsigned short* ata_get_identify(void) 1224unsigned short* ata_get_identify(void)
1130{ 1225{
1131 return ata_identify_data; 1226 return identify_info;
1132} 1227}
1133 1228
1134int ata_spinup_time(void) 1229int ata_spinup_time(void)
@@ -1136,24 +1231,29 @@ int ata_spinup_time(void)
1136 return spinup_time; 1231 return spinup_time;
1137} 1232}
1138 1233
1234#ifdef HAVE_ATA_DMA
1139int ata_get_dma_mode(void) 1235int ata_get_dma_mode(void)
1140{ 1236{
1141 return dma_mode; 1237 return dma_mode;
1142} 1238}
1239#endif
1143 1240
1144void INT_ATA(void) 1241void INT_ATA(void)
1145{ 1242{
1146 uint32_t ata_irq = ATA_IRQ; 1243 uint32_t ata_irq = ATA_IRQ;
1147 ATA_IRQ = ata_irq; 1244 ATA_IRQ = ata_irq;
1148 if (ata_irq & ATA_IRQ_MASK) semaphore_release(&ata_wakeup); 1245 if (ata_irq & ATA_IRQ_MASK)
1246 semaphore_release(&ata_wakeup);
1149 ATA_IRQ_MASK = 0; 1247 ATA_IRQ_MASK = 0;
1150} 1248}
1151 1249
1152void INT_MMC(void) 1250void INT_MMC(void)
1153{ 1251{
1154 uint32_t irq = SDCI_IRQ; 1252 uint32_t irq = SDCI_IRQ;
1155 if (irq & SDCI_IRQ_DAT_DONE_INT) semaphore_release(&mmc_wakeup); 1253 if (irq & SDCI_IRQ_DAT_DONE_INT)
1156 if (irq & SDCI_IRQ_IOCARD_IRQ_INT) semaphore_release(&mmc_comp_wakeup); 1254 semaphore_release(&mmc_wakeup);
1255 if (irq & SDCI_IRQ_IOCARD_IRQ_INT)
1256 semaphore_release(&mmc_comp_wakeup);
1157 SDCI_IRQ = irq; 1257 SDCI_IRQ = irq;
1158} 1258}
1159 1259
diff --git a/firmware/target/arm/tms320dm320/system-dm320.c b/firmware/target/arm/tms320dm320/system-dm320.c
index 6cf616184d..62eaf1f8ce 100644
--- a/firmware/target/arm/tms320dm320/system-dm320.c
+++ b/firmware/target/arm/tms320dm320/system-dm320.c
@@ -100,7 +100,7 @@ default_interrupt(RESERVED);
100 * change the offset for the interrupt in the entry table. 100 * change the offset for the interrupt in the entry table.
101 */ 101 */
102 102
103static const unsigned short const irqpriority[] = 103static const unsigned short irqpriority[] =
104{ 104{
105 IRQ_TIMER0,IRQ_TIMER1,IRQ_TIMER2,IRQ_TIMER3,IRQ_CCD_VD0,IRQ_CCD_VD1, 105 IRQ_TIMER0,IRQ_TIMER1,IRQ_TIMER2,IRQ_TIMER3,IRQ_CCD_VD0,IRQ_CCD_VD1,
106 IRQ_CCD_WEN,IRQ_VENC,IRQ_SERIAL0,IRQ_SERIAL1,IRQ_EXT_HOST,IRQ_DSPHINT, 106 IRQ_CCD_WEN,IRQ_VENC,IRQ_SERIAL0,IRQ_SERIAL1,IRQ_EXT_HOST,IRQ_DSPHINT,
diff --git a/firmware/target/coldfire/system-coldfire.c b/firmware/target/coldfire/system-coldfire.c
index ed130fca1f..2f2f2cb45b 100644
--- a/firmware/target/coldfire/system-coldfire.c
+++ b/firmware/target/coldfire/system-coldfire.c
@@ -26,6 +26,11 @@
26#include "lcd.h" 26#include "lcd.h"
27#include "font.h" 27#include "font.h"
28 28
29#if __GNUC__ >= 9
30#pragma GCC diagnostic push
31#pragma GCC diagnostic ignored "-Wmissing-attributes"
32#endif
33
29#define default_interrupt(name) \ 34#define default_interrupt(name) \
30 extern __attribute__((weak,alias("UIE"))) void name (void) 35 extern __attribute__((weak,alias("UIE"))) void name (void)
31 36
diff --git a/firmware/target/hosted/agptek/debug-agptek.c b/firmware/target/hosted/agptek/debug-agptek.c
index a9b829f7ec..de4bc946bc 100644
--- a/firmware/target/hosted/agptek/debug-agptek.c
+++ b/firmware/target/hosted/agptek/debug-agptek.c
@@ -37,6 +37,8 @@
37 37
38static int line = 0; 38static int line = 0;
39 39
40extern int hwver;
41
40bool dbg_hw_info(void) 42bool dbg_hw_info(void)
41{ 43{
42 int btn = 0; 44 int btn = 0;
@@ -61,6 +63,10 @@ bool dbg_hw_info(void)
61 lcd_putsf(0, line++, "Boot ver: %s", verstr); 63 lcd_putsf(0, line++, "Boot ver: %s", verstr);
62 } 64 }
63 65
66#ifdef EROS_Q
67 lcd_putsf(0, line++, "hwver: %d", hwver);
68#endif
69
64 lcd_putsf(0, line++, "pcm srate: %d", pcm_alsa_get_rate()); 70 lcd_putsf(0, line++, "pcm srate: %d", pcm_alsa_get_rate());
65 lcd_putsf(0, line++, "pcm xruns: %d", pcm_alsa_get_xruns()); 71 lcd_putsf(0, line++, "pcm xruns: %d", pcm_alsa_get_xruns());
66#ifdef HAVE_HEADPHONE_DETECTION 72#ifdef HAVE_HEADPHONE_DETECTION
diff --git a/firmware/target/hosted/aigo/power-erosq.c b/firmware/target/hosted/aigo/power-erosq.c
index 73fa5fe972..7c4515f616 100644
--- a/firmware/target/hosted/aigo/power-erosq.c
+++ b/firmware/target/hosted/aigo/power-erosq.c
@@ -28,17 +28,34 @@
28#include "power.h" 28#include "power.h"
29#include "panic.h" 29#include "panic.h"
30#include "sysfs.h" 30#include "sysfs.h"
31#include "tick.h"
31 32
32const char * const sysfs_bat_voltage = 33const char * const sysfs_bat_voltage[2] = {
33 "/sys/class/power_supply/battery/voltage_now"; 34 "/sys/class/power_supply/battery/voltage_now",
35 "/sys/class/power_supply/axp_battery/voltage_now",
36};
34 37
35const char * const sysfs_bat_capacity = 38const char * const sysfs_bat_capacity[2] = {
36 "/sys/class/power_supply/battery/capacity"; 39 "/sys/class/power_supply/battery/capacity",
40 "/sys/class/power_supply/axp_battery/capacity",
41};
42
43const char * const sysfs_bat_status[2] = {
44 "/sys/class/power_supply/battery/status",
45 "/sys/class/power_supply/axp_battery/status",
46};
47
48int hwver = 1; /* Exported */
37 49
38unsigned int erosq_power_get_battery_voltage(void) 50unsigned int erosq_power_get_battery_voltage(void)
39{ 51{
40 int battery_voltage; 52 int battery_voltage;
41 sysfs_get_int(sysfs_bat_voltage, &battery_voltage); 53 int x = sysfs_get_int(sysfs_bat_voltage[hwver == 4], &battery_voltage);
54
55 if (!x && hwver != 4) {
56 hwver = 4;
57 sysfs_get_int(sysfs_bat_voltage[hwver == 4], &battery_voltage);
58 }
42 59
43 return battery_voltage/1000; 60 return battery_voltage/1000;
44} 61}
@@ -46,7 +63,33 @@ unsigned int erosq_power_get_battery_voltage(void)
46unsigned int erosq_power_get_battery_capacity(void) 63unsigned int erosq_power_get_battery_capacity(void)
47{ 64{
48 int battery_capacity; 65 int battery_capacity;
49 sysfs_get_int(sysfs_bat_capacity, &battery_capacity); 66 int x = sysfs_get_int(sysfs_bat_capacity[hwver == 4], &battery_capacity);
67
68 if (!x && hwver != 4) {
69 hwver = 4;
70 sysfs_get_int(sysfs_bat_capacity[hwver == 4], &battery_capacity);
71 }
50 72
51 return battery_capacity; 73 return battery_capacity;
52} 74}
75
76/* We get called multiple times per tick, let's cut that back! */
77static long last_tick = 0;
78static bool last_power = false;
79
80bool charging_state(void)
81{
82 if ((current_tick - last_tick) > HZ/2 ) {
83 char buf[12] = {0};
84 int x = sysfs_get_string(sysfs_bat_status[hwver == 4], buf, sizeof(buf));
85
86 if (!x && hwver != 4) {
87 hwver = 4;
88 sysfs_get_string(sysfs_bat_status[hwver == 4], buf, sizeof(buf));
89 }
90
91 last_tick = current_tick;
92 last_power = (strncmp(buf, "Charging", 8) == 0);
93 }
94 return last_power;
95}
diff --git a/firmware/target/hosted/alsa-controls.h b/firmware/target/hosted/alsa-controls.h
index af3e584cd9..b868ef52fb 100644
--- a/firmware/target/hosted/alsa-controls.h
+++ b/firmware/target/hosted/alsa-controls.h
@@ -36,6 +36,8 @@ void alsa_controls_close(void);
36 36
37/* check wether a control exists */ 37/* check wether a control exists */
38bool alsa_has_control(const char *name); 38bool alsa_has_control(const char *name);
39/* find a control element ID by name, return -1 of not found or index into array */
40int alsa_controls_find(const char *name);
39/* find a control element enum index by name, return -1 if not found */ 41/* find a control element enum index by name, return -1 if not found */
40int alsa_controls_find_enum(const char *name, const char *enum_name); 42int alsa_controls_find_enum(const char *name, const char *enum_name);
41/* set a control, potentially supports several values */ 43/* set a control, potentially supports several values */
diff --git a/firmware/target/hosted/power-linux.c b/firmware/target/hosted/power-linux.c
index ddd7ad63e3..8d263eebec 100644
--- a/firmware/target/hosted/power-linux.c
+++ b/firmware/target/hosted/power-linux.c
@@ -33,9 +33,13 @@
33#include "usb.h" 33#include "usb.h"
34#endif 34#endif
35 35
36#ifdef BATTERY_DEV_NAME
36#define BATTERY_STATUS_PATH "/sys/class/power_supply/" BATTERY_DEV_NAME "/status" 37#define BATTERY_STATUS_PATH "/sys/class/power_supply/" BATTERY_DEV_NAME "/status"
38#endif
39
37#define POWER_STATUS_PATH "/sys/class/power_supply/" POWER_DEV_NAME "/online" 40#define POWER_STATUS_PATH "/sys/class/power_supply/" POWER_DEV_NAME "/online"
38 41
42#ifdef BATTERY_DEV_NAME
39/* We get called multiple times per tick, let's cut that back! */ 43/* We get called multiple times per tick, let's cut that back! */
40static long last_tick = 0; 44static long last_tick = 0;
41static bool last_power = false; 45static bool last_power = false;
@@ -51,6 +55,7 @@ bool charging_state(void)
51 } 55 }
52 return last_power; 56 return last_power;
53} 57}
58#endif
54 59
55unsigned int power_input_status(void) 60unsigned int power_input_status(void)
56{ 61{
diff --git a/firmware/target/hosted/sdl/app/button-application.c b/firmware/target/hosted/sdl/app/button-application.c
index 9c313b76b1..8071df201a 100644
--- a/firmware/target/hosted/sdl/app/button-application.c
+++ b/firmware/target/hosted/sdl/app/button-application.c
@@ -40,23 +40,23 @@ int key_to_button(int keyboard_key)
40#if (CONFIG_PLATFORM & PLATFORM_MAEMO4) 40#if (CONFIG_PLATFORM & PLATFORM_MAEMO4)
41 case SDLK_ESCAPE: 41 case SDLK_ESCAPE:
42#endif 42#endif
43 case SDLK_KP7: 43 case SDLK_KP_7:
44 new_btn = BUTTON_TOPLEFT; 44 new_btn = BUTTON_TOPLEFT;
45 break; 45 break;
46 case SDLK_KP8: 46 case SDLK_KP_8:
47 case SDLK_UP: 47 case SDLK_UP:
48 new_btn = BUTTON_TOPMIDDLE; 48 new_btn = BUTTON_TOPMIDDLE;
49 break; 49 break;
50#if (CONFIG_PLATFORM & PLATFORM_MAEMO4) 50#if (CONFIG_PLATFORM & PLATFORM_MAEMO4)
51 case SDLK_F7: 51 case SDLK_F7:
52#endif 52#endif
53 case SDLK_KP9: 53 case SDLK_KP_9:
54 new_btn = BUTTON_TOPRIGHT; 54 new_btn = BUTTON_TOPRIGHT;
55 break; 55 break;
56#if (CONFIG_PLATFORM & PLATFORM_PANDORA) 56#if (CONFIG_PLATFORM & PLATFORM_PANDORA)
57 case SDLK_RSHIFT: 57 case SDLK_RSHIFT:
58#endif 58#endif
59 case SDLK_KP4: 59 case SDLK_KP_4:
60 case SDLK_LEFT: 60 case SDLK_LEFT:
61 new_btn = BUTTON_MIDLEFT; 61 new_btn = BUTTON_MIDLEFT;
62 break; 62 break;
@@ -64,40 +64,32 @@ int key_to_button(int keyboard_key)
64 case SDLK_RETURN: 64 case SDLK_RETURN:
65 case SDLK_KP_ENTER: 65 case SDLK_KP_ENTER:
66#endif 66#endif
67 case SDLK_KP5: 67 case SDLK_KP_5:
68 new_btn = BUTTON_CENTER; 68 new_btn = BUTTON_CENTER;
69 break; 69 break;
70#if (CONFIG_PLATFORM & PLATFORM_PANDORA) 70#if (CONFIG_PLATFORM & PLATFORM_PANDORA)
71 case SDLK_RCTRL: 71 case SDLK_RCTRL:
72#endif 72#endif
73 case SDLK_KP6: 73 case SDLK_KP_6:
74 case SDLK_RIGHT: 74 case SDLK_RIGHT:
75 new_btn = BUTTON_MIDRIGHT; 75 new_btn = BUTTON_MIDRIGHT;
76 break; 76 break;
77#if (CONFIG_PLATFORM & PLATFORM_MAEMO4) 77#if (CONFIG_PLATFORM & PLATFORM_MAEMO4)
78 case SDLK_F6: 78 case SDLK_F6:
79#endif 79#endif
80 case SDLK_KP1: 80 case SDLK_KP_1:
81 new_btn = BUTTON_BOTTOMLEFT; 81 new_btn = BUTTON_BOTTOMLEFT;
82 break; 82 break;
83 case SDLK_KP2: 83 case SDLK_KP_2:
84 case SDLK_DOWN: 84 case SDLK_DOWN:
85 new_btn = BUTTON_BOTTOMMIDDLE; 85 new_btn = BUTTON_BOTTOMMIDDLE;
86 break; 86 break;
87#if (CONFIG_PLATFORM & PLATFORM_MAEMO4) 87#if (CONFIG_PLATFORM & PLATFORM_MAEMO4)
88 case SDLK_F8: 88 case SDLK_F8:
89#endif 89#endif
90 case SDLK_KP3: 90 case SDLK_KP_3:
91 new_btn = BUTTON_BOTTOMRIGHT; 91 new_btn = BUTTON_BOTTOMRIGHT;
92 break; 92 break;
93#ifdef HAVE_SCROLLWHEEL
94 case SDL_BUTTON_WHEELUP:
95 new_btn = BUTTON_SCROLL_BACK;
96 break;
97 case SDL_BUTTON_WHEELDOWN:
98 new_btn = BUTTON_SCROLL_FWD;
99 break;
100#endif
101 case SDL_BUTTON_RIGHT: 93 case SDL_BUTTON_RIGHT:
102 new_btn = BUTTON_MIDLEFT; 94 new_btn = BUTTON_MIDLEFT;
103 break; 95 break;
diff --git a/firmware/target/hosted/sdl/button-sdl.c b/firmware/target/hosted/sdl/button-sdl.c
index b5f3720a3b..8af6f3ffaf 100644
--- a/firmware/target/hosted/sdl/button-sdl.c
+++ b/firmware/target/hosted/sdl/button-sdl.c
@@ -107,6 +107,30 @@ static void touchscreen_event(int x, int y)
107} 107}
108#endif 108#endif
109 109
110#if defined(HAVE_SCROLLWHEEL) || ((defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK)))
111static void scrollwheel_event(int x, int y)
112{
113 int new_btn = 0;
114 if (y > 0)
115 new_btn = BUTTON_SCROLL_BACK;
116 else if (y < 0)
117 new_btn = BUTTON_SCROLL_FWD;
118 else
119 return;
120
121#ifdef HAVE_BACKLIGHT
122 backlight_on();
123#endif
124#ifdef HAVE_BUTTON_LIGHT
125 buttonlight_on();
126#endif
127 reset_poweroff_timer();
128 if (new_btn && !queue_full(&button_queue))
129 queue_post(&button_queue, new_btn, 1<<24);
130
131 (void)x;
132}
133#endif
110static void mouse_event(SDL_MouseButtonEvent *event, bool button_up) 134static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
111{ 135{
112#define SQUARE(x) ((x)*(x)) 136#define SQUARE(x) ((x)*(x))
@@ -118,10 +142,6 @@ static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
118 if(button_up) { 142 if(button_up) {
119 switch ( event->button ) 143 switch ( event->button )
120 { 144 {
121#ifdef HAVE_SCROLLWHEEL
122 case SDL_BUTTON_WHEELUP:
123 case SDL_BUTTON_WHEELDOWN:
124#endif
125 case SDL_BUTTON_MIDDLE: 145 case SDL_BUTTON_MIDDLE:
126 case SDL_BUTTON_RIGHT: 146 case SDL_BUTTON_RIGHT:
127 button_event( event->button, false ); 147 button_event( event->button, false );
@@ -145,13 +165,9 @@ static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
145#endif 165#endif
146 break; 166 break;
147 } 167 }
148 } else { /* button down */ 168 } else { /* button down */
149 switch ( event->button ) 169 switch ( event->button )
150 { 170 {
151#ifdef HAVE_SCROLLWHEEL
152 case SDL_BUTTON_WHEELUP:
153 case SDL_BUTTON_WHEELDOWN:
154#endif
155 case SDL_BUTTON_MIDDLE: 171 case SDL_BUTTON_MIDDLE:
156 case SDL_BUTTON_RIGHT: 172 case SDL_BUTTON_RIGHT:
157 button_event( event->button, true ); 173 button_event( event->button, true );
@@ -215,18 +231,15 @@ static void mouse_event(SDL_MouseButtonEvent *event, bool button_up)
215 231
216static bool event_handler(SDL_Event *event) 232static bool event_handler(SDL_Event *event)
217{ 233{
218 SDLKey ev_key; 234 SDL_Keycode ev_key;
219 235
220 switch(event->type) 236 switch(event->type)
221 { 237 {
222 case SDL_ACTIVEEVENT: 238 case SDL_WINDOWEVENT:
223 if (event->active.state & SDL_APPINPUTFOCUS) 239 if (event->window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
224 { 240 sdl_app_has_input_focus = 1;
225 if (event->active.gain == 1) 241 else if (event->window.event == SDL_WINDOWEVENT_FOCUS_LOST)
226 sdl_app_has_input_focus = 1; 242 sdl_app_has_input_focus = 0;
227 else
228 sdl_app_has_input_focus = 0;
229 }
230 break; 243 break;
231 case SDL_KEYDOWN: 244 case SDL_KEYDOWN:
232 case SDL_KEYUP: 245 case SDL_KEYUP:
@@ -275,6 +288,13 @@ static bool event_handler(SDL_Event *event)
275 mouse_event(mev, event->type == SDL_MOUSEBUTTONUP); 288 mouse_event(mev, event->type == SDL_MOUSEBUTTONUP);
276 break; 289 break;
277 } 290 }
291#ifdef HAVE_SCROLLWHEEL
292 case SDL_MOUSEWHEEL:
293 {
294 scrollwheel_event(event->wheel.x, event->wheel.y);
295 break;
296 }
297#endif
278 case SDL_QUIT: 298 case SDL_QUIT:
279 /* Will post SDL_USEREVENT in shutdown_hw() if successful. */ 299 /* Will post SDL_USEREVENT in shutdown_hw() if successful. */
280 sdl_sys_quit(); 300 sdl_sys_quit();
@@ -362,7 +382,7 @@ static void button_event(int key, bool pressed)
362 } 382 }
363 return; 383 return;
364#endif 384#endif
365 385
366#ifdef HAS_REMOTE_BUTTON_HOLD 386#ifdef HAS_REMOTE_BUTTON_HOLD
367 case SDLK_j: 387 case SDLK_j:
368 if(pressed) 388 if(pressed)
@@ -379,7 +399,7 @@ static void button_event(int key, bool pressed)
379 if(pressed) 399 if(pressed)
380 switch(_remote_type) 400 switch(_remote_type)
381 { 401 {
382 case REMOTETYPE_UNPLUGGED: 402 case REMOTETYPE_UNPLUGGED:
383 _remote_type=REMOTETYPE_H100_LCD; 403 _remote_type=REMOTETYPE_H100_LCD;
384 DEBUGF("Changed remote type to H100\n"); 404 DEBUGF("Changed remote type to H100\n");
385 break; 405 break;
@@ -399,7 +419,7 @@ static void button_event(int key, bool pressed)
399 break; 419 break;
400#endif 420#endif
401#ifndef APPLICATION 421#ifndef APPLICATION
402 case SDLK_KP0: 422 case SDLK_KP_0:
403 case SDLK_F5: 423 case SDLK_F5:
404 if(pressed) 424 if(pressed)
405 { 425 {
@@ -430,32 +450,17 @@ static void button_event(int key, bool pressed)
430#endif 450#endif
431 break; 451 break;
432 } 452 }
433 /* Call to make up for scrollwheel target implementation. This is 453
434 * not handled in the main button.c driver, but on the target
435 * implementation (look at button-e200.c for example if you are trying to
436 * figure out why using button_get_data needed a hack before).
437 */
438#if defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK) 454#if defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK)
439 if((new_btn == BUTTON_SCROLL_FWD || new_btn == BUTTON_SCROLL_BACK) && 455 if((new_btn == BUTTON_SCROLL_FWD || new_btn == BUTTON_SCROLL_BACK) &&
440 pressed) 456 pressed)
441 { 457 {
442 /* Clear these buttons from the data - adding them to the queue is 458 scrollwheel_event(0, new_btn == BUTTON_SCROLL_FWD ? -1 : 1);
443 * handled in the scrollwheel drivers for the targets. They do not
444 * store the scroll forward/back buttons in their button data for
445 * the button_read call.
446 */
447#ifdef HAVE_BACKLIGHT
448 backlight_on();
449#endif
450#ifdef HAVE_BUTTON_LIGHT
451 buttonlight_on();
452#endif
453 reset_poweroff_timer();
454 queue_post(&button_queue, new_btn, 1<<24);
455 new_btn &= ~(BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK); 459 new_btn &= ~(BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK);
456 } 460 }
457#endif 461#endif
458 462
463 /* Update global button press state */
459 if (pressed) 464 if (pressed)
460 btn |= new_btn; 465 btn |= new_btn;
461 else 466 else
@@ -496,5 +501,4 @@ int button_read_device(void)
496 501
497void button_init_device(void) 502void button_init_device(void)
498{ 503{
499 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
500} 504}
diff --git a/firmware/target/hosted/sdl/kernel-sdl.c b/firmware/target/hosted/sdl/kernel-sdl.c
index 5c16f86749..bcad39b4d8 100644
--- a/firmware/target/hosted/sdl/kernel-sdl.c
+++ b/firmware/target/hosted/sdl/kernel-sdl.c
@@ -153,7 +153,7 @@ void sim_kernel_shutdown(void)
153 SDL_Delay(10); 153 SDL_Delay(10);
154 154
155 SDL_DestroyMutex(sim_irq_mtx); 155 SDL_DestroyMutex(sim_irq_mtx);
156 SDL_DestroyCond(sim_thread_cond); 156 SDL_DestroyCond(sim_thread_cond);
157} 157}
158 158
159Uint32 tick_timer(Uint32 interval, void *param) 159Uint32 tick_timer(Uint32 interval, void *param)
@@ -162,9 +162,9 @@ Uint32 tick_timer(Uint32 interval, void *param)
162 162
163 (void) interval; 163 (void) interval;
164 (void) param; 164 (void) param;
165 165
166 new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ); 166 new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
167 167
168 while(new_tick != current_tick) 168 while(new_tick != current_tick)
169 { 169 {
170 sim_enter_irq_handler(); 170 sim_enter_irq_handler();
@@ -175,7 +175,7 @@ Uint32 tick_timer(Uint32 interval, void *param)
175 175
176 sim_exit_irq_handler(); 176 sim_exit_irq_handler();
177 } 177 }
178 178
179 return interval; 179 return interval;
180} 180}
181 181
@@ -187,10 +187,10 @@ void tick_start(unsigned int interval_in_ms)
187 exit(-1); 187 exit(-1);
188 } 188 }
189 189
190 if (tick_timer_id != NULL) 190 if (tick_timer_id != 0)
191 { 191 {
192 SDL_RemoveTimer(tick_timer_id); 192 SDL_RemoveTimer(tick_timer_id);
193 tick_timer_id = NULL; 193 tick_timer_id = 0;
194 } 194 }
195 else 195 else
196 { 196 {
diff --git a/firmware/target/hosted/sdl/key_to_touch-sdl.c b/firmware/target/hosted/sdl/key_to_touch-sdl.c
index d56d06ba74..b7052e043f 100644
--- a/firmware/target/hosted/sdl/key_to_touch-sdl.c
+++ b/firmware/target/hosted/sdl/key_to_touch-sdl.c
@@ -52,12 +52,12 @@ int key_to_touch(int keyboard_button, unsigned int mouse_coords)
52 } 52 }
53 break; 53 break;
54#ifndef APPLICATION 54#ifndef APPLICATION
55 case SDLK_KP7: 55 case SDLK_KP_7:
56 case SDLK_7: 56 case SDLK_7:
57 case SDLK_HOME: 57 case SDLK_HOME:
58 new_btn = BUTTON_TOPLEFT; 58 new_btn = BUTTON_TOPLEFT;
59 break; 59 break;
60 case SDLK_KP8: 60 case SDLK_KP_8:
61 case SDLK_8: 61 case SDLK_8:
62 case SDLK_UP: 62 case SDLK_UP:
63#ifdef HAVE_SCROLLWHEEL 63#ifdef HAVE_SCROLLWHEEL
@@ -65,32 +65,32 @@ int key_to_touch(int keyboard_button, unsigned int mouse_coords)
65#endif 65#endif
66 new_btn = BUTTON_TOPMIDDLE; 66 new_btn = BUTTON_TOPMIDDLE;
67 break; 67 break;
68 case SDLK_KP9: 68 case SDLK_KP_9:
69 case SDLK_9: 69 case SDLK_9:
70 case SDLK_PAGEUP: 70 case SDLK_PAGEUP:
71 new_btn = BUTTON_TOPRIGHT; 71 new_btn = BUTTON_TOPRIGHT;
72 break; 72 break;
73 case SDLK_KP4: 73 case SDLK_KP_4:
74 case SDLK_u: 74 case SDLK_u:
75 case SDLK_LEFT: 75 case SDLK_LEFT:
76 new_btn = BUTTON_MIDLEFT; 76 new_btn = BUTTON_MIDLEFT;
77 break; 77 break;
78 case SDLK_KP5: 78 case SDLK_KP_5:
79 case SDLK_i: 79 case SDLK_i:
80 case SDL_BUTTON_MIDDLE: 80 case SDL_BUTTON_MIDDLE:
81 new_btn = BUTTON_CENTER; 81 new_btn = BUTTON_CENTER;
82 break; 82 break;
83 case SDLK_KP6: 83 case SDLK_KP_6:
84 case SDLK_o: 84 case SDLK_o:
85 case SDLK_RIGHT: 85 case SDLK_RIGHT:
86 new_btn = BUTTON_MIDRIGHT; 86 new_btn = BUTTON_MIDRIGHT;
87 break; 87 break;
88 case SDLK_KP1: 88 case SDLK_KP_1:
89 case SDLK_j: 89 case SDLK_j:
90 case SDLK_END: 90 case SDLK_END:
91 new_btn = BUTTON_BOTTOMLEFT; 91 new_btn = BUTTON_BOTTOMLEFT;
92 break; 92 break;
93 case SDLK_KP2: 93 case SDLK_KP_2:
94 case SDLK_k: 94 case SDLK_k:
95#ifdef HAVE_SCROLLWHEEL 95#ifdef HAVE_SCROLLWHEEL
96 case SDL_BUTTON_WHEELDOWN: 96 case SDL_BUTTON_WHEELDOWN:
@@ -98,7 +98,7 @@ int key_to_touch(int keyboard_button, unsigned int mouse_coords)
98 case SDLK_DOWN: 98 case SDLK_DOWN:
99 new_btn = BUTTON_BOTTOMMIDDLE; 99 new_btn = BUTTON_BOTTOMMIDDLE;
100 break; 100 break;
101 case SDLK_KP3: 101 case SDLK_KP_3:
102 case SDLK_l: 102 case SDLK_l:
103 case SDLK_PAGEDOWN: 103 case SDLK_PAGEDOWN:
104 new_btn = BUTTON_BOTTOMRIGHT; 104 new_btn = BUTTON_BOTTOMRIGHT;
@@ -106,4 +106,5 @@ int key_to_touch(int keyboard_button, unsigned int mouse_coords)
106#endif 106#endif
107 } 107 }
108 return new_btn; 108 return new_btn;
109
109} 110}
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.c b/firmware/target/hosted/sdl/lcd-bitmap.c
index ea30afea3b..ef284eeb48 100644
--- a/firmware/target/hosted/sdl/lcd-bitmap.c
+++ b/firmware/target/hosted/sdl/lcd-bitmap.c
@@ -164,12 +164,12 @@ void sim_backlight(int value)
164#else /* LCD_DEPTH > 8 */ 164#else /* LCD_DEPTH > 8 */
165#if defined(HAVE_TRANSFLECTIVE_LCD) && defined(HAVE_LCD_SLEEP) 165#if defined(HAVE_TRANSFLECTIVE_LCD) && defined(HAVE_LCD_SLEEP)
166 if (!lcd_active()) 166 if (!lcd_active())
167 SDL_SetAlpha(lcd_surface, SDL_SRCALPHA, 0); 167 SDL_SetSurfaceAlphaMod(lcd_surface, 0);
168 else 168 else
169 SDL_SetAlpha(lcd_surface, SDL_SRCALPHA, 169 SDL_SetSurfaceAlphaMod(lcd_surface,
170 MAX(BACKLIGHT_OFF_ALPHA, (value * 255) / 100)); 170 MAX(BACKLIGHT_OFF_ALPHA, (value * 255) / 100));
171#else 171#else
172 SDL_SetAlpha(lcd_surface, SDL_SRCALPHA, (value * 255) / 100); 172 SDL_SetSurfaceAlphaMod(lcd_surface, (value * 255) / 100);
173#endif 173#endif
174#endif /* LCD_DEPTH */ 174#endif /* LCD_DEPTH */
175 175
@@ -187,6 +187,7 @@ void lcd_init_device(void)
187 SIM_LCD_WIDTH * display_zoom, 187 SIM_LCD_WIDTH * display_zoom,
188 SIM_LCD_HEIGHT * display_zoom, 188 SIM_LCD_HEIGHT * display_zoom,
189 LCD_DEPTH, 0, 0, 0, 0); 189 LCD_DEPTH, 0, 0, 0, 0);
190 SDL_SetSurfaceBlendMode(lcd_surface, SDL_BLENDMODE_BLEND);
190#elif LCD_DEPTH <= 8 191#elif LCD_DEPTH <= 8
191 lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 192 lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
192 SIM_LCD_WIDTH * display_zoom, 193 SIM_LCD_WIDTH * display_zoom,
@@ -222,7 +223,7 @@ void sim_lcd_ex_update_rect(int x_start, int y_start, int width, int height)
222 if (lcd_ex_getpixel) { 223 if (lcd_ex_getpixel) {
223 sdl_update_rect(lcd_surface, x_start, y_start, width, height, 224 sdl_update_rect(lcd_surface, x_start, y_start, width, height,
224 LCD_WIDTH, LCD_HEIGHT, lcd_ex_getpixel); 225 LCD_WIDTH, LCD_HEIGHT, lcd_ex_getpixel);
225 sdl_gui_update(lcd_surface, x_start, y_start, width, 226 sdl_gui_update(lcd_surface, x_start, y_start, width,
226 height + LCD_SPLIT_LINES, SIM_LCD_WIDTH, SIM_LCD_HEIGHT, 227 height + LCD_SPLIT_LINES, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
227 background ? UI_LCD_POSX : 0, 228 background ? UI_LCD_POSX : 0,
228 background ? UI_LCD_POSY : 0); 229 background ? UI_LCD_POSY : 0);
diff --git a/firmware/target/hosted/sdl/lcd-sdl.c b/firmware/target/hosted/sdl/lcd-sdl.c
index 8cbb6c5651..1e9daeffd3 100644
--- a/firmware/target/hosted/sdl/lcd-sdl.c
+++ b/firmware/target/hosted/sdl/lcd-sdl.c
@@ -115,12 +115,17 @@ void sdl_gui_update(SDL_Surface *surface, int x_start, int y_start, int width,
115 (ui_y + y_start) * display_zoom, 115 (ui_y + y_start) * display_zoom,
116 width * display_zoom, height * display_zoom}; 116 width * display_zoom, height * display_zoom};
117 117
118 if (surface->flags & SDL_SRCALPHA) /* alpha needs a black background */ 118 uint8_t alpha;
119 if (SDL_GetSurfaceAlphaMod(surface,&alpha) == 0 && alpha < 255)
119 SDL_FillRect(gui_surface, &dest, 0); 120 SDL_FillRect(gui_surface, &dest, 0);
120 121
121 SDL_BlitSurface(surface, &src, gui_surface, &dest); 122 SDL_BlitSurface(surface, &src, gui_surface, &dest); /* alpha needs a black background */
122 123
123 SDL_Flip(gui_surface); 124 SDL_Texture *sdlTexture = SDL_CreateTextureFromSurface(sdlRenderer, gui_surface);
125 SDL_RenderClear(sdlRenderer);
126 SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
127 SDL_RenderPresent(sdlRenderer);
128 SDL_DestroyTexture(sdlTexture);
124} 129}
125 130
126/* set a range of bitmap indices to a gradient from startcolour to endcolour */ 131/* set a range of bitmap indices to a gradient from startcolour to endcolour */
@@ -136,7 +141,7 @@ void sdl_set_gradient(SDL_Surface *surface, SDL_Color *start, SDL_Color *end,
136 palette[i].b = start->b + (end->b - start->b) * i / (steps - 1); 141 palette[i].b = start->b + (end->b - start->b) * i / (steps - 1);
137 } 142 }
138 143
139 SDL_SetPalette(surface, SDL_LOGPAL|SDL_PHYSPAL, palette, first, steps); 144 SDL_SetPaletteColors(surface->format->palette, palette, first , steps);
140} 145}
141 146
142int lcd_get_dpi(void) 147int lcd_get_dpi(void)
diff --git a/firmware/target/hosted/sdl/lcd-sdl.h b/firmware/target/hosted/sdl/lcd-sdl.h
index a964c9bc40..3f1334e4a2 100644
--- a/firmware/target/hosted/sdl/lcd-sdl.h
+++ b/firmware/target/hosted/sdl/lcd-sdl.h
@@ -3,7 +3,7 @@
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
@@ -27,6 +27,7 @@
27 27
28/* Default display zoom level */ 28/* Default display zoom level */
29extern SDL_Surface *gui_surface; 29extern SDL_Surface *gui_surface;
30extern SDL_Renderer *sdlRenderer;
30 31
31void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width, 32void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width,
32 int height, int max_x, int max_y, 33 int height, int max_x, int max_y,
@@ -39,4 +40,3 @@ void sdl_set_gradient(SDL_Surface *surface, SDL_Color *start, SDL_Color *end,
39 int first, int steps); 40 int first, int steps);
40 41
41#endif /* #ifndef __LCDSDL_H__ */ 42#endif /* #ifndef __LCDSDL_H__ */
42
diff --git a/firmware/target/hosted/sdl/pcm-sdl.c b/firmware/target/hosted/sdl/pcm-sdl.c
index 940403002f..dec12af2f1 100644
--- a/firmware/target/hosted/sdl/pcm-sdl.c
+++ b/firmware/target/hosted/sdl/pcm-sdl.c
@@ -1,10 +1,10 @@
1/*************************************************************************** 1/***************************************************************************
2 * __________ __ ___. 2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2005 by Nick Lanham 10 * Copyright (C) 2005 by Nick Lanham
@@ -85,8 +85,43 @@ void pcm_play_unlock(void)
85 SDL_UnlockMutex(audio_lock); 85 SDL_UnlockMutex(audio_lock);
86} 86}
87 87
88static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len);
88static void pcm_dma_apply_settings_nolock(void) 89static void pcm_dma_apply_settings_nolock(void)
89{ 90{
91 SDL_AudioSpec wanted_spec;
92 wanted_spec.freq = pcm_sampr;
93 wanted_spec.format = AUDIO_S16SYS;
94 wanted_spec.channels = 2;
95 wanted_spec.samples = 2048;
96 wanted_spec.callback =
97 (void (SDLCALL *)(void *userdata,
98 Uint8 *stream, int len))sdl_audio_callback;
99 wanted_spec.userdata = &udata;
100 SDL_CloseAudio();
101 /* Open the audio device and start playing sound! */
102 if(SDL_OpenAudio(&wanted_spec, &obtained) < 0) {
103 DEBUGF("Unable to open audio: %s\n", SDL_GetError());
104 return;
105 }
106 switch (obtained.format)
107 {
108 case AUDIO_U8:
109 case AUDIO_S8:
110 pcm_channel_bytes = 1;
111 break;
112 case AUDIO_U16LSB:
113 case AUDIO_S16LSB:
114 case AUDIO_U16MSB:
115 case AUDIO_S16MSB:
116 pcm_channel_bytes = 2;
117 break;
118 default:
119 DEBUGF("Unknown sample format obtained: %u\n",
120 (unsigned)obtained.format);
121 return;
122 }
123 pcm_sample_bytes = obtained.channels * pcm_channel_bytes;
124
90 cvt_status = SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, 2, pcm_sampr, 125 cvt_status = SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, 2, pcm_sampr,
91 obtained.format, obtained.channels, obtained.freq); 126 obtained.format, obtained.channels, obtained.freq);
92 127
@@ -104,7 +139,6 @@ void pcm_dma_apply_settings(void)
104 139
105void pcm_play_dma_start(const void *addr, size_t size) 140void pcm_play_dma_start(const void *addr, size_t size)
106{ 141{
107 pcm_dma_apply_settings_nolock();
108 142
109 pcm_data = addr; 143 pcm_data = addr;
110 pcm_data_size = size; 144 pcm_data_size = size;
@@ -257,9 +291,7 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
257 291
258 if (delay > 0) 292 if (delay > 0)
259 { 293 {
260 SDL_UnlockMutex(audio_lock);
261 SDL_Delay(delay); 294 SDL_Delay(delay);
262 SDL_LockMutex(audio_lock);
263 295
264 if (!pcm_is_playing()) 296 if (!pcm_is_playing())
265 break; 297 break;
@@ -340,7 +372,6 @@ void pcm_play_dma_init(void)
340 return; 372 return;
341 } 373 }
342 374
343 SDL_AudioSpec wanted_spec;
344#ifdef DEBUG 375#ifdef DEBUG
345 udata.debug = NULL; 376 udata.debug = NULL;
346 if (debug_audio) { 377 if (debug_audio) {
@@ -348,43 +379,6 @@ void pcm_play_dma_init(void)
348 DEBUGF("Audio debug file open\n"); 379 DEBUGF("Audio debug file open\n");
349 } 380 }
350#endif 381#endif
351 /* Set 16-bit stereo audio at 44Khz */
352 wanted_spec.freq = 44100;
353 wanted_spec.format = AUDIO_S16SYS;
354 wanted_spec.channels = 2;
355 wanted_spec.samples = 2048;
356 wanted_spec.callback =
357 (void (SDLCALL *)(void *userdata,
358 Uint8 *stream, int len))sdl_audio_callback;
359 wanted_spec.userdata = &udata;
360
361 /* Open the audio device and start playing sound! */
362 if(SDL_OpenAudio(&wanted_spec, &obtained) < 0) {
363 DEBUGF("Unable to open audio: %s\n", SDL_GetError());
364 return;
365 }
366
367 switch (obtained.format)
368 {
369 case AUDIO_U8:
370 case AUDIO_S8:
371 pcm_channel_bytes = 1;
372 break;
373 case AUDIO_U16LSB:
374 case AUDIO_S16LSB:
375 case AUDIO_U16MSB:
376 case AUDIO_S16MSB:
377 pcm_channel_bytes = 2;
378 break;
379 default:
380 DEBUGF("Unknown sample format obtained: %u\n",
381 (unsigned)obtained.format);
382 return;
383 }
384
385 pcm_sample_bytes = obtained.channels * pcm_channel_bytes;
386
387 pcm_dma_apply_settings_nolock();
388} 382}
389 383
390void pcm_play_dma_postinit(void) 384void pcm_play_dma_postinit(void)
diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c
index e53643f449..56cff3f1be 100644
--- a/firmware/target/hosted/sdl/system-sdl.c
+++ b/firmware/target/hosted/sdl/system-sdl.c
@@ -1,10 +1,10 @@
1/*************************************************************************** 1/***************************************************************************
2 * __________ __ ___. 2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2006 by Daniel Everton <dan@iocaine.org> 10 * Copyright (C) 2006 by Daniel Everton <dan@iocaine.org>
@@ -50,6 +50,8 @@
50#define SIMULATOR_DEFAULT_ROOT "simdisk" 50#define SIMULATOR_DEFAULT_ROOT "simdisk"
51 51
52SDL_Surface *gui_surface; 52SDL_Surface *gui_surface;
53SDL_Window *window;
54SDL_Renderer *sdlRenderer;
53 55
54bool background = true; /* use backgrounds by default */ 56bool background = true; /* use backgrounds by default */
55#ifdef HAVE_REMOTE_LCD 57#ifdef HAVE_REMOTE_LCD
@@ -72,26 +74,12 @@ bool debug_audio = false;
72bool debug_wps = false; 74bool debug_wps = false;
73int wps_verbose_level = 3; 75int wps_verbose_level = 3;
74 76
75/* 77static void sdl_window_setup(void)
76 * This thread will read the buttons in an interrupt like fashion, and
77 * also initializes SDL_INIT_VIDEO and the surfaces
78 *
79 * it must be done in the same thread (at least on windows) because events only
80 * work in the thread which called SDL_Init(SubSystem) with SDL_INIT_VIDEO
81 *
82 * This is an SDL thread and relies on preemptive behavoir of the host
83 **/
84static int sdl_event_thread(void * param)
85{ 78{
86 SDL_InitSubSystem(SDL_INIT_VIDEO);
87
88#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
89 SDL_sem *wait_for_maemo_startup;
90#endif
91 SDL_Surface *picture_surface = NULL; 79 SDL_Surface *picture_surface = NULL;
92 int width, height; 80 int width, height;
93 int depth; 81 int depth;
94 Uint32 flags; 82 Uint32 flags = 0;
95 83
96 /* Try and load the background image. If it fails go without */ 84 /* Try and load the background image. If it fails go without */
97 if (background) { 85 if (background) {
@@ -101,14 +89,14 @@ static int sdl_event_thread(void * param)
101 DEBUGF("warn: %s\n", SDL_GetError()); 89 DEBUGF("warn: %s\n", SDL_GetError());
102 } 90 }
103 } 91 }
104 92
105 /* Set things up */ 93 /* Set things up */
106 if (background) 94 if (background)
107 { 95 {
108 width = UI_WIDTH; 96 width = UI_WIDTH;
109 height = UI_HEIGHT; 97 height = UI_HEIGHT;
110 } 98 }
111 else 99 else
112 { 100 {
113#ifdef HAVE_REMOTE_LCD 101#ifdef HAVE_REMOTE_LCD
114 if (showremote) 102 if (showremote)
@@ -128,17 +116,47 @@ static int sdl_event_thread(void * param)
128 if (depth < 8) 116 if (depth < 8)
129 depth = 16; 117 depth = 16;
130 118
131 flags = SDL_HWSURFACE|SDL_DOUBLEBUF;
132#if (CONFIG_PLATFORM & (PLATFORM_MAEMO|PLATFORM_PANDORA)) 119#if (CONFIG_PLATFORM & (PLATFORM_MAEMO|PLATFORM_PANDORA))
133 /* Fullscreen mode for maemo app */ 120 /* Fullscreen mode for maemo app */
134 flags |= SDL_FULLSCREEN; 121 flags |= SDL_WINDOW_FULLSCREEN;
135#endif 122#endif
136 123
137 SDL_WM_SetCaption(UI_TITLE, NULL); 124 if ((window = SDL_CreateWindow(UI_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
138 125 width * display_zoom, height * display_zoom , flags)) == NULL)
139 if ((gui_surface = SDL_SetVideoMode(width * display_zoom, height * display_zoom, depth, flags)) == NULL) { 126 panicf("%s", SDL_GetError());
127 if ((sdlRenderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL)
140 panicf("%s", SDL_GetError()); 128 panicf("%s", SDL_GetError());
129 if ((gui_surface = SDL_CreateRGBSurface(0, width * display_zoom, height * display_zoom, depth,
130 0, 0, 0, 0)) == NULL)
131 panicf("%s", SDL_GetError());
132
133 /* If we have a background, blit it over to the display surface */
134 if (background && picture_surface)
135 {
136 SDL_BlitSurface(picture_surface, NULL, gui_surface, NULL);
137 SDL_FreeSurface(picture_surface);
141 } 138 }
139}
140
141/*
142 * This thread will read the buttons in an interrupt like fashion, and
143 * also initializes SDL_INIT_VIDEO and the surfaces
144 *
145 * it must be done in the same thread (at least on windows) because events only
146 * work in the thread that called SDL_InitSubSystem(SDL_INIT_VIDEO)
147 *
148 * This is an SDL thread and relies on preemptive behavoir of the host
149 **/
150static int sdl_event_thread(void * param)
151{
152#ifdef __WIN32 /* Fails on Linux and MacOS */
153 SDL_InitSubSystem(SDL_INIT_VIDEO);
154 sdl_window_setup();
155#endif
156
157#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
158 SDL_sem *wait_for_maemo_startup;
159#endif
142 160
143#if (CONFIG_PLATFORM & (PLATFORM_MAEMO|PLATFORM_PANDORA)) 161#if (CONFIG_PLATFORM & (PLATFORM_MAEMO|PLATFORM_PANDORA))
144 /* SDL touch screen fix: Work around a SDL assumption that returns 162 /* SDL touch screen fix: Work around a SDL assumption that returns
@@ -152,14 +170,10 @@ static int sdl_event_thread(void * param)
152 SDL_SetCursor(hiddenCursor); 170 SDL_SetCursor(hiddenCursor);
153#endif 171#endif
154 172
155 if (background && picture_surface != NULL)
156 SDL_BlitSurface(picture_surface, NULL, gui_surface, NULL);
157
158#if (CONFIG_PLATFORM & PLATFORM_MAEMO) 173#if (CONFIG_PLATFORM & PLATFORM_MAEMO)
159 /* start maemo thread: Listen to display on/off events and battery monitoring */ 174 /* start maemo thread: Listen to display on/off events and battery monitoring */
160 wait_for_maemo_startup = SDL_CreateSemaphore(0); /* 0-count so it blocks */ 175 wait_for_maemo_startup = SDL_CreateSemaphore(0); /* 0-count so it blocks */
161 SDL_Thread *maemo_thread = SDL_CreateThread(maemo_thread_func, wait_for_maemo_startup); 176 SDL_Thread *maemo_thread = SDL_CreateThread(maemo_thread_func, NULL, wait_for_maemo_startup);
162
163 SDL_SemWait(wait_for_maemo_startup); 177 SDL_SemWait(wait_for_maemo_startup);
164 SDL_DestroySemaphore(wait_for_maemo_startup); 178 SDL_DestroySemaphore(wait_for_maemo_startup);
165#endif 179#endif
@@ -184,9 +198,6 @@ static int sdl_event_thread(void * param)
184 SDL_FreeCursor(hiddenCursor); 198 SDL_FreeCursor(hiddenCursor);
185#endif 199#endif
186 200
187 if(picture_surface)
188 SDL_FreeSurface(picture_surface);
189
190 /* Order here is relevent to prevent deadlocks and use of destroyed 201 /* Order here is relevent to prevent deadlocks and use of destroyed
191 sync primitives by kernel threads */ 202 sync primitives by kernel threads */
192#ifdef HAVE_SDL_THREADS 203#ifdef HAVE_SDL_THREADS
@@ -251,15 +262,16 @@ void system_init(void)
251 g_type_init(); 262 g_type_init();
252#endif 263#endif
253 264
254 if (SDL_Init(SDL_INIT_TIMER)) 265 if (SDL_InitSubSystem(SDL_INIT_TIMER))
255 panicf("%s", SDL_GetError()); 266 panicf("%s", SDL_GetError());
256 267
257 s = SDL_CreateSemaphore(0); /* 0-count so it blocks */ 268#ifndef __WIN32 /* Fails on Windows */
258 269 SDL_InitSubSystem(SDL_INIT_VIDEO);
259 evt_thread = SDL_CreateThread(sdl_event_thread, s); 270 sdl_window_setup();
271#endif
260 272
261 /* wait for sdl_event_thread to run so that it can initialize the surfaces 273 s = SDL_CreateSemaphore(0); /* 0-count so it blocks */
262 * and video subsystem needed for SDL events */ 274 evt_thread = SDL_CreateThread(sdl_event_thread, NULL, s);
263 SDL_SemWait(s); 275 SDL_SemWait(s);
264 /* cleanup */ 276 /* cleanup */
265 SDL_DestroySemaphore(s); 277 SDL_DestroySemaphore(s);
@@ -303,29 +315,29 @@ int hostfs_flush(void)
303 315
304void sys_handle_argv(int argc, char *argv[]) 316void sys_handle_argv(int argc, char *argv[])
305{ 317{
306 if (argc >= 1) 318 if (argc >= 1)
307 { 319 {
308 int x; 320 int x;
309 for (x = 1; x < argc; x++) 321 for (x = 1; x < argc; x++)
310 { 322 {
311#ifdef DEBUG 323#ifdef DEBUG
312 if (!strcmp("--debugaudio", argv[x])) 324 if (!strcmp("--debugaudio", argv[x]))
313 { 325 {
314 debug_audio = true; 326 debug_audio = true;
315 printf("Writing debug audio file.\n"); 327 printf("Writing debug audio file.\n");
316 } 328 }
317 else 329 else
318#endif 330#endif
319 if (!strcmp("--debugwps", argv[x])) 331 if (!strcmp("--debugwps", argv[x]))
320 { 332 {
321 debug_wps = true; 333 debug_wps = true;
322 printf("WPS debug mode enabled.\n"); 334 printf("WPS debug mode enabled.\n");
323 } 335 }
324 else if (!strcmp("--nobackground", argv[x])) 336 else if (!strcmp("--nobackground", argv[x]))
325 { 337 {
326 background = false; 338 background = false;
327 printf("Disabling background image.\n"); 339 printf("Disabling background image.\n");
328 } 340 }
329#ifdef HAVE_REMOTE_LCD 341#ifdef HAVE_REMOTE_LCD
330 else if (!strcmp("--noremote", argv[x])) 342 else if (!strcmp("--noremote", argv[x]))
331 { 343 {
@@ -346,7 +358,7 @@ void sys_handle_argv(int argc, char *argv[])
346 display_zoom=atof(argv[x]); 358 display_zoom=atof(argv[x]);
347 else 359 else
348 display_zoom = 2; 360 display_zoom = 2;
349 printf("Window zoom is %d\n", display_zoom); 361 printf("Window zoom is %f\n", display_zoom);
350 } 362 }
351 else if (!strcmp("--alarm", argv[x])) 363 else if (!strcmp("--alarm", argv[x]))
352 { 364 {
@@ -372,7 +384,7 @@ void sys_handle_argv(int argc, char *argv[])
372 debug_buttons = true; 384 debug_buttons = true;
373 printf("Printing background button clicks.\n"); 385 printf("Printing background button clicks.\n");
374 } 386 }
375 else 387 else
376 { 388 {
377 printf("rockboxui\n"); 389 printf("rockboxui\n");
378 printf("Arguments:\n"); 390 printf("Arguments:\n");
diff --git a/firmware/target/hosted/sdl/thread-sdl.c b/firmware/target/hosted/sdl/thread-sdl.c
index 17a0f847b5..abd6339cee 100644
--- a/firmware/target/hosted/sdl/thread-sdl.c
+++ b/firmware/target/hosted/sdl/thread-sdl.c
@@ -340,7 +340,7 @@ unsigned int create_thread(void (*function)(void),
340 return 0; 340 return 0;
341 } 341 }
342 342
343 SDL_Thread *t = SDL_CreateThread(runthread, thread); 343 SDL_Thread *t = SDL_CreateThread(runthread, NULL, thread);
344 if (t == NULL) 344 if (t == NULL)
345 { 345 {
346 DEBUGF("Failed to create SDL thread\n"); 346 DEBUGF("Failed to create SDL thread\n");
@@ -447,7 +447,7 @@ void init_threads(void)
447 thread->context.s = SDL_CreateSemaphore(0); 447 thread->context.s = SDL_CreateSemaphore(0);
448 thread->context.t = NULL; /* NULL for the implicit main thread */ 448 thread->context.t = NULL; /* NULL for the implicit main thread */
449 __running_self_entry() = thread; 449 __running_self_entry() = thread;
450 450
451 if (thread->context.s == NULL) 451 if (thread->context.s == NULL)
452 { 452 {
453 fprintf(stderr, "Failed to create main semaphore\n"); 453 fprintf(stderr, "Failed to create main semaphore\n");
diff --git a/firmware/target/mips/ingenic_jz47xx/xduoo_x3/power-xduoo_x3.c b/firmware/target/mips/ingenic_jz47xx/xduoo_x3/power-xduoo_x3.c
index 9ae602ba56..c9bcb47fcd 100644
--- a/firmware/target/mips/ingenic_jz47xx/xduoo_x3/power-xduoo_x3.c
+++ b/firmware/target/mips/ingenic_jz47xx/xduoo_x3/power-xduoo_x3.c
@@ -23,15 +23,19 @@
23#include "power.h" 23#include "power.h"
24#include "cpu.h" 24#include "cpu.h"
25 25
26#define CHARGE_STAT_GPIO (32*1+6) /* STAT port */ 26#define CHARGE_STAT_GPIO (32*1+6) /* STAT port */
27#define PIN_USB_DET (32*4+19) /* USB connected */
27 28
28/* Detect which power sources are present. */ 29/* Detect which power sources are present. */
29unsigned int power_input_status(void) 30unsigned int power_input_status(void)
30{ 31{
32 int rval = POWER_INPUT_NONE;
33 if(!__gpio_get_pin(PIN_USB_DET))
34 rval |= POWER_INPUT_USB;
31 if(!__gpio_get_pin(CHARGE_STAT_GPIO)) 35 if(!__gpio_get_pin(CHARGE_STAT_GPIO))
32 return POWER_INPUT_USB_CHARGER; 36 rval |= POWER_INPUT_USB_CHARGER;
33 37
34 return POWER_INPUT_NONE; 38 return rval;
35} 39}
36 40
37void power_init(void) 41void power_init(void)
@@ -42,5 +46,5 @@ void power_init(void)
42 46
43bool charging_state(void) 47bool charging_state(void)
44{ 48{
45 return (power_input_status() == POWER_INPUT_USB_CHARGER); 49 return (power_input_status() & POWER_INPUT_USB_CHARGER);
46} 50}
diff --git a/firmware/target/mips/ingenic_x1000/crt0.S b/firmware/target/mips/ingenic_x1000/crt0.S
index 6c0942b0db..23daaefb5e 100644
--- a/firmware/target/mips/ingenic_x1000/crt0.S
+++ b/firmware/target/mips/ingenic_x1000/crt0.S
@@ -23,6 +23,10 @@
23#include "mips.h" 23#include "mips.h"
24#include "bootdata.h" 24#include "bootdata.h"
25 25
26#if defined(HAVE_DEVICEDATA) && !defined(BOOTLOADER)
27#include "devicedata.h"
28#endif
29
26 .text 30 .text
27 .extern main 31 .extern main
28 .extern system_early_init 32 .extern system_early_init
@@ -52,6 +56,9 @@ _header:
52#ifndef BOOTLOADER 56#ifndef BOOTLOADER
53 /* Multiboot support header; this is not part of the above header. */ 57 /* Multiboot support header; this is not part of the above header. */
54 put_boot_data_here 58 put_boot_data_here
59#ifdef HAVE_DEVICEDATA
60 put_device_data_here
61#endif
55#endif 62#endif
56 63
57_realstart: 64_realstart:
diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
index 0d43a3f010..bcc30a71bd 100644
--- a/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
+++ b/firmware/target/mips/ingenic_x1000/erosqnative/lcd-erosqnative.c
@@ -25,11 +25,138 @@
25#include "lcd-x1000.h" 25#include "lcd-x1000.h"
26#include "gpio-x1000.h" 26#include "gpio-x1000.h"
27#include "system.h" 27#include "system.h"
28#include "devicedata.h"
28 29
29/* for reference on these command/data hex values, see the mipi dcs lcd spec. * 30/* for reference on these command/data hex values, see the mipi dcs lcd spec. *
30 * Not everything here is there, but all the standard stuff is. */ 31 * Not everything here is there, but all the standard stuff is. */
31 32
32static const uint32_t erosqnative_lcd_cmd_enable[] = { 33/* New Display Eroq 2.1 / Hifiwalker 1.7+ / Surfans v3.2, unknown Controller *
34 * (partially GC9A01 register compatible) *
35 * https://espruino.microcosm.app/api/v1/files/ \ *
36 * 9dc1b976d621a2ab3854312cce862c4a9a50dc1b.html#GC9A01 , *
37 * https://www.buydisplay.com/download/ic/GC9A01A.pdf , *
38 * https://lcddisplay.co/wp-content/uploads/2023/02/GC9A01.pdf *
39 * Init sequence From 'EROS Q (c口)_V2.1_20231209固件.zip' *
40 * update.upt/.iso -> In 'uboot.bin' at 0x52da0-0x5305f *
41 * http://www.eroshifi.com/download/firmware/122.html */
42static const uint32_t erosqnative_lcd_cmd_enable_v3[] = {
43
44 /* Unlock EXTC? */
45 LCD_INSTR_CMD, 0xfe, // Inter Register Enable1
46 LCD_INSTR_CMD, 0xef, // Inter Register Enable2
47
48 LCD_INSTR_CMD, 0x36, // Memory Access Control
49/* Bit7 1:vertical flip 0:no vertical flip
50 Bit6 1:horizontal flip 0:no horizontal flip
51 Bit3 1:BGR 0:RGB */
52 LCD_INSTR_DAT, 0x90,
53 /* Pixel Format Set */
54 LCD_INSTR_CMD, 0x3a,
55 LCD_INSTR_DAT, 0x55, /* Rockbox uses 16pp, OF specified 18 bpp */
56
57 LCD_INSTR_CMD, 0x84, // ?? (undocumented)
58 LCD_INSTR_DAT, 0x04,
59 LCD_INSTR_CMD, 0x86, // ??
60 LCD_INSTR_DAT, 0xfb,
61 LCD_INSTR_CMD, 0x87, // ??
62 LCD_INSTR_DAT, 0x79,
63 LCD_INSTR_CMD, 0x89, // ??
64 LCD_INSTR_DAT, 0x0b,
65 LCD_INSTR_CMD, 0x8a, // ??
66 LCD_INSTR_DAT, 0x20,
67 LCD_INSTR_CMD, 0x8b, // ??
68 LCD_INSTR_DAT, 0x80,
69 LCD_INSTR_CMD, 0x8d, // ??
70 LCD_INSTR_DAT, 0x3b,
71 LCD_INSTR_CMD, 0x8e, // ??
72 LCD_INSTR_DAT, 0xcf,
73
74 LCD_INSTR_CMD, 0xec, // Charge Pump Frequent Control
75 LCD_INSTR_DAT, 0x33,
76 LCD_INSTR_DAT, 0x02,
77 LCD_INSTR_DAT, 0x4c,
78
79 LCD_INSTR_CMD, 0x98, // ?? (undocumented)
80 LCD_INSTR_DAT, 0x3e,
81 LCD_INSTR_CMD, 0x9c, // ??
82 LCD_INSTR_DAT, 0x4b,
83 LCD_INSTR_CMD, 0x99, // ??
84 LCD_INSTR_DAT, 0x3e,
85 LCD_INSTR_CMD, 0x9d, // ??
86 LCD_INSTR_DAT, 0x4b,
87 LCD_INSTR_CMD, 0x9b, // ??
88 LCD_INSTR_DAT, 0x55,
89
90 LCD_INSTR_CMD, 0xe8, // Frame Rate
91 LCD_INSTR_DAT, 0x11,
92 LCD_INSTR_DAT, 0x00,
93
94 LCD_INSTR_CMD, 0xff, // ?? (Adafruit & Co lib. C:0xFF, D:0x60, D:0x01, D:0x04)
95 LCD_INSTR_DAT, 0x62, // LCD_INSTR_DAT, 0x01, LCD_INSTR_DAT, 0x04,
96 LCD_INSTR_CMD, 0xc3, // Vreg1a voltage Control
97 LCD_INSTR_DAT, 0x20,
98 LCD_INSTR_CMD, 0xc4, // Vreg1b voltage Control
99 LCD_INSTR_DAT, 0x03,
100 LCD_INSTR_CMD, 0xc9, // Vreg2a voltage Control
101 LCD_INSTR_DAT, 0x2a,
102
103 LCD_INSTR_CMD, 0xf0, // SET_GAMMA1
104 LCD_INSTR_DAT, 0x4a,
105 LCD_INSTR_DAT, 0x10,
106 LCD_INSTR_DAT, 0x0a,
107 LCD_INSTR_DAT, 0x0a,
108 LCD_INSTR_DAT, 0x26,
109 LCD_INSTR_DAT, 0x39,
110
111 LCD_INSTR_CMD, 0xf2, // SET_GAMMA3
112 LCD_INSTR_DAT, 0x4a,
113 LCD_INSTR_DAT, 0x10,
114 LCD_INSTR_DAT, 0x0a,
115 LCD_INSTR_DAT, 0x0a,
116 LCD_INSTR_DAT, 0x26,
117 LCD_INSTR_DAT, 0x39,
118
119 LCD_INSTR_CMD, 0xf1, // SET_GAMMA2
120 LCD_INSTR_DAT, 0x50,
121 LCD_INSTR_DAT, 0x8f,
122 LCD_INSTR_DAT, 0xaf,
123 LCD_INSTR_DAT, 0x3b,
124 LCD_INSTR_DAT, 0x3f,
125 LCD_INSTR_DAT, 0x7f,
126
127 LCD_INSTR_CMD, 0xf3, // SET_GAMMA4
128 LCD_INSTR_DAT, 0x50,
129 LCD_INSTR_DAT, 0x8f,
130 LCD_INSTR_DAT, 0xaf,
131 LCD_INSTR_DAT, 0x3b,
132 LCD_INSTR_DAT, 0x3f,
133 LCD_INSTR_DAT, 0x7f,
134
135 LCD_INSTR_CMD, 0xba, // TE Control
136 LCD_INSTR_DAT, 0x0a,
137
138#ifdef BOOTLOADER
139 LCD_INSTR_CMD, 0x35, // Tearing Effect Line ON
140 LCD_INSTR_DAT, 0x00,
141#endif
142
143 LCD_INSTR_CMD, 0x21, /* Invert */
144
145 /* Lock EXTC? */
146 LCD_INSTR_CMD, 0xfe, // Inter Register Enable1
147 LCD_INSTR_CMD, 0xee,
148
149 /* Exit Sleep */
150 LCD_INSTR_CMD, 0x11,
151 LCD_INSTR_UDELAY, 120000,
152 /* Display On */
153 LCD_INSTR_CMD, 0x29,
154 LCD_INSTR_UDELAY, 20000,
155 LCD_INSTR_END,
156};
157
158/* Original Display / Hifiwalker -1.5 / Surfans -2.7 */
159static const uint32_t erosqnative_lcd_cmd_enable_v1[] = {
33 /* Set EXTC? */ 160 /* Set EXTC? */
34 LCD_INSTR_CMD, 0xc8, 161 LCD_INSTR_CMD, 0xc8,
35 LCD_INSTR_DAT, 0xff, 162 LCD_INSTR_DAT, 0xff,
@@ -179,7 +306,22 @@ void lcd_tgt_enable(bool enable)
179 mdelay(5); 306 mdelay(5);
180 gpio_set_level(GPIO_LCD_CE, 0); 307 gpio_set_level(GPIO_LCD_CE, 0);
181 308
182 lcd_exec_commands(&erosqnative_lcd_cmd_enable[0]); 309#ifdef BOOTLOADER
310# if EROSQN_VER == 3
311 lcd_exec_commands(&erosqnative_lcd_cmd_enable_v3[0]);
312# else
313 lcd_exec_commands(&erosqnative_lcd_cmd_enable_v1[0]);
314# endif
315#else
316 if (device_data.lcd_version == 3)
317 {
318 lcd_exec_commands(&erosqnative_lcd_cmd_enable_v3[0]);
319 }
320 else
321 {
322 lcd_exec_commands(&erosqnative_lcd_cmd_enable_v1[0]);
323 }
324#endif
183 } else { 325 } else {
184 /* doesn't flash white if we don't do anything... */ 326 /* doesn't flash white if we don't do anything... */
185#if 0 327#if 0
diff --git a/firmware/target/mips/ingenic_x1000/system-x1000.c b/firmware/target/mips/ingenic_x1000/system-x1000.c
index 64890a6c3a..1c850736b6 100644
--- a/firmware/target/mips/ingenic_x1000/system-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/system-x1000.c
@@ -20,6 +20,7 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22#include "system.h" 22#include "system.h"
23#include <string.h>
23#include "mips.h" 24#include "mips.h"
24#include "panic.h" 25#include "panic.h"
25#include "button.h" 26#include "button.h"
@@ -36,6 +37,10 @@
36#include "x1000/msc.h" 37#include "x1000/msc.h"
37#include "x1000/aic.h" 38#include "x1000/aic.h"
38 39
40#if defined(HAVE_DEVICEDATA)
41#include "devicedata.h"
42#endif
43
39#ifdef X1000_CPUIDLE_STATS 44#ifdef X1000_CPUIDLE_STATS
40int __cpu_idle_avg = 0; 45int __cpu_idle_avg = 0;
41int __cpu_idle_cur = 0; 46int __cpu_idle_cur = 0;
@@ -81,6 +86,20 @@ void system_early_init(void)
81 clk_init(); 86 clk_init();
82} 87}
83 88
89#if defined (HAVE_DEVICEDATA) && defined(EROS_QN)
90void fill_devicedata(struct device_data_t *data)
91{
92#ifdef BOOTLOADER
93 memset(data->payload, 0xff, data->length);
94 data->lcd_version = EROSQN_VER;
95#else
96 uint8_t lcd_version = device_data.lcd_version;
97 memset(data->payload, 0xff, data->length);
98 data->lcd_version = lcd_version;
99#endif
100}
101#endif
102
84/* First thing called from Rockbox main() */ 103/* First thing called from Rockbox main() */
85void system_init(void) 104void system_init(void)
86{ 105{
diff --git a/firmware/target/mips/ingenic_x1000/x1000boot.make b/firmware/target/mips/ingenic_x1000/x1000boot.make
index 0bdf5cf7b4..7a861b0a3d 100644
--- a/firmware/target/mips/ingenic_x1000/x1000boot.make
+++ b/firmware/target/mips/ingenic_x1000/x1000boot.make
@@ -12,7 +12,7 @@ include $(ROOTDIR)/lib/microtar/microtar.make
12INCLUDES += -I$(APPSDIR) 12INCLUDES += -I$(APPSDIR)
13SRC += $(call preprocess, $(APPSDIR)/SOURCES) 13SRC += $(call preprocess, $(APPSDIR)/SOURCES)
14 14
15LDSDEP := $(FIRMDIR)/export/cpu.h $(FIRMDIR)/export/config/$(MODELNAME).h 15LDSDEP := $(FIRMDIR)/export/cpu.h $(FIRMDIR)/export/config.h
16 16
17BOOTLDS := $(FIRMDIR)/target/$(CPU)/$(MANUFACTURER)/boot.lds 17BOOTLDS := $(FIRMDIR)/target/$(CPU)/$(MANUFACTURER)/boot.lds
18BOOTLINK := $(BUILDDIR)/boot.link 18BOOTLINK := $(BUILDDIR)/boot.link
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index b4a117d959..92cdeb9a59 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -119,16 +119,13 @@ static const struct usb_qualifier_descriptor __attribute__((aligned(2)))
119 .bNumConfigurations = 1 119 .bNumConfigurations = 1
120}; 120};
121 121
122static const struct usb_string_descriptor __attribute__((aligned(2))) 122static const struct usb_string_descriptor usb_string_iManufacturer =
123 usb_string_iManufacturer =
124USB_STRING_INITIALIZER(u"Rockbox.org"); 123USB_STRING_INITIALIZER(u"Rockbox.org");
125 124
126static const struct usb_string_descriptor __attribute__((aligned(2))) 125static const struct usb_string_descriptor usb_string_iProduct =
127 usb_string_iProduct =
128USB_STRING_INITIALIZER(u"Rockbox media player"); 126USB_STRING_INITIALIZER(u"Rockbox media player");
129 127
130static struct usb_string_descriptor __attribute__((aligned(2))) 128static struct usb_string_descriptor usb_string_iSerial =
131 usb_string_iSerial =
132USB_STRING_INITIALIZER(u"00000000000000000000000000000000000000000"); 129USB_STRING_INITIALIZER(u"00000000000000000000000000000000000000000");
133 130
134/* Generic for all targets */ 131/* Generic for all targets */
@@ -523,11 +520,11 @@ void usb_core_hotswap_event(int volume, bool inserted)
523static void usb_core_set_serial_function_id(void) 520static void usb_core_set_serial_function_id(void)
524{ 521{
525 int i, id = 0; 522 int i, id = 0;
526 523
527 for(i = 0; i < USB_NUM_DRIVERS; i++) 524 for(i = 0; i < USB_NUM_DRIVERS; i++)
528 if(drivers[i].enabled) 525 if(drivers[i].enabled)
529 id |= 1 << i; 526 id |= 1 << i;
530 527
531 usb_string_iSerial.wString[0] = hex[id]; 528 usb_string_iSerial.wString[0] = hex[id];
532} 529}
533 530
@@ -856,10 +853,10 @@ static void request_handler_endpoint_drivers(struct usb_ctrlrequest* req, void*
856 if(EP_NUM(req->wIndex) < USB_NUM_ENDPOINTS) 853 if(EP_NUM(req->wIndex) < USB_NUM_ENDPOINTS)
857 control_handler = 854 control_handler =
858 ep_data[EP_NUM(req->wIndex)].control_handler[EP_DIR(req->wIndex)]; 855 ep_data[EP_NUM(req->wIndex)].control_handler[EP_DIR(req->wIndex)];
859 856
860 if(control_handler) 857 if(control_handler)
861 handled = control_handler(req, reqdata, response_data); 858 handled = control_handler(req, reqdata, response_data);
862 859
863 if(!handled) { 860 if(!handled) {
864 /* nope. flag error */ 861 /* nope. flag error */
865 logf("usb bad req %d", req->bRequest); 862 logf("usb bad req %d", req->bRequest);
diff --git a/firmware/usbstack/usb_storage.c b/firmware/usbstack/usb_storage.c
index e226c15f99..617988b19f 100644
--- a/firmware/usbstack/usb_storage.c
+++ b/firmware/usbstack/usb_storage.c
@@ -106,8 +106,9 @@
106#define SCSI_MODE_SENSE_10 0x5a 106#define SCSI_MODE_SENSE_10 0x5a
107#define SCSI_REQUEST_SENSE 0x03 107#define SCSI_REQUEST_SENSE 0x03
108#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e 108#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1e
109#define SCSI_READ_CAPACITY 0x25 109#define SCSI_READ_CAPACITY_10 0x25
110#define SCSI_READ_FORMAT_CAPACITY 0x23 110#define SCSI_READ_CAPACITY_16 0x9e
111#define USB_UFI_READ_FORMAT_CAPACITY 0x23
111#define SCSI_READ_10 0x28 112#define SCSI_READ_10 0x28
112#define SCSI_WRITE_10 0x2a 113#define SCSI_WRITE_10 0x2a
113#define SCSI_START_STOP_UNIT 0x1b 114#define SCSI_START_STOP_UNIT 0x1b
@@ -248,9 +249,16 @@ struct command_status_wrapper {
248 unsigned char status; 249 unsigned char status;
249} __attribute__ ((packed)); 250} __attribute__ ((packed));
250 251
251struct capacity { 252struct capacity_10 {
252 unsigned int block_count; 253 unsigned char block_count[4];
253 unsigned int block_size; 254 unsigned char block_size[4];
255} __attribute__ ((packed));
256
257struct capacity_16 {
258 unsigned char block_count[8];
259 unsigned char block_size[4];
260 unsigned char flags[2];
261 unsigned char lowest_aligned_lba[2];
254} __attribute__ ((packed)); 262} __attribute__ ((packed));
255 263
256struct format_capacity { 264struct format_capacity {
@@ -263,7 +271,8 @@ struct format_capacity {
263static union { 271static union {
264 unsigned char* transfer_buffer; 272 unsigned char* transfer_buffer;
265 struct inquiry_data* inquiry; 273 struct inquiry_data* inquiry;
266 struct capacity* capacity_data; 274 struct capacity_10* capacity_data_10;
275 struct capacity_16* capacity_data_16;
267 struct format_capacity* format_capacity_data; 276 struct format_capacity* format_capacity_data;
268 struct sense_data *sense_data; 277 struct sense_data *sense_data;
269 struct mode_sense_data_6 *ms_data_6; 278 struct mode_sense_data_6 *ms_data_6;
@@ -278,8 +287,8 @@ static char *cbw_buffer;
278static struct { 287static struct {
279 sector_t sector; 288 sector_t sector;
280 unsigned int count; 289 unsigned int count;
281 unsigned int orig_count;
282 unsigned int cur_cmd; 290 unsigned int cur_cmd;
291 unsigned int block_size;
283 unsigned int tag; 292 unsigned int tag;
284 unsigned int lun; 293 unsigned int lun;
285 unsigned char *data[2]; 294 unsigned char *data[2];
@@ -501,6 +510,7 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
501#endif 510#endif
502 511
503 logf("transfer result for ep %d/%d %X %d", ep,dir,status, length); 512 logf("transfer result for ep %d/%d %X %d", ep,dir,status, length);
513
504 switch(state) { 514 switch(state) {
505 case RECEIVING_BLOCKS: 515 case RECEIVING_BLOCKS:
506 if(dir==USB_DIR_IN) { 516 if(dir==USB_DIR_IN) {
@@ -508,37 +518,37 @@ void usb_storage_transfer_complete(int ep,int dir,int status,int length)
508 } 518 }
509 logf("scsi write %llu %d", cur_cmd.sector, cur_cmd.count); 519 logf("scsi write %llu %d", cur_cmd.sector, cur_cmd.count);
510 if(status==0) { 520 if(status==0) {
511 if((unsigned int)length!=(SECTOR_SIZE* cur_cmd.count) 521 if((unsigned int)length!=(cur_cmd.block_size* cur_cmd.count)
512 && (unsigned int)length!=WRITE_BUFFER_SIZE) { 522 && (unsigned int)length!=WRITE_BUFFER_SIZE) {
513 logf("unexpected length :%d",length); 523 logf("unexpected length :%d",length);
514 break; 524 break;
515 } 525 }
516 526
517 sector_t next_sector = cur_cmd.sector + 527 sector_t next_sector = cur_cmd.sector +
518 (WRITE_BUFFER_SIZE/SECTOR_SIZE); 528 (WRITE_BUFFER_SIZE/cur_cmd.block_size);
519 unsigned int next_count = cur_cmd.count - 529 unsigned int next_count = cur_cmd.count -
520 MIN(cur_cmd.count,WRITE_BUFFER_SIZE/SECTOR_SIZE); 530 MIN(cur_cmd.count,WRITE_BUFFER_SIZE/cur_cmd.block_size);
521 int next_select = !cur_cmd.data_select; 531 int next_select = !cur_cmd.data_select;
522 532
523 if(next_count!=0) { 533 if(next_count!=0) {
524 /* Ask the host to send more, to the other buffer */ 534 /* Ask the host to send more, to the other buffer */
525 receive_block_data(cur_cmd.data[next_select], 535 receive_block_data(cur_cmd.data[next_select],
526 MIN(WRITE_BUFFER_SIZE,next_count*SECTOR_SIZE)); 536 MIN(WRITE_BUFFER_SIZE,next_count*cur_cmd.block_size));
527 } 537 }
528 538
529 /* Now write the data that just came in, while the host is 539 /* Now write the data that just came in, while the host is
530 sending the next bit */ 540 sending the next bit */
531#ifdef USB_USE_RAMDISK 541#ifdef USB_USE_RAMDISK
532 memcpy(ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 542 memcpy(ramdisk_buffer + cur_cmd.sector*cur_cmd.block_size,
533 cur_cmd.data[cur_cmd.data_select], 543 cur_cmd.data[cur_cmd.data_select],
534 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 544 MIN(WRITE_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count)*cur_cmd.block_size);
535#else 545#else
536 int result = USBSTOR_WRITE_SECTORS_FILTER(); 546 int result = USBSTOR_WRITE_SECTORS_FILTER();
537 547
538 if (result == 0) { 548 if (result == 0) {
539 result = storage_write_sectors(IF_MD(cur_cmd.lun,) 549 result = storage_write_sectors(IF_MD(cur_cmd.lun,)
540 cur_cmd.sector, 550 cur_cmd.sector,
541 MIN(WRITE_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 551 MIN(WRITE_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count),
542 cur_cmd.data[cur_cmd.data_select]); 552 cur_cmd.data[cur_cmd.data_select]);
543 } 553 }
544 554
@@ -712,25 +722,25 @@ static void send_and_read_next(void)
712 cur_cmd.last_result = result; 722 cur_cmd.last_result = result;
713 723
714 send_block_data(cur_cmd.data[cur_cmd.data_select], 724 send_block_data(cur_cmd.data[cur_cmd.data_select],
715 MIN(READ_BUFFER_SIZE,cur_cmd.count*SECTOR_SIZE)); 725 MIN(READ_BUFFER_SIZE,cur_cmd.count*cur_cmd.block_size));
716 726
717 /* Switch buffers for the next one */ 727 /* Switch buffers for the next one */
718 cur_cmd.data_select=!cur_cmd.data_select; 728 cur_cmd.data_select=!cur_cmd.data_select;
719 729
720 cur_cmd.sector+=(READ_BUFFER_SIZE/SECTOR_SIZE); 730 cur_cmd.sector+=(READ_BUFFER_SIZE/cur_cmd.block_size);
721 cur_cmd.count-=MIN(cur_cmd.count,READ_BUFFER_SIZE/SECTOR_SIZE); 731 cur_cmd.count-=MIN(cur_cmd.count,READ_BUFFER_SIZE/cur_cmd.block_size);
722 732
723 if(cur_cmd.count!=0) { 733 if(cur_cmd.count!=0) {
724 /* already read the next bit, so we can send it out immediately when the 734 /* already read the next bit, so we can send it out immediately when the
725 * current transfer completes. */ 735 * current transfer completes. */
726#ifdef USB_USE_RAMDISK 736#ifdef USB_USE_RAMDISK
727 memcpy(cur_cmd.data[cur_cmd.data_select], 737 memcpy(cur_cmd.data[cur_cmd.data_select],
728 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 738 ramdisk_buffer + cur_cmd.sector*cur_cmd.block_size,
729 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count)*SECTOR_SIZE); 739 MIN(READ_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count)*cur_cmd.block_size);
730#else 740#else
731 result = storage_read_sectors(IF_MD(cur_cmd.lun,) 741 result = storage_read_sectors(IF_MD(cur_cmd.lun,)
732 cur_cmd.sector, 742 cur_cmd.sector,
733 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 743 MIN(READ_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count),
734 cur_cmd.data[cur_cmd.data_select]); 744 cur_cmd.data[cur_cmd.data_select]);
735 if(cur_cmd.last_result == 0) 745 if(cur_cmd.last_result == 0)
736 cur_cmd.last_result = result; 746 cur_cmd.last_result = result;
@@ -748,7 +758,6 @@ static void handle_scsi(struct command_block_wrapper* cbw)
748 unsigned int block_size; 758 unsigned int block_size;
749 bool lun_present=true; 759 bool lun_present=true;
750 unsigned char lun = cbw->lun; 760 unsigned char lun = cbw->lun;
751 unsigned int block_size_mult = 1;
752 761
753 if(letoh32(cbw->signature) != CBW_SIGNATURE) { 762 if(letoh32(cbw->signature) != CBW_SIGNATURE) {
754 logf("ums: bad cbw signature (%x)", cbw->signature); 763 logf("ums: bad cbw signature (%x)", cbw->signature);
@@ -783,10 +792,14 @@ static void handle_scsi(struct command_block_wrapper* cbw)
783 if(ejected[lun]) 792 if(ejected[lun])
784 lun_present = false; 793 lun_present = false;
785 794
795 unsigned int block_size_mult = 1; /* Number of LOGICAL storage device blocks in each USB block */
786#ifdef MAX_LOG_SECTOR_SIZE 796#ifdef MAX_LOG_SECTOR_SIZE
787 block_size_mult = disk_get_sector_multiplier(IF_MD(lun)); 797 block_size_mult = disk_get_sector_multiplier(IF_MD(lun));
788#endif 798#endif
789 799
800 uint32_t bsize = block_size*block_size_mult;
801 sector_t bcount = block_count/block_size_mult;
802
790 cur_cmd.tag = cbw->tag; 803 cur_cmd.tag = cbw->tag;
791 cur_cmd.lun = lun; 804 cur_cmd.lun = lun;
792 cur_cmd.cur_cmd = cbw->command_block[0]; 805 cur_cmd.cur_cmd = cbw->command_block[0];
@@ -887,31 +900,33 @@ static void handle_scsi(struct command_block_wrapper* cbw)
887 htobe16(sizeof(struct mode_sense_bdesc_longlba)); 900 htobe16(sizeof(struct mode_sense_bdesc_longlba));
888 901
889 memset(tb.ms_data_10->block_descriptor.reserved,0,4); 902 memset(tb.ms_data_10->block_descriptor.reserved,0,4);
890 memset(tb.ms_data_10->block_descriptor.num_blocks,0,8);
891 903
892#ifdef STORAGE_64BIT_SECTOR 904#ifdef STORAGE_64BIT_SECTOR
893 tb.ms_data_10->block_descriptor.num_blocks[2] = 905 tb.ms_data_10->block_descriptor.num_blocks[2] =
894 ((block_count/block_size_mult) & 0xff00000000ULL)>>40; 906 (bcount & 0xff00000000ULL)>>40;
895 tb.ms_data_10->block_descriptor.num_blocks[3] = 907 tb.ms_data_10->block_descriptor.num_blocks[3] =
896 ((block_count/block_size_mult) & 0x00ff000000ULL)>>32; 908 (bcount & 0x00ff000000ULL)>>32;
909#else
910 tb.ms_data_10->block_descriptor.num_blocks[2] = 0;
911 tb.ms_data_10->block_descriptor.num_blocks[3] = 0;
897#endif 912#endif
898 tb.ms_data_10->block_descriptor.num_blocks[4] = 913 tb.ms_data_10->block_descriptor.num_blocks[4] =
899 ((block_count/block_size_mult) & 0xff000000)>>24; 914 (bcount & 0xff000000)>>24;
900 tb.ms_data_10->block_descriptor.num_blocks[5] = 915 tb.ms_data_10->block_descriptor.num_blocks[5] =
901 ((block_count/block_size_mult) & 0x00ff0000)>>16; 916 (bcount & 0x00ff0000)>>16;
902 tb.ms_data_10->block_descriptor.num_blocks[6] = 917 tb.ms_data_10->block_descriptor.num_blocks[6] =
903 ((block_count/block_size_mult) & 0x0000ff00)>>8; 918 (bcount & 0x0000ff00)>>8;
904 tb.ms_data_10->block_descriptor.num_blocks[7] = 919 tb.ms_data_10->block_descriptor.num_blocks[7] =
905 ((block_count/block_size_mult) & 0x000000ff); 920 (bcount & 0x000000ff);
906 921
907 tb.ms_data_10->block_descriptor.block_size[0] = 922 tb.ms_data_10->block_descriptor.block_size[0] =
908 ((block_size*block_size_mult) & 0xff000000)>>24; 923 (bsize & 0xff000000)>>24;
909 tb.ms_data_10->block_descriptor.block_size[1] = 924 tb.ms_data_10->block_descriptor.block_size[1] =
910 ((block_size*block_size_mult) & 0x00ff0000)>>16; 925 (bsize & 0x00ff0000)>>16;
911 tb.ms_data_10->block_descriptor.block_size[2] = 926 tb.ms_data_10->block_descriptor.block_size[2] =
912 ((block_size*block_size_mult) & 0x0000ff00)>>8; 927 (bsize & 0x0000ff00)>>8;
913 tb.ms_data_10->block_descriptor.block_size[3] = 928 tb.ms_data_10->block_descriptor.block_size[3] =
914 ((block_size*block_size_mult) & 0x000000ff); 929 (bsize & 0x000000ff);
915 send_command_result(tb.ms_data_10, 930 send_command_result(tb.ms_data_10,
916 MIN(sizeof(struct mode_sense_data_10), length)); 931 MIN(sizeof(struct mode_sense_data_10), length));
917 break; 932 break;
@@ -947,25 +962,24 @@ static void handle_scsi(struct command_block_wrapper* cbw)
947 sizeof(struct mode_sense_bdesc_shortlba); 962 sizeof(struct mode_sense_bdesc_shortlba);
948 tb.ms_data_6->block_descriptor.density_code = 0; 963 tb.ms_data_6->block_descriptor.density_code = 0;
949 tb.ms_data_6->block_descriptor.reserved = 0; 964 tb.ms_data_6->block_descriptor.reserved = 0;
950 if(block_count/block_size_mult > 0xffffff) { 965 if(bcount > 0xffffff) {
951 tb.ms_data_6->block_descriptor.num_blocks[0] = 0xff; 966 tb.ms_data_6->block_descriptor.num_blocks[0] = 0xff;
952 tb.ms_data_6->block_descriptor.num_blocks[1] = 0xff; 967 tb.ms_data_6->block_descriptor.num_blocks[1] = 0xff;
953 tb.ms_data_6->block_descriptor.num_blocks[2] = 0xff; 968 tb.ms_data_6->block_descriptor.num_blocks[2] = 0xff;
954 } 969 } else {
955 else {
956 tb.ms_data_6->block_descriptor.num_blocks[0] = 970 tb.ms_data_6->block_descriptor.num_blocks[0] =
957 ((block_count/block_size_mult) & 0xff0000)>>16; 971 (bcount & 0xff0000)>>16;
958 tb.ms_data_6->block_descriptor.num_blocks[1] = 972 tb.ms_data_6->block_descriptor.num_blocks[1] =
959 ((block_count/block_size_mult) & 0x00ff00)>>8; 973 (bcount & 0x00ff00)>>8;
960 tb.ms_data_6->block_descriptor.num_blocks[2] = 974 tb.ms_data_6->block_descriptor.num_blocks[2] =
961 ((block_count/block_size_mult) & 0x0000ff); 975 (bcount & 0x0000ff);
962 } 976 }
963 tb.ms_data_6->block_descriptor.block_size[0] = 977 tb.ms_data_6->block_descriptor.block_size[0] =
964 ((block_size*block_size_mult) & 0xff0000)>>16; 978 (bsize & 0xff0000)>>16;
965 tb.ms_data_6->block_descriptor.block_size[1] = 979 tb.ms_data_6->block_descriptor.block_size[1] =
966 ((block_size*block_size_mult) & 0x00ff00)>>8; 980 (bsize & 0x00ff00)>>8;
967 tb.ms_data_6->block_descriptor.block_size[2] = 981 tb.ms_data_6->block_descriptor.block_size[2] =
968 ((block_size*block_size_mult) & 0x0000ff); 982 (bsize & 0x0000ff);
969 send_command_result(tb.ms_data_6, 983 send_command_result(tb.ms_data_6,
970 MIN(sizeof(struct mode_sense_data_6), length)); 984 MIN(sizeof(struct mode_sense_data_6), length));
971 break; 985 break;
@@ -1009,15 +1023,16 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1009 send_csw(UMS_STATUS_GOOD); 1023 send_csw(UMS_STATUS_GOOD);
1010 break; 1024 break;
1011 1025
1012 case SCSI_READ_FORMAT_CAPACITY: { 1026 case USB_UFI_READ_FORMAT_CAPACITY: {
1013 logf("scsi read_format_capacity %d",lun); 1027 logf("usb ufi read_format_capacity %d",lun);
1014 if(lun_present) { 1028 if(lun_present) {
1015 tb.format_capacity_data->following_length=htobe32(8); 1029 tb.format_capacity_data->following_length=htobe32(8);
1016 /* "block count" actually means "number of last block" */ 1030 /* "block count" actually means "number of last block" */
1017 tb.format_capacity_data->block_count = 1031 if (bcount > 0xffffffff)
1018 htobe32(block_count/block_size_mult - 1); 1032 tb.format_capacity_data->block_count = 0xffffffff;
1019 tb.format_capacity_data->block_size = 1033 else
1020 htobe32(block_size*block_size_mult); 1034 tb.format_capacity_data->block_count = htobe32(bcount - 1);
1035 tb.format_capacity_data->block_size = htobe32(bsize);
1021 tb.format_capacity_data->block_size |= 1036 tb.format_capacity_data->block_size |=
1022 htobe32(SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA); 1037 htobe32(SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA);
1023 1038
@@ -1033,20 +1048,30 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1033 break; 1048 break;
1034 } 1049 }
1035 1050
1036 case SCSI_READ_CAPACITY: { 1051 case SCSI_READ_CAPACITY_10: {
1037 logf("scsi read_capacity %d",lun); 1052 logf("scsi read_capacity10 %d",lun);
1038 1053
1039 if(lun_present) { 1054 if(lun_present) {
1040 /* "block count" actually means "number of last block" */ 1055 /* "block count" actually means "number of last block" */
1041 tb.capacity_data->block_count = 1056 if (bcount >= 0xffffffff) {
1042 htobe32(block_count/block_size_mult - 1); 1057 tb.capacity_data_10->block_count[0] = 0xff;
1043 tb.capacity_data->block_size = 1058 tb.capacity_data_10->block_count[1] = 0xff;
1044 htobe32(block_size*block_size_mult); 1059 tb.capacity_data_10->block_count[2] = 0xff;
1045 1060 tb.capacity_data_10->block_count[3] = 0xff;
1046 send_command_result(tb.capacity_data, 1061 } else {
1047 MIN(sizeof(struct capacity), length)); 1062 tb.capacity_data_10->block_count[0] = ((bcount-1) & 0xff000000)>>24;
1048 } 1063 tb.capacity_data_10->block_count[1] = ((bcount-1) & 0x00ff0000)>>16;
1049 else { 1064 tb.capacity_data_10->block_count[2] = ((bcount-1) & 0x0000ff00)>>8;
1065 tb.capacity_data_10->block_count[3] = ((bcount-1) & 0x000000ff);
1066 }
1067 tb.capacity_data_10->block_size[0] = (bsize & 0xff000000)>>24;
1068 tb.capacity_data_10->block_size[1] = (bsize & 0x00ff0000)>>16;
1069 tb.capacity_data_10->block_size[2] = (bsize & 0x0000ff00)>>8;
1070 tb.capacity_data_10->block_size[3] = (bsize & 0x000000ff);
1071
1072 send_command_result(tb.capacity_data_10,
1073 MIN(sizeof(struct capacity_10), length));
1074 } else {
1050 send_command_failed_result(); 1075 send_command_failed_result();
1051 cur_sense_data.sense_key=SENSE_NOT_READY; 1076 cur_sense_data.sense_key=SENSE_NOT_READY;
1052 cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT; 1077 cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
@@ -1054,7 +1079,59 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1054 } 1079 }
1055 break; 1080 break;
1056 } 1081 }
1082 case SCSI_READ_CAPACITY_16: {
1083 logf("scsi read_capacity16 %d",lun);
1057 1084
1085 if(lun_present) {
1086 /* "block count" actually means "number of last block" */
1087#ifdef STORAGE_64BIT_SECTOR
1088 tb.capacity_data_16->block_count[2] =
1089 ((bcount-1) & 0xff00000000ULL)>>40;
1090 tb.capacity_data_16->block_count[3] =
1091 ((bcount-1) & 0x00ff000000ULL)>>32;
1092#else
1093 tb.capacity_data_16->block_count[2] = 0;
1094 tb.capacity_data_16->block_count[3] = 0;
1095#endif
1096 tb.capacity_data_16->block_count[4] =
1097 ((bcount-1) & 0xff000000)>>24;
1098 tb.capacity_data_16->block_count[5] =
1099 ((bcount-1) & 0x00ff0000)>>16;
1100 tb.capacity_data_16->block_count[6] =
1101 ((bcount-1) & 0x0000ff00)>>8;
1102 tb.capacity_data_16->block_count[7] =
1103 ((bcount-1) & 0x000000ff);
1104
1105 tb.ms_data_10->block_descriptor.block_size[0] =
1106 (bsize & 0xff000000)>>24;
1107 tb.ms_data_10->block_descriptor.block_size[1] =
1108 (bsize & 0x00ff0000)>>16;
1109 tb.ms_data_10->block_descriptor.block_size[2] =
1110 (bsize & 0x0000ff00)>>8;
1111 tb.ms_data_10->block_descriptor.block_size[3] =
1112 (bsize & 0x000000ff);
1113
1114 tb.capacity_data_16->block_size[0] = (bsize & 0xff000000)>>24;
1115 tb.capacity_data_16->block_size[1] = (bsize & 0x00ff0000)>>16;
1116 tb.capacity_data_16->block_size[2] = (bsize & 0x0000ff00)>>8;
1117 tb.capacity_data_16->block_size[3] = (bsize & 0x000000ff);
1118
1119 uint16_t flags = htobe16((1<<12) | find_first_set_bit(block_size_mult));
1120 memcpy(tb.capacity_data_16->flags, &flags, sizeof(flags));
1121
1122 tb.capacity_data_16->lowest_aligned_lba[0] = 0;
1123 tb.capacity_data_16->lowest_aligned_lba[1] = 1;
1124
1125 send_command_result(tb.capacity_data_16,
1126 MIN(sizeof(struct capacity_16), length));
1127 } else {
1128 send_command_failed_result();
1129 cur_sense_data.sense_key=SENSE_NOT_READY;
1130 cur_sense_data.asc=ASC_MEDIUM_NOT_PRESENT;
1131 cur_sense_data.ascq=0;
1132 }
1133 break;
1134 }
1058 case SCSI_READ_10: 1135 case SCSI_READ_10:
1059 logf("scsi read10 %d",lun); 1136 logf("scsi read10 %d",lun);
1060 if(!lun_present) { 1137 if(!lun_present) {
@@ -1075,7 +1152,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1075 cur_cmd.count = block_size_mult * 1152 cur_cmd.count = block_size_mult *
1076 (cbw->command_block[7] << 8 | 1153 (cbw->command_block[7] << 8 |
1077 cbw->command_block[8]); 1154 cbw->command_block[8]);
1078 cur_cmd.orig_count = cur_cmd.count; 1155 cur_cmd.block_size = block_size;
1079 1156
1080 logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count); 1157 logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count);
1081 1158
@@ -1088,12 +1165,12 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1088 else { 1165 else {
1089#ifdef USB_USE_RAMDISK 1166#ifdef USB_USE_RAMDISK
1090 memcpy(cur_cmd.data[cur_cmd.data_select], 1167 memcpy(cur_cmd.data[cur_cmd.data_select],
1091 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 1168 ramdisk_buffer + cur_cmd.sector*cur_cmd.block_size,
1092 MIN(READ_BUFFER_SIZE/SECTOR_SIZE,cur_cmd.count)*SECTOR_SIZE); 1169 MIN(READ_BUFFER_SIZE/cur_cmd.block_size,cur_cmd.count)*cur_cmd.block_size);
1093#else 1170#else
1094 cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,) 1171 cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,)
1095 cur_cmd.sector, 1172 cur_cmd.sector,
1096 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 1173 MIN(READ_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count),
1097 cur_cmd.data[cur_cmd.data_select]); 1174 cur_cmd.data[cur_cmd.data_select]);
1098#endif 1175#endif
1099 send_and_read_next(); 1176 send_and_read_next();
@@ -1126,7 +1203,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1126 cbw->command_block[11] << 16 | 1203 cbw->command_block[11] << 16 |
1127 cbw->command_block[12] << 8 | 1204 cbw->command_block[12] << 8 |
1128 cbw->command_block[13]); 1205 cbw->command_block[13]);
1129 cur_cmd.orig_count = cur_cmd.count; 1206 cur_cmd.block_size = block_size;
1130 1207
1131 logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count); 1208 logf("scsi read %llu %d", cur_cmd.sector, cur_cmd.count);
1132 1209
@@ -1139,12 +1216,12 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1139 else { 1216 else {
1140#ifdef USB_USE_RAMDISK 1217#ifdef USB_USE_RAMDISK
1141 memcpy(cur_cmd.data[cur_cmd.data_select], 1218 memcpy(cur_cmd.data[cur_cmd.data_select],
1142 ramdisk_buffer + cur_cmd.sector*SECTOR_SIZE, 1219 ramdisk_buffer + cur_cmd.sector*cur_cmd.block_size,
1143 MIN(READ_BUFFER_SIZE/SECTOR_SIZE,cur_cmd.count)*SECTOR_SIZE); 1220 MIN(READ_BUFFER_SIZE/cur_cmd.block_size,cur_cmd.count)*cur_cmd.block_size);
1144#else 1221#else
1145 cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,) 1222 cur_cmd.last_result = storage_read_sectors(IF_MD(cur_cmd.lun,)
1146 cur_cmd.sector, 1223 cur_cmd.sector,
1147 MIN(READ_BUFFER_SIZE/SECTOR_SIZE, cur_cmd.count), 1224 MIN(READ_BUFFER_SIZE/cur_cmd.block_size, cur_cmd.count),
1148 cur_cmd.data[cur_cmd.data_select]); 1225 cur_cmd.data[cur_cmd.data_select]);
1149#endif 1226#endif
1150 send_and_read_next(); 1227 send_and_read_next();
@@ -1171,7 +1248,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1171 cur_cmd.count = block_size_mult * 1248 cur_cmd.count = block_size_mult *
1172 (cbw->command_block[7] << 8 | 1249 (cbw->command_block[7] << 8 |
1173 cbw->command_block[8]); 1250 cbw->command_block[8]);
1174 cur_cmd.orig_count = cur_cmd.count; 1251 cur_cmd.block_size = block_size;
1175 1252
1176 /* expect data */ 1253 /* expect data */
1177 if((cur_cmd.sector + cur_cmd.count) > block_count) { 1254 if((cur_cmd.sector + cur_cmd.count) > block_count) {
@@ -1182,7 +1259,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1182 } 1259 }
1183 else { 1260 else {
1184 receive_block_data(cur_cmd.data[0], 1261 receive_block_data(cur_cmd.data[0],
1185 MIN(WRITE_BUFFER_SIZE, cur_cmd.count*SECTOR_SIZE)); 1262 MIN(WRITE_BUFFER_SIZE, cur_cmd.count*cur_cmd.block_size));
1186 } 1263 }
1187 break; 1264 break;
1188#ifdef STORAGE_64BIT_SECTOR 1265#ifdef STORAGE_64BIT_SECTOR
@@ -1212,7 +1289,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1212 cbw->command_block[11] << 16 | 1289 cbw->command_block[11] << 16 |
1213 cbw->command_block[12] << 8 | 1290 cbw->command_block[12] << 8 |
1214 cbw->command_block[13]); 1291 cbw->command_block[13]);
1215 cur_cmd.orig_count = cur_cmd.count; 1292 cur_cmd.block_size = block_size;
1216 1293
1217 /* expect data */ 1294 /* expect data */
1218 if((cur_cmd.sector + cur_cmd.count) > block_count) { 1295 if((cur_cmd.sector + cur_cmd.count) > block_count) {
@@ -1223,7 +1300,7 @@ static void handle_scsi(struct command_block_wrapper* cbw)
1223 } 1300 }
1224 else { 1301 else {
1225 receive_block_data(cur_cmd.data[0], 1302 receive_block_data(cur_cmd.data[0],
1226 MIN(WRITE_BUFFER_SIZE, cur_cmd.count*SECTOR_SIZE)); 1303 MIN(WRITE_BUFFER_SIZE, cur_cmd.count*cur_cmd.block_size));
1227 } 1304 }
1228 break; 1305 break;
1229#endif 1306#endif