revert between 56095 -> 55830 in arch
[AROS.git] / rom / devs / ahci / ahci_aros.c
blobe8c0882e6c0738f4a8a4b48a0391a07e0a0c33c2
1 /*
2 * Copyright (C) 2012-2018, The AROS Development Team. All rights reserved.
3 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
5 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
6 */
8 #include <proto/exec.h>
10 /* We want all other bases obtained from our base */
11 #define __NOLIBBASE__
13 #include <aros/atomic.h>
15 #include <proto/oop.h>
17 #include <hidd/pci.h>
19 #include <devices/timer.h>
21 #include "ahci.h"
22 #include "timer.h"
24 void callout_init_mp(struct callout *co)
26 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
27 memset(co, 0, sizeof(*co));
30 void callout_init(struct callout *co)
32 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
33 callout_init_mp(co);
36 void callout_stop(struct callout *co)
38 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
39 Forbid();
40 if (co->co_Task) {
41 Signal(co->co_Task, SIGF_ABORT);
42 co->co_Task = NULL;
44 Permit();
47 void callout_stop_sync(struct callout *co)
49 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
50 callout_stop(co);
53 static void callout_handler(struct callout *co, unsigned ticks, timeout_t *func, void *arg)
55 struct IORequest *io;
56 ULONG signals = 0;
57 ULONG ms = ticks;
59 if ((io = ahci_OpenTimer())) {
60 signals = ahci_WaitTO(io, ms / 1000, 1000 * (ms % 1000), SIGF_ABORT);
61 ahci_CloseTimer(io);
64 if (!(signals & SIGF_ABORT)) {
65 co->co_Task = NULL;
66 func(arg);
70 int callout_reset(struct callout *co, unsigned ticks, timeout_t *func, void *arg)
72 struct Task *t;
73 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
75 callout_stop(co);
77 t = NewCreateTask(TASKTAG_NAME, "AHCI Callout",
78 TASKTAG_PC, callout_handler,
79 TASKTAG_PRI, 21,
80 TASKTAG_ARG1, co,
81 TASKTAG_ARG2, ticks,
82 TASKTAG_ARG3, func,
83 TASKTAG_ARG4, arg,
84 TAG_END);
85 co->co_Task = t;
87 return (t == NULL) ? ENOMEM : 0;
90 void ahci_os_sleep(int ms)
92 struct IORequest *io = ahci_OpenTimer();
93 if (io != NULL) {
94 ahci_WaitTO(io, ms / 1000, (ms % 1000) * 1000, 0);
95 ahci_CloseTimer(io);
99 void ahci_os_hardsleep(int us)
101 ahci_WaitNano((ULONG)us * 1000);
105 * Sleep for a minimum interval and return the number of milliseconds
106 * that was. The minimum value returned is 1
108 * UNIT_MICROHZ is only guaranteed to work down to 2 microseconds.
110 int ahci_os_softsleep(void)
112 struct IORequest *io = ahci_OpenTimer();
113 if (io != NULL) {
114 ahci_WaitTO(io, 0, 100 * 1000, 0);
115 ahci_CloseTimer(io);
117 return 100;
121 * Per-port thread helper. This helper thread is responsible for
122 * atomically retrieving and clearing the signal mask and calling
123 * the machine-independant driver core.
125 * MPSAFE
127 static void ahci_port_thread(void *arg)
129 struct ahci_port *ap = arg;
130 int mask;
132 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
135 * The helper thread is responsible for the initial port init,
136 * so all the ports can be inited in parallel.
138 * We also run the state machine which should do all probes.
139 * Since CAM is not attached yet we will not get out-of-order
140 * SCSI attachments.
142 ahci_os_lock_port(ap);
143 ahci_port_init(ap);
144 atomic_clear_int(&ap->ap_signal, AP_SIGF_THREAD_SYNC);
145 ahci_port_state_machine(ap, 1);
146 ahci_os_unlock_port(ap);
147 atomic_clear_int(&ap->ap_signal, AP_SIGF_INIT);
150 * Then loop on the helper core.
152 mask = ap->ap_signal;
153 while ((mask & AP_SIGF_STOP) == 0) {
154 ahci_port_thread_core(ap, mask);
155 // lockmgr(&ap->ap_sig_lock, LK_EXCLUSIVE);
156 if (ap->ap_signal == 0)
157 Wait(SIGF_DOS);
158 mask = ap->ap_signal;
159 atomic_clear_int(&ap->ap_signal, mask);
160 // lockmgr(&ap->ap_sig_lock, LK_RELEASE);
162 ap->ap_thread = NULL;
165 void ahci_os_start_port(struct ahci_port *ap)
167 char name[16];
169 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
171 atomic_set_int(&ap->ap_signal, AP_SIGF_INIT | AP_SIGF_THREAD_SYNC);
172 lockinit(&ap->ap_lock, "ahcipo", 0, LK_CANRECURSE);
173 lockinit(&ap->ap_sim_lock, "ahcicam", 0, LK_CANRECURSE);
174 ksnprintf(name, sizeof(name), "%d", ap->ap_num);
176 kthread_create(ahci_port_thread, ap, &ap->ap_thread,
177 "%s", PORTNAME(ap));
181 * Stop the OS-specific port helper thread and kill the per-port lock.
183 void ahci_os_stop_port(struct ahci_port *ap)
185 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
186 if (ap->ap_thread) {
187 ahci_os_signal_port_thread(ap, AP_SIGF_STOP);
188 ahci_os_sleep(10);
189 if (ap->ap_thread) {
190 kprintf("%s: Waiting for thread to terminate\n",
191 PORTNAME(ap));
192 while (ap->ap_thread)
193 ahci_os_sleep(100);
194 kprintf("%s: thread terminated\n",
195 PORTNAME(ap));
198 lockuninit(&ap->ap_lock);
202 * Add (mask) to the set of bits being sent to the per-port thread helper
203 * and wake the helper up if necessary.
205 * We use SIGF_DOS, since these are Threads, not Processes, and
206 * won't already be using SIGF_DOS for messages.
208 void ahci_os_signal_port_thread(struct ahci_port *ap, int mask)
210 D(bug("[AHCI] %s()\n", __PRETTY_FUNCTION__));
211 atomic_set_int(&ap->ap_signal, mask);
212 Signal(ap->ap_thread, SIGF_DOS);
216 * Unconditionally lock the port structure for access.
218 void ahci_os_lock_port(struct ahci_port *ap)
220 lockmgr(&ap->ap_lock, LK_EXCLUSIVE);
224 * Conditionally lock the port structure for access.
226 * Returns 0 on success, non-zero on failure.
228 int ahci_os_lock_port_nb(struct ahci_port *ap)
230 return 1;
234 * Unlock a previously locked port.
236 void ahci_os_unlock_port(struct ahci_port *ap)
238 lockmgr(&ap->ap_lock, LK_RELEASE);