diff options
Diffstat (limited to 'firmware')
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) | ||
66 | common/devicedata.c | ||
67 | #endif | ||
68 | |||
65 | #ifdef HAVE_SDL | 69 | #ifdef HAVE_SDL |
66 | target/hosted/sdl/button-sdl.c | 70 | target/hosted/sdl/button-sdl.c |
67 | target/hosted/sdl/kernel-sdl.c | 71 | target/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 | ||
28 | void verify_device_data(void) INIT_ATTR; | ||
29 | void 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) | ||
49 | void __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 | */ | ||
62 | bool 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 |
113 | static int disk_sector_multiplier[NUM_DRIVES] = | 114 | static uint16_t disk_sector_multiplier[NUM_DRIVES] = |
114 | { [0 ... NUM_DRIVES-1] = 1 }; | 115 | { [0 ... NUM_DRIVES-1] = 1 }; |
115 | 116 | ||
116 | int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)) | 117 | int 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? | ||
130 | static uint16_t disk_log_sector_size[NUM_DRIVES] = | ||
131 | { [0 ... NUM_DRIVES-1] = SECTOR_SIZE }; /* Updated from STORAGE_INFO */ | ||
132 | int 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 | ||
149 | int 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 | |||
128 | bool disk_init(IF_MD_NONVOID(int drive)) | 156 | bool 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)) | |||
213 | reload: | 264 | reload: |
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 | |||
25 | struct 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 */ | ||
31 | static struct sector_cache_entry sector_cache STORAGE_ALIGN_ATTR; | ||
32 | static int phys_sector_mult = 1; | ||
33 | |||
34 | static 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 | |||
56 | static 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 | |||
62 | int 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 | |||
128 | int 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 | |||
205 | static 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(§or_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 | ||
91 | static int ata_state = ATA_BOOT; | 91 | static int ata_state = ATA_BOOT; |
92 | 92 | ||
93 | static struct mutex ata_mtx SHAREDBSS_ATTR; | 93 | static struct mutex ata_mutex SHAREDBSS_ATTR; |
94 | static int ata_device; /* device 0 (master) or 1 (slave) */ | 94 | static int ata_device; /* device 0 (master) or 1 (slave) */ |
95 | 95 | ||
96 | static int spinup_time = 0; | 96 | static int spinup_time = 0; |
@@ -101,8 +101,9 @@ static bool ata_led_on = false; | |||
101 | 101 | ||
102 | static long sleep_timeout = 5*HZ; | 102 | static long sleep_timeout = 5*HZ; |
103 | #ifdef HAVE_LBA48 | 103 | #ifdef HAVE_LBA48 |
104 | static bool lba48 = false; /* set for 48 bit addressing */ | 104 | static bool ata_lba48 = false; /* set for 48 bit addressing */ |
105 | #endif | 105 | #endif |
106 | static bool canflush = true; | ||
106 | 107 | ||
107 | static long last_disk_activity = -1; | 108 | static 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 | ||
112 | static sector_t total_sectors; | 113 | static sector_t total_sectors; |
113 | static int multisectors; /* number of supported multisectors */ | 114 | static int multisectors; /* number of supported multisectors */ |
114 | static unsigned short identify_info[ATA_IDENTIFY_WORDS]; | ||
115 | 115 | ||
116 | #ifdef MAX_PHYS_SECTOR_SIZE | 116 | static unsigned short identify_info[ATA_IDENTIFY_WORDS] STORAGE_ALIGN_ATTR; |
117 | |||
118 | struct 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 | ||
125 | static struct sector_cache_entry sector_cache; | ||
126 | static int phys_sector_mult = 1; | ||
127 | #endif | ||
128 | 117 | ||
129 | #ifdef HAVE_ATA_DMA | 118 | #ifdef HAVE_ATA_DMA |
130 | static int dma_mode = 0; | 119 | static 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 | ||
145 | static inline void schedule_ata_sleep(long from_now) | ||
146 | { | ||
147 | last_disk_activity = current_tick - sleep_timeout + from_now; | ||
148 | } | ||
149 | |||
150 | static inline bool ata_sleep_timed_out(void) | 134 | static 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) | |||
224 | static int ata_perform_sleep(void) | 208 | static 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 | ||
279 | int 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 | |||
290 | static ICODE_ATTR int wait_for_start_of_transfer(void) | 289 | static 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 |
594 | int ata_read_sectors(IF_MD(int drive,) | 595 | int 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 | ||
626 | static 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 | |||
648 | static 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 | |||
654 | int 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 | |||
720 | int 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 | |||
798 | static int STORAGE_INIT_ATTR check_registers(void) | 626 | static 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 | ||
846 | bool ata_disk_is_active(void) | 674 | bool ata_disk_is_active(void) |
847 | { | 675 | { |
848 | return ata_state >= ATA_SPINUP; | 676 | return (ata_state >= ATA_SPINUP); |
849 | } | 677 | } |
850 | 678 | ||
851 | void ata_sleepnow(void) | 679 | void 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 |
1071 | static int get_best_mode(unsigned short identword, int max, int modetype) | 906 | static 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(§or_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 | |||
1324 | error: | 1146 | error: |
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 | ||
63 | static int hw_init = 0; | 81 | static int hw_init = 0; |
@@ -68,6 +86,8 @@ static long int last_ps = -1; | |||
68 | 86 | ||
69 | static int muted = -1; | 87 | static int muted = -1; |
70 | 88 | ||
89 | extern int hwver; | ||
90 | |||
71 | void audiohw_mute(int mute) | 91 | void 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) | |||
154 | const int min_pcm = -740; | 181 | const int min_pcm = -740; |
155 | const int max_pcm = 0; | 182 | const int max_pcm = 0; |
156 | 183 | ||
157 | void audiohw_set_volume(int vol_l, int vol_r) | 184 | static 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 | ||
208 | static 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 | |||
232 | void 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 | |||
183 | void audiohw_set_lineout_volume(int vol_l, int vol_r) | 241 | void 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 | ||
30 | static unsigned char ramdisk[SECTOR_SIZE * NUM_SECTORS]; | 31 | static 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 | ||
191 | bool rda5802_detect(void) | 191 | bool 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 | ||
196 | void rda5802_init(void) | 210 | void 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 */ |
107 | enum ata_attr_raw_format | 107 | enum 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 */ |
214 | static inline int ata_disk_can_poweroff(void) | 212 | static 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 | ||
220 | int ata_flush(void); | ||
221 | |||
222 | #ifdef HAVE_ATA_DMA | 222 | #ifdef HAVE_ATA_DMA |
223 | /* Returns current DMA mode */ | 223 | /* Returns current DMA mode */ |
224 | int ata_get_dma_mode(void); | 224 | int 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 */ | ||
46 | struct 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 | |||
70 | void fill_devicedata(struct device_data_t *data); | ||
71 | bool write_devicedata(unsigned char* buf, int len); | ||
72 | #ifndef BOOTLOADER | ||
73 | extern struct device_data_t device_data; | ||
74 | |||
75 | void 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 | ||
85 | device_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); | |||
47 | int disk_unmount_all(void); | 47 | int disk_unmount_all(void); |
48 | int disk_unmount(int drive); | 48 | int 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 |
52 | int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)); | 52 | int disk_get_sector_multiplier(IF_MD_NONVOID(int drive)); |
53 | #endif | 53 | #endif |
54 | /* The size of the drive's smallest addressible unit */ | ||
55 | int disk_get_log_sector_size(IF_MD_NONVOID(int drive)); | ||
54 | 56 | ||
55 | bool disk_present(IF_MD_NONVOID(int drive)); | 57 | bool 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); | |||
141 | extern bool queue_in_queue_send(struct event_queue *q); | 141 | extern bool queue_in_queue_send(struct event_queue *q); |
142 | #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ | 142 | #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */ |
143 | extern bool queue_empty(const struct event_queue* q); | 143 | extern bool queue_empty(const struct event_queue* q); |
144 | extern bool queue_full(const struct event_queue* q); | ||
144 | extern bool queue_peek(struct event_queue *q, struct queue_event *ev); | 145 | extern 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 */ | ||
705 | bool queue_full(const struct event_queue* q) | ||
706 | { | ||
707 | return ((q->write - q->read) >= QUEUE_LENGTH); | ||
708 | } | ||
709 | |||
704 | void queue_clear(struct event_queue* q) | 710 | void 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 |
56 | void exit(int status); | 57 | void 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); | |||
92 | default_interrupt(INT_GPIOB); | 92 | default_interrupt(INT_GPIOB); |
93 | default_interrupt(INT_GPIOC); | 93 | default_interrupt(INT_GPIOC); |
94 | 94 | ||
95 | static const char const irqname[][9] = | 95 | static 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 */ |
70 | void imx233_clkctrl_set_frac_div(enum imx233_clock_t clk, int fracdiv); | 70 | void imx233_clkctrl_set_frac_div(enum imx233_clock_t clk, int fracdiv); |
71 | /* 0 means fractional dividor disable */ | 71 | /* 0 means fractional dividor disabled */ |
72 | int imx233_clkctrl_get_frac_div(enum imx233_clock_t clk); | 72 | int imx233_clkctrl_get_frac_div(enum imx233_clock_t clk); |
73 | void imx233_clkctrl_set_bypass(enum imx233_clock_t clk, bool bypass); | 73 | void imx233_clkctrl_set_bypass(enum imx233_clock_t clk, bool bypass); |
74 | bool imx233_clkctrl_get_bypass(enum imx233_clock_t clk); | 74 | bool 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) | |||
327 | void button_init_device(void) | 327 | void 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. */ |
187 | struct ftl_vfl_cxt_type | 187 | struct 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 */ |
531 | static void ftl_vfl_update_checksum(uint32_t bank) | 535 | static 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. */ |
542 | static uint32_t ftl_vfl_store_cxt(uint32_t bank) | 547 | static 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 **/ |
62 | static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; | 65 | static uint8_t ceata_taskfile[16] STORAGE_ALIGN_ATTR; |
63 | static uint16_t ata_identify_data[ATA_IDENTIFY_WORDS] STORAGE_ALIGN_ATTR; | 66 | static uint16_t identify_info[ATA_IDENTIFY_WORDS] STORAGE_ALIGN_ATTR; |
64 | static bool ceata; | 67 | static bool ceata; |
65 | static bool ata_lba48; | 68 | static bool ata_lba48; |
66 | static bool ata_dma; | 69 | static bool ata_dma; |
@@ -69,18 +72,18 @@ static struct mutex ata_mutex; | |||
69 | static struct semaphore ata_wakeup; | 72 | static struct semaphore ata_wakeup; |
70 | static uint32_t ata_dma_flags; | 73 | static uint32_t ata_dma_flags; |
71 | static long ata_last_activity_value = -1; | 74 | static long ata_last_activity_value = -1; |
72 | static long ata_sleep_timeout = 20 * HZ; | 75 | static long ata_sleep_timeout = 7 * HZ; |
73 | static bool ata_powered; | 76 | static bool ata_powered; |
74 | static const int ata_retries = ATA_RETRIES; | 77 | static bool canflush = true; |
75 | static const bool ata_error_srst = true; | ||
76 | static struct semaphore mmc_wakeup; | 78 | static struct semaphore mmc_wakeup; |
77 | static struct semaphore mmc_comp_wakeup; | 79 | static struct semaphore mmc_comp_wakeup; |
78 | static int spinup_time = 0; | 80 | static int spinup_time = 0; |
79 | static int dma_mode = 0; | 81 | static int dma_mode = 0; |
80 | static char aligned_buffer[SECTOR_SIZE] STORAGE_ALIGN_ATTR; | ||
81 | 82 | ||
82 | static int ata_reset(void); | 83 | static const int ata_retries = ATA_RETRIES; |
84 | static const bool ata_error_srst = true; | ||
83 | 85 | ||
86 | static int ata_reset(void); | ||
84 | 87 | ||
85 | static uint16_t ata_read_cbr(uint32_t volatile* reg) | 88 | static 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 | ||
321 | static int ceata_read_multiple_register(uint32_t addr, void* dest, uint32_t size) | 352 | static 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 | |||
343 | static int ceata_write_multiple_register(uint32_t addr, void* dest, uint32_t size) | 375 | static 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 | ||
597 | static 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 | }; | ||
610 | static int mwdmatimes[ATA_MAX_MWDMA + 1] = { | ||
611 | 0x1c175, | ||
612 | 0x7083, | ||
613 | 0x5072, | ||
614 | }; | ||
615 | |||
616 | static 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 | ||
709 | static void ata_power_down(void) | 769 | static 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 | ||
853 | static int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write) | 893 | static 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 | ||
968 | int ata_read_sectors(IF_MD(int drive,) sector_t start, int incount, | 1006 | int 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, | |||
977 | int ata_write_sectors(IF_MD(int drive,) sector_t start, int count, | 1019 | int 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 | ||
986 | void ata_spindown(int seconds) | 1033 | void 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 | ||
1070 | int 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 | |||
1022 | void ata_sleepnow(void) | 1080 | void 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 | ||
1039 | void ata_get_info(IF_MD(int drive,) struct storage_info *info) | 1120 | void 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 | ||
1048 | long ata_last_disk_activity(void) | 1135 | long 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 | ||
1129 | unsigned short* ata_get_identify(void) | 1224 | unsigned short* ata_get_identify(void) |
1130 | { | 1225 | { |
1131 | return ata_identify_data; | 1226 | return identify_info; |
1132 | } | 1227 | } |
1133 | 1228 | ||
1134 | int ata_spinup_time(void) | 1229 | int 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 | ||
1139 | int ata_get_dma_mode(void) | 1235 | int ata_get_dma_mode(void) |
1140 | { | 1236 | { |
1141 | return dma_mode; | 1237 | return dma_mode; |
1142 | } | 1238 | } |
1239 | #endif | ||
1143 | 1240 | ||
1144 | void INT_ATA(void) | 1241 | void 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 | ||
1152 | void INT_MMC(void) | 1250 | void 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 | ||
103 | static const unsigned short const irqpriority[] = | 103 | static 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 | ||
38 | static int line = 0; | 38 | static int line = 0; |
39 | 39 | ||
40 | extern int hwver; | ||
41 | |||
40 | bool dbg_hw_info(void) | 42 | bool 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 | ||
32 | const char * const sysfs_bat_voltage = | 33 | const 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 | ||
35 | const char * const sysfs_bat_capacity = | 38 | const 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 | |||
43 | const char * const sysfs_bat_status[2] = { | ||
44 | "/sys/class/power_supply/battery/status", | ||
45 | "/sys/class/power_supply/axp_battery/status", | ||
46 | }; | ||
47 | |||
48 | int hwver = 1; /* Exported */ | ||
37 | 49 | ||
38 | unsigned int erosq_power_get_battery_voltage(void) | 50 | unsigned 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) | |||
46 | unsigned int erosq_power_get_battery_capacity(void) | 63 | unsigned 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! */ | ||
77 | static long last_tick = 0; | ||
78 | static bool last_power = false; | ||
79 | |||
80 | bool 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 */ |
38 | bool alsa_has_control(const char *name); | 38 | bool alsa_has_control(const char *name); |
39 | /* find a control element ID by name, return -1 of not found or index into array */ | ||
40 | int 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 */ |
40 | int alsa_controls_find_enum(const char *name, const char *enum_name); | 42 | int 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! */ |
40 | static long last_tick = 0; | 44 | static long last_tick = 0; |
41 | static bool last_power = false; | 45 | static 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 | ||
55 | unsigned int power_input_status(void) | 60 | unsigned 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))) | ||
111 | static 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 | ||
110 | static void mouse_event(SDL_MouseButtonEvent *event, bool button_up) | 134 | static 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 | ||
216 | static bool event_handler(SDL_Event *event) | 232 | static 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 | ||
497 | void button_init_device(void) | 502 | void 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 | ||
159 | Uint32 tick_timer(Uint32 interval, void *param) | 159 | Uint32 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 | ||
142 | int lcd_get_dpi(void) | 147 | int 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 */ |
29 | extern SDL_Surface *gui_surface; | 29 | extern SDL_Surface *gui_surface; |
30 | extern SDL_Renderer *sdlRenderer; | ||
30 | 31 | ||
31 | void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width, | 32 | void 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 | ||
88 | static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len); | ||
88 | static void pcm_dma_apply_settings_nolock(void) | 89 | static 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 | ||
105 | void pcm_play_dma_start(const void *addr, size_t size) | 140 | void 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 | ||
390 | void pcm_play_dma_postinit(void) | 384 | void 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 | ||
52 | SDL_Surface *gui_surface; | 52 | SDL_Surface *gui_surface; |
53 | SDL_Window *window; | ||
54 | SDL_Renderer *sdlRenderer; | ||
53 | 55 | ||
54 | bool background = true; /* use backgrounds by default */ | 56 | bool background = true; /* use backgrounds by default */ |
55 | #ifdef HAVE_REMOTE_LCD | 57 | #ifdef HAVE_REMOTE_LCD |
@@ -72,26 +74,12 @@ bool debug_audio = false; | |||
72 | bool debug_wps = false; | 74 | bool debug_wps = false; |
73 | int wps_verbose_level = 3; | 75 | int wps_verbose_level = 3; |
74 | 76 | ||
75 | /* | 77 | static 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 | **/ | ||
84 | static 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 | **/ | ||
150 | static 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 | ||
304 | void sys_handle_argv(int argc, char *argv[]) | 316 | void 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. */ |
29 | unsigned int power_input_status(void) | 30 | unsigned 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 | ||
37 | void power_init(void) | 41 | void power_init(void) |
@@ -42,5 +46,5 @@ void power_init(void) | |||
42 | 46 | ||
43 | bool charging_state(void) | 47 | bool 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 | ||
32 | static 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 */ | ||
42 | static 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 */ | ||
159 | static 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 |
40 | int __cpu_idle_avg = 0; | 45 | int __cpu_idle_avg = 0; |
41 | int __cpu_idle_cur = 0; | 46 | int __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) | ||
90 | void 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() */ |
85 | void system_init(void) | 104 | void 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 | |||
12 | INCLUDES += -I$(APPSDIR) | 12 | INCLUDES += -I$(APPSDIR) |
13 | SRC += $(call preprocess, $(APPSDIR)/SOURCES) | 13 | SRC += $(call preprocess, $(APPSDIR)/SOURCES) |
14 | 14 | ||
15 | LDSDEP := $(FIRMDIR)/export/cpu.h $(FIRMDIR)/export/config/$(MODELNAME).h | 15 | LDSDEP := $(FIRMDIR)/export/cpu.h $(FIRMDIR)/export/config.h |
16 | 16 | ||
17 | BOOTLDS := $(FIRMDIR)/target/$(CPU)/$(MANUFACTURER)/boot.lds | 17 | BOOTLDS := $(FIRMDIR)/target/$(CPU)/$(MANUFACTURER)/boot.lds |
18 | BOOTLINK := $(BUILDDIR)/boot.link | 18 | BOOTLINK := $(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 | ||
122 | static const struct usb_string_descriptor __attribute__((aligned(2))) | 122 | static const struct usb_string_descriptor usb_string_iManufacturer = |
123 | usb_string_iManufacturer = | ||
124 | USB_STRING_INITIALIZER(u"Rockbox.org"); | 123 | USB_STRING_INITIALIZER(u"Rockbox.org"); |
125 | 124 | ||
126 | static const struct usb_string_descriptor __attribute__((aligned(2))) | 125 | static const struct usb_string_descriptor usb_string_iProduct = |
127 | usb_string_iProduct = | ||
128 | USB_STRING_INITIALIZER(u"Rockbox media player"); | 126 | USB_STRING_INITIALIZER(u"Rockbox media player"); |
129 | 127 | ||
130 | static struct usb_string_descriptor __attribute__((aligned(2))) | 128 | static struct usb_string_descriptor usb_string_iSerial = |
131 | usb_string_iSerial = | ||
132 | USB_STRING_INITIALIZER(u"00000000000000000000000000000000000000000"); | 129 | USB_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) | |||
523 | static void usb_core_set_serial_function_id(void) | 520 | static 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 | ||
251 | struct capacity { | 252 | struct 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 | |||
257 | struct 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 | ||
256 | struct format_capacity { | 264 | struct format_capacity { |
@@ -263,7 +271,8 @@ struct format_capacity { | |||
263 | static union { | 271 | static 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; | |||
278 | static struct { | 287 | static 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 |