Defined more SCSI sense data keys
[AROS.git] / rom / devs / ahci / ahci_aros.c
blobba334a89cf0fc8d3239d4a559f108757333f0229
1 /*
2 * Copyright (C) 2012, 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 <aros/atomic.h>
10 #include <proto/exec.h>
11 #include <proto/oop.h>
13 #include <hidd/pci.h>
15 #include <devices/timer.h>
17 #include "ahci.h"
18 #include "timer.h"
20 void callout_init_mp(struct callout *co)
22 memset(co, 0, sizeof(*co));
25 void callout_init(struct callout *co)
27 callout_init_mp(co);
30 void callout_stop(struct callout *co)
32 Forbid();
33 if (co->co_Task) {
34 Signal(co->co_Task, SIGF_ABORT);
35 co->co_Task = NULL;
37 Permit();
40 void callout_stop_sync(struct callout *co)
42 callout_stop(co);
45 static void callout_handler(struct callout *co, unsigned ticks, timeout_t *func, void *arg)
47 struct IORequest *io;
48 ULONG signals = 0;
49 ULONG ms = ticks / hz;
51 if ((io = ahci_OpenTimer())) {
52 signals = ahci_WaitTO(io, ms, 0, SIGF_ABORT);
53 ahci_CloseTimer(io);
56 if (!(signals & SIGF_ABORT)) {
57 co->co_Task = NULL;
58 func(arg);
62 int callout_reset(struct callout *co, unsigned ticks, timeout_t *func, void *arg)
64 struct Task *t;
66 callout_stop(co);
68 t = NewCreateTask(TASKTAG_NAME, "AHCI Callout",
69 TASKTAG_PC, callout_handler,
70 TASKTAG_PRI, 21,
71 TASKTAG_ARG1, co,
72 TASKTAG_ARG2, ticks,
73 TASKTAG_ARG3, func,
74 TASKTAG_ARG4, arg,
75 TAG_END);
76 co->co_Task = t;
78 return (t == NULL) ? ENOMEM : 0;
81 void ahci_os_sleep(int ms)
83 struct IORequest *io = ahci_OpenTimer();
84 if (io != NULL) {
85 ahci_WaitTO(io, ms / 1000, (ms % 1000) * 1000, 0);
86 ahci_CloseTimer(io);
90 void ahci_os_hardsleep(int us)
92 ahci_WaitNano((ULONG)us * 1000);
96 * Sleep for a minimum interval and return the number of milliseconds
97 * that was. The minimum value returned is 1
99 * UNIT_MICROHZ is only guaranteed to work down to 2 microseconds.
101 int ahci_os_softsleep(void)
103 struct IORequest *io = ahci_OpenTimer();
104 if (io != NULL) {
105 ahci_WaitTO(io, 0, 100 * 1000, 0);
106 ahci_CloseTimer(io);
108 return 100;
112 * Per-port thread helper. This helper thread is responsible for
113 * atomically retrieving and clearing the signal mask and calling
114 * the machine-independant driver core.
116 * MPSAFE
118 static void ahci_port_thread(void *arg)
120 struct ahci_port *ap = arg;
121 int mask;
124 * The helper thread is responsible for the initial port init,
125 * so all the ports can be inited in parallel.
127 * We also run the state machine which should do all probes.
128 * Since CAM is not attached yet we will not get out-of-order
129 * SCSI attachments.
131 ahci_os_lock_port(ap);
132 ahci_port_init(ap);
133 atomic_clear_int(&ap->ap_signal, AP_SIGF_THREAD_SYNC);
134 ahci_port_state_machine(ap, 1);
135 ahci_os_unlock_port(ap);
136 atomic_clear_int(&ap->ap_signal, AP_SIGF_INIT);
139 * Then loop on the helper core.
141 mask = ap->ap_signal;
142 while ((mask & AP_SIGF_STOP) == 0) {
143 ahci_port_thread_core(ap, mask);
144 // lockmgr(&ap->ap_sig_lock, LK_EXCLUSIVE);
145 if (ap->ap_signal == 0)
146 Wait(SIGF_DOS);
147 mask = ap->ap_signal;
148 atomic_clear_int(&ap->ap_signal, mask);
149 // lockmgr(&ap->ap_sig_lock, LK_RELEASE);
151 ap->ap_thread = NULL;
154 void ahci_os_start_port(struct ahci_port *ap)
156 char name[16];
158 atomic_set_int(&ap->ap_signal, AP_SIGF_INIT | AP_SIGF_THREAD_SYNC);
159 lockinit(&ap->ap_lock, "ahcipo", 0, LK_CANRECURSE);
160 lockinit(&ap->ap_sim_lock, "ahcicam", 0, LK_CANRECURSE);
161 ksnprintf(name, sizeof(name), "%d", ap->ap_num);
163 kthread_create(ahci_port_thread, ap, &ap->ap_thread,
164 "%s", PORTNAME(ap));
168 * Stop the OS-specific port helper thread and kill the per-port lock.
170 void ahci_os_stop_port(struct ahci_port *ap)
172 if (ap->ap_thread) {
173 ahci_os_signal_port_thread(ap, AP_SIGF_STOP);
174 ahci_os_sleep(10);
175 if (ap->ap_thread) {
176 kprintf("%s: Waiting for thread to terminate\n",
177 PORTNAME(ap));
178 while (ap->ap_thread)
179 ahci_os_sleep(100);
180 kprintf("%s: thread terminated\n",
181 PORTNAME(ap));
184 lockuninit(&ap->ap_lock);
188 * Add (mask) to the set of bits being sent to the per-port thread helper
189 * and wake the helper up if necessary.
191 * We use SIGF_DOS, since these are Threads, not Processes, and
192 * won't already be using SIGF_DOS for messages.
194 void ahci_os_signal_port_thread(struct ahci_port *ap, int mask)
196 atomic_set_int(&ap->ap_signal, mask);
197 Signal(ap->ap_thread, SIGF_DOS);
201 * Unconditionally lock the port structure for access.
203 void ahci_os_lock_port(struct ahci_port *ap)
205 lockmgr(&ap->ap_lock, LK_EXCLUSIVE);
209 * Conditionally lock the port structure for access.
211 * Returns 0 on success, non-zero on failure.
213 int ahci_os_lock_port_nb(struct ahci_port *ap)
215 return 1;
219 * Unlock a previously locked port.
221 void ahci_os_unlock_port(struct ahci_port *ap)
223 lockmgr(&ap->ap_lock, LK_RELEASE);