1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
// $Id: gpsm_dcm_fast_handler.S,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $
/// \file gpsm_dcm_fast_handler.S
/// \brief Assembler support for GPSM_DCM procedures
/// \cond
.nolist
#include "ssx.h"
#include "pmc_dcm.h"
#include "gpsm_dcm.h"
.list
#define GPSM_IC_CONTINUOUS_DATA (PMC_IC_MSG_CC << 4 | GPSM_IC_DATA)
// The gpsm_dcm_write fast handler.
// Register use:
//
// R3 = Entry: void *arg; *arg -> GpsmDcmFast
// R4 = Entry: SsxIrqId irq; irq : constant
// R5 = Entry: int priority; priority -> data
// R6 = data_pointer
// R7 = remaining_size
// CR = <condition>
// LR = <return address>
// No other registers can be used, other than SPRG
.global_function gpsm_dcm_fast_write
gpsm_dcm_fast_write:
_ssx_irq_status_clear %r4, %r6, %r7 //clear status first
lwz %r6, 0(%r3) //load data pointer
lwz %r7, 4(%r3) //load remaining size
cmpwi %r7, 0 //if size == 0
beq exit_write_handler //exit fast write
cmpwi %r7, 1 //if size == 1
beq load_one_byte //load only one byte
lhz %r5, 0(%r6) //otherwise load two bytes
addi %r6, %r6, 2 //data pointer+2
addi %r7, %r7,-2 //remaining size-2
b form_and_send_packet //then form and send packet
load_one_byte:
lbz %r5, 0(%r6) //load one byte from buffer
addi %r6, %r6, 1 //data pointer+1
addi %r7, %r7,-1 //remaining size-1
form_and_send_packet:
stw %r6, 0(%r3) //store updated data pointer
stw %r7, 4(%r3) //store updated remaining size
lis %r6, GPSM_IC_CONTINUOUS_DATA //load cmd code to upper bits
or %r5, %r5, %r6 //load data into lower bits
slwi %r5, %r5, 8 //packet<<8 to give ecc field
_stwi %r5, %r7, PMC_INTCHP_MSG_WDATA //send packet
blr //return
exit_write_handler:
bl __ssx_irq_fast2full //convert fast to full irq handler
_ssx_irq_disable %r4, %r6, %r7 //disable this irq
addi %r3, %r3, 8 //argument pointer to semaphore
bl ssx_semaphore_post //post to that semaphore
b __ssx_irq_full_mode_exit //exit
.epilogue gpsm_dcm_fast_write
// The gpsm_dcm_read fast handler.
// Register use:
//
// R3 = Entry: void *arg; *arg -> GpsmDcmFast(data,size,semaphore)
// R4 = Entry: SsxIrqId irq; irq : constant
// R5 = Entry: int priority; priority -> data
// R6 = data_pointer
// R7 = remaining_size
// CR = <condition>
// LR = <return address>
// No other registers can be used, other than SPRG
.global_function gpsm_dcm_fast_read
gpsm_dcm_fast_read:
_ssx_irq_status_clear %r4, %r6, %r7 //clear status first
lwz %r7, 4(%r3) //load remaining size
cmpwi %r7, 0 //if size == 0
beq exit_read_handler //then exit fast read
_lwzi %r6, %r7, PMC_INTCHP_MSG_RDATA //receive packet
extrwi %r5, %r6, 16, 8 //extract data to r5
extrwi %r6, %r6, 8, 0 //extract cmd code to r6
li %r7, GPSM_IC_CONTINUOUS_DATA //designated cmd code to r7
cmpw %r6, %r7 //compare and check cmd code
bne panic_read_packet //panic on wrong cmd code
lwz %r6, 0(%r3) //load data pointer
lwz %r7, 4(%r3) //load remaining size
cmpwi %r7, 1 //if only one byte left
beq store_one_byte //then store only one byte
sth %r5, 0(%r6) //otherwise store two bytes to buf
addi %r6, %r6, 2 //data pointer+2
addi %r7, %r7,-2 //remaining size-2
b check_read_status //check read status
store_one_byte:
stb %r5, 0(%r6) //store one byte to buf
addi %r6, %r6, 1 //data pointer+1
addi %r7, %r7,-1 //remaining size-1
check_read_status:
stw %r6, 0(%r3) //store updated data pointer
stw %r7, 4(%r3) //store updated remaining size
cmpwi %r7, 0 //if size == 0
beq exit_read_handler //then terminate fast read
blr //return if still data left
exit_read_handler:
bl __ssx_irq_fast2full //convert fast to full irq handler
_ssx_irq_disable %r4, %r6, %r7 //disable this irq
addi %r3, %r3, 8 //argument pointer to semaphore
bl ssx_semaphore_post //post to that semaphore
b __ssx_irq_full_mode_exit //exit
panic_read_packet:
SSX_PANIC(GPSM_DCM_READ_NOT_WRITE_DATA) //PANIC if cmd code is wrong
.epilogue gpsm_dcm_fast_read
/// \endcond
|