Commit ee51f4432e375d07c29758e592c8c1ad1a343208
Committed by
Jiri Kosina
1 parent
53c0ad522e
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
aic94xx: Get rid of redundant NULL check before release_firmware() call
release_firmware() checks for NULL pointers internally, so checking before calling the function is redundant. Signed-off-by: Jesper Juhl <jj@chaosbits.net> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Showing 1 changed file with 1 additions and 2 deletions Inline Diff
drivers/scsi/aic94xx/aic94xx_seq.c
1 | /* | 1 | /* |
2 | * Aic94xx SAS/SATA driver sequencer interface. | 2 | * Aic94xx SAS/SATA driver sequencer interface. |
3 | * | 3 | * |
4 | * Copyright (C) 2005 Adaptec, Inc. All rights reserved. | 4 | * Copyright (C) 2005 Adaptec, Inc. All rights reserved. |
5 | * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> | 5 | * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> |
6 | * | 6 | * |
7 | * Parts of this code adapted from David Chaw's adp94xx_seq.c. | 7 | * Parts of this code adapted from David Chaw's adp94xx_seq.c. |
8 | * | 8 | * |
9 | * This file is licensed under GPLv2. | 9 | * This file is licensed under GPLv2. |
10 | * | 10 | * |
11 | * This file is part of the aic94xx driver. | 11 | * This file is part of the aic94xx driver. |
12 | * | 12 | * |
13 | * The aic94xx driver is free software; you can redistribute it and/or | 13 | * The aic94xx driver is free software; you can redistribute it and/or |
14 | * modify it under the terms of the GNU General Public License as | 14 | * modify it under the terms of the GNU General Public License as |
15 | * published by the Free Software Foundation; version 2 of the | 15 | * published by the Free Software Foundation; version 2 of the |
16 | * License. | 16 | * License. |
17 | * | 17 | * |
18 | * The aic94xx driver is distributed in the hope that it will be useful, | 18 | * The aic94xx driver is distributed in the hope that it will be useful, |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
21 | * General Public License for more details. | 21 | * General Public License for more details. |
22 | * | 22 | * |
23 | * You should have received a copy of the GNU General Public License | 23 | * You should have received a copy of the GNU General Public License |
24 | * along with the aic94xx driver; if not, write to the Free Software | 24 | * along with the aic94xx driver; if not, write to the Free Software |
25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/gfp.h> | 30 | #include <linux/gfp.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/firmware.h> | 33 | #include <linux/firmware.h> |
34 | #include "aic94xx_reg.h" | 34 | #include "aic94xx_reg.h" |
35 | #include "aic94xx_hwi.h" | 35 | #include "aic94xx_hwi.h" |
36 | 36 | ||
37 | #include "aic94xx_seq.h" | 37 | #include "aic94xx_seq.h" |
38 | #include "aic94xx_dump.h" | 38 | #include "aic94xx_dump.h" |
39 | 39 | ||
40 | /* It takes no more than 0.05 us for an instruction | 40 | /* It takes no more than 0.05 us for an instruction |
41 | * to complete. So waiting for 1 us should be more than | 41 | * to complete. So waiting for 1 us should be more than |
42 | * plenty. | 42 | * plenty. |
43 | */ | 43 | */ |
44 | #define PAUSE_DELAY 1 | 44 | #define PAUSE_DELAY 1 |
45 | #define PAUSE_TRIES 1000 | 45 | #define PAUSE_TRIES 1000 |
46 | 46 | ||
47 | static const struct firmware *sequencer_fw; | 47 | static const struct firmware *sequencer_fw; |
48 | static u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task, | 48 | static u16 cseq_vecs[CSEQ_NUM_VECS], lseq_vecs[LSEQ_NUM_VECS], mode2_task, |
49 | cseq_idle_loop, lseq_idle_loop; | 49 | cseq_idle_loop, lseq_idle_loop; |
50 | static const u8 *cseq_code, *lseq_code; | 50 | static const u8 *cseq_code, *lseq_code; |
51 | static u32 cseq_code_size, lseq_code_size; | 51 | static u32 cseq_code_size, lseq_code_size; |
52 | 52 | ||
53 | static u16 first_scb_site_no = 0xFFFF; | 53 | static u16 first_scb_site_no = 0xFFFF; |
54 | static u16 last_scb_site_no; | 54 | static u16 last_scb_site_no; |
55 | 55 | ||
56 | /* ---------- Pause/Unpause CSEQ/LSEQ ---------- */ | 56 | /* ---------- Pause/Unpause CSEQ/LSEQ ---------- */ |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * asd_pause_cseq - pause the central sequencer | 59 | * asd_pause_cseq - pause the central sequencer |
60 | * @asd_ha: pointer to host adapter structure | 60 | * @asd_ha: pointer to host adapter structure |
61 | * | 61 | * |
62 | * Return 0 on success, negative on failure. | 62 | * Return 0 on success, negative on failure. |
63 | */ | 63 | */ |
64 | static int asd_pause_cseq(struct asd_ha_struct *asd_ha) | 64 | static int asd_pause_cseq(struct asd_ha_struct *asd_ha) |
65 | { | 65 | { |
66 | int count = PAUSE_TRIES; | 66 | int count = PAUSE_TRIES; |
67 | u32 arp2ctl; | 67 | u32 arp2ctl; |
68 | 68 | ||
69 | arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); | 69 | arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); |
70 | if (arp2ctl & PAUSED) | 70 | if (arp2ctl & PAUSED) |
71 | return 0; | 71 | return 0; |
72 | 72 | ||
73 | asd_write_reg_dword(asd_ha, CARP2CTL, arp2ctl | EPAUSE); | 73 | asd_write_reg_dword(asd_ha, CARP2CTL, arp2ctl | EPAUSE); |
74 | do { | 74 | do { |
75 | arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); | 75 | arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); |
76 | if (arp2ctl & PAUSED) | 76 | if (arp2ctl & PAUSED) |
77 | return 0; | 77 | return 0; |
78 | udelay(PAUSE_DELAY); | 78 | udelay(PAUSE_DELAY); |
79 | } while (--count > 0); | 79 | } while (--count > 0); |
80 | 80 | ||
81 | ASD_DPRINTK("couldn't pause CSEQ\n"); | 81 | ASD_DPRINTK("couldn't pause CSEQ\n"); |
82 | return -1; | 82 | return -1; |
83 | } | 83 | } |
84 | 84 | ||
85 | /** | 85 | /** |
86 | * asd_unpause_cseq - unpause the central sequencer. | 86 | * asd_unpause_cseq - unpause the central sequencer. |
87 | * @asd_ha: pointer to host adapter structure. | 87 | * @asd_ha: pointer to host adapter structure. |
88 | * | 88 | * |
89 | * Return 0 on success, negative on error. | 89 | * Return 0 on success, negative on error. |
90 | */ | 90 | */ |
91 | static int asd_unpause_cseq(struct asd_ha_struct *asd_ha) | 91 | static int asd_unpause_cseq(struct asd_ha_struct *asd_ha) |
92 | { | 92 | { |
93 | u32 arp2ctl; | 93 | u32 arp2ctl; |
94 | int count = PAUSE_TRIES; | 94 | int count = PAUSE_TRIES; |
95 | 95 | ||
96 | arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); | 96 | arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); |
97 | if (!(arp2ctl & PAUSED)) | 97 | if (!(arp2ctl & PAUSED)) |
98 | return 0; | 98 | return 0; |
99 | 99 | ||
100 | asd_write_reg_dword(asd_ha, CARP2CTL, arp2ctl & ~EPAUSE); | 100 | asd_write_reg_dword(asd_ha, CARP2CTL, arp2ctl & ~EPAUSE); |
101 | do { | 101 | do { |
102 | arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); | 102 | arp2ctl = asd_read_reg_dword(asd_ha, CARP2CTL); |
103 | if (!(arp2ctl & PAUSED)) | 103 | if (!(arp2ctl & PAUSED)) |
104 | return 0; | 104 | return 0; |
105 | udelay(PAUSE_DELAY); | 105 | udelay(PAUSE_DELAY); |
106 | } while (--count > 0); | 106 | } while (--count > 0); |
107 | 107 | ||
108 | ASD_DPRINTK("couldn't unpause the CSEQ\n"); | 108 | ASD_DPRINTK("couldn't unpause the CSEQ\n"); |
109 | return -1; | 109 | return -1; |
110 | } | 110 | } |
111 | 111 | ||
112 | /** | 112 | /** |
113 | * asd_seq_pause_lseq - pause a link sequencer | 113 | * asd_seq_pause_lseq - pause a link sequencer |
114 | * @asd_ha: pointer to a host adapter structure | 114 | * @asd_ha: pointer to a host adapter structure |
115 | * @lseq: link sequencer of interest | 115 | * @lseq: link sequencer of interest |
116 | * | 116 | * |
117 | * Return 0 on success, negative on error. | 117 | * Return 0 on success, negative on error. |
118 | */ | 118 | */ |
119 | static int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq) | 119 | static int asd_seq_pause_lseq(struct asd_ha_struct *asd_ha, int lseq) |
120 | { | 120 | { |
121 | u32 arp2ctl; | 121 | u32 arp2ctl; |
122 | int count = PAUSE_TRIES; | 122 | int count = PAUSE_TRIES; |
123 | 123 | ||
124 | arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); | 124 | arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); |
125 | if (arp2ctl & PAUSED) | 125 | if (arp2ctl & PAUSED) |
126 | return 0; | 126 | return 0; |
127 | 127 | ||
128 | asd_write_reg_dword(asd_ha, LmARP2CTL(lseq), arp2ctl | EPAUSE); | 128 | asd_write_reg_dword(asd_ha, LmARP2CTL(lseq), arp2ctl | EPAUSE); |
129 | do { | 129 | do { |
130 | arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); | 130 | arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); |
131 | if (arp2ctl & PAUSED) | 131 | if (arp2ctl & PAUSED) |
132 | return 0; | 132 | return 0; |
133 | udelay(PAUSE_DELAY); | 133 | udelay(PAUSE_DELAY); |
134 | } while (--count > 0); | 134 | } while (--count > 0); |
135 | 135 | ||
136 | ASD_DPRINTK("couldn't pause LSEQ %d\n", lseq); | 136 | ASD_DPRINTK("couldn't pause LSEQ %d\n", lseq); |
137 | return -1; | 137 | return -1; |
138 | } | 138 | } |
139 | 139 | ||
140 | /** | 140 | /** |
141 | * asd_pause_lseq - pause the link sequencer(s) | 141 | * asd_pause_lseq - pause the link sequencer(s) |
142 | * @asd_ha: pointer to host adapter structure | 142 | * @asd_ha: pointer to host adapter structure |
143 | * @lseq_mask: mask of link sequencers of interest | 143 | * @lseq_mask: mask of link sequencers of interest |
144 | * | 144 | * |
145 | * Return 0 on success, negative on failure. | 145 | * Return 0 on success, negative on failure. |
146 | */ | 146 | */ |
147 | static int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask) | 147 | static int asd_pause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask) |
148 | { | 148 | { |
149 | int lseq; | 149 | int lseq; |
150 | int err = 0; | 150 | int err = 0; |
151 | 151 | ||
152 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { | 152 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { |
153 | err = asd_seq_pause_lseq(asd_ha, lseq); | 153 | err = asd_seq_pause_lseq(asd_ha, lseq); |
154 | if (err) | 154 | if (err) |
155 | return err; | 155 | return err; |
156 | } | 156 | } |
157 | 157 | ||
158 | return err; | 158 | return err; |
159 | } | 159 | } |
160 | 160 | ||
161 | /** | 161 | /** |
162 | * asd_seq_unpause_lseq - unpause a link sequencer | 162 | * asd_seq_unpause_lseq - unpause a link sequencer |
163 | * @asd_ha: pointer to host adapter structure | 163 | * @asd_ha: pointer to host adapter structure |
164 | * @lseq: link sequencer of interest | 164 | * @lseq: link sequencer of interest |
165 | * | 165 | * |
166 | * Return 0 on success, negative on error. | 166 | * Return 0 on success, negative on error. |
167 | */ | 167 | */ |
168 | static int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq) | 168 | static int asd_seq_unpause_lseq(struct asd_ha_struct *asd_ha, int lseq) |
169 | { | 169 | { |
170 | u32 arp2ctl; | 170 | u32 arp2ctl; |
171 | int count = PAUSE_TRIES; | 171 | int count = PAUSE_TRIES; |
172 | 172 | ||
173 | arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); | 173 | arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); |
174 | if (!(arp2ctl & PAUSED)) | 174 | if (!(arp2ctl & PAUSED)) |
175 | return 0; | 175 | return 0; |
176 | 176 | ||
177 | asd_write_reg_dword(asd_ha, LmARP2CTL(lseq), arp2ctl & ~EPAUSE); | 177 | asd_write_reg_dword(asd_ha, LmARP2CTL(lseq), arp2ctl & ~EPAUSE); |
178 | do { | 178 | do { |
179 | arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); | 179 | arp2ctl = asd_read_reg_dword(asd_ha, LmARP2CTL(lseq)); |
180 | if (!(arp2ctl & PAUSED)) | 180 | if (!(arp2ctl & PAUSED)) |
181 | return 0; | 181 | return 0; |
182 | udelay(PAUSE_DELAY); | 182 | udelay(PAUSE_DELAY); |
183 | } while (--count > 0); | 183 | } while (--count > 0); |
184 | 184 | ||
185 | ASD_DPRINTK("couldn't unpause LSEQ %d\n", lseq); | 185 | ASD_DPRINTK("couldn't unpause LSEQ %d\n", lseq); |
186 | return 0; | 186 | return 0; |
187 | } | 187 | } |
188 | 188 | ||
189 | 189 | ||
190 | /* ---------- Downloading CSEQ/LSEQ microcode ---------- */ | 190 | /* ---------- Downloading CSEQ/LSEQ microcode ---------- */ |
191 | 191 | ||
192 | static int asd_verify_cseq(struct asd_ha_struct *asd_ha, const u8 *_prog, | 192 | static int asd_verify_cseq(struct asd_ha_struct *asd_ha, const u8 *_prog, |
193 | u32 size) | 193 | u32 size) |
194 | { | 194 | { |
195 | u32 addr = CSEQ_RAM_REG_BASE_ADR; | 195 | u32 addr = CSEQ_RAM_REG_BASE_ADR; |
196 | const u32 *prog = (u32 *) _prog; | 196 | const u32 *prog = (u32 *) _prog; |
197 | u32 i; | 197 | u32 i; |
198 | 198 | ||
199 | for (i = 0; i < size; i += 4, prog++, addr += 4) { | 199 | for (i = 0; i < size; i += 4, prog++, addr += 4) { |
200 | u32 val = asd_read_reg_dword(asd_ha, addr); | 200 | u32 val = asd_read_reg_dword(asd_ha, addr); |
201 | 201 | ||
202 | if (le32_to_cpu(*prog) != val) { | 202 | if (le32_to_cpu(*prog) != val) { |
203 | asd_printk("%s: cseq verify failed at %u " | 203 | asd_printk("%s: cseq verify failed at %u " |
204 | "read:0x%x, wanted:0x%x\n", | 204 | "read:0x%x, wanted:0x%x\n", |
205 | pci_name(asd_ha->pcidev), | 205 | pci_name(asd_ha->pcidev), |
206 | i, val, le32_to_cpu(*prog)); | 206 | i, val, le32_to_cpu(*prog)); |
207 | return -1; | 207 | return -1; |
208 | } | 208 | } |
209 | } | 209 | } |
210 | ASD_DPRINTK("verified %d bytes, passed\n", size); | 210 | ASD_DPRINTK("verified %d bytes, passed\n", size); |
211 | return 0; | 211 | return 0; |
212 | } | 212 | } |
213 | 213 | ||
214 | /** | 214 | /** |
215 | * asd_verify_lseq - verify the microcode of a link sequencer | 215 | * asd_verify_lseq - verify the microcode of a link sequencer |
216 | * @asd_ha: pointer to host adapter structure | 216 | * @asd_ha: pointer to host adapter structure |
217 | * @_prog: pointer to the microcode | 217 | * @_prog: pointer to the microcode |
218 | * @size: size of the microcode in bytes | 218 | * @size: size of the microcode in bytes |
219 | * @lseq: link sequencer of interest | 219 | * @lseq: link sequencer of interest |
220 | * | 220 | * |
221 | * The link sequencer code is accessed in 4 KB pages, which are selected | 221 | * The link sequencer code is accessed in 4 KB pages, which are selected |
222 | * by setting LmRAMPAGE (bits 8 and 9) of the LmBISTCTL1 register. | 222 | * by setting LmRAMPAGE (bits 8 and 9) of the LmBISTCTL1 register. |
223 | * The 10 KB LSEQm instruction code is mapped, page at a time, at | 223 | * The 10 KB LSEQm instruction code is mapped, page at a time, at |
224 | * LmSEQRAM address. | 224 | * LmSEQRAM address. |
225 | */ | 225 | */ |
226 | static int asd_verify_lseq(struct asd_ha_struct *asd_ha, const u8 *_prog, | 226 | static int asd_verify_lseq(struct asd_ha_struct *asd_ha, const u8 *_prog, |
227 | u32 size, int lseq) | 227 | u32 size, int lseq) |
228 | { | 228 | { |
229 | #define LSEQ_CODEPAGE_SIZE 4096 | 229 | #define LSEQ_CODEPAGE_SIZE 4096 |
230 | int pages = (size + LSEQ_CODEPAGE_SIZE - 1) / LSEQ_CODEPAGE_SIZE; | 230 | int pages = (size + LSEQ_CODEPAGE_SIZE - 1) / LSEQ_CODEPAGE_SIZE; |
231 | u32 page; | 231 | u32 page; |
232 | const u32 *prog = (u32 *) _prog; | 232 | const u32 *prog = (u32 *) _prog; |
233 | 233 | ||
234 | for (page = 0; page < pages; page++) { | 234 | for (page = 0; page < pages; page++) { |
235 | u32 i; | 235 | u32 i; |
236 | 236 | ||
237 | asd_write_reg_dword(asd_ha, LmBISTCTL1(lseq), | 237 | asd_write_reg_dword(asd_ha, LmBISTCTL1(lseq), |
238 | page << LmRAMPAGE_LSHIFT); | 238 | page << LmRAMPAGE_LSHIFT); |
239 | for (i = 0; size > 0 && i < LSEQ_CODEPAGE_SIZE; | 239 | for (i = 0; size > 0 && i < LSEQ_CODEPAGE_SIZE; |
240 | i += 4, prog++, size-=4) { | 240 | i += 4, prog++, size-=4) { |
241 | 241 | ||
242 | u32 val = asd_read_reg_dword(asd_ha, LmSEQRAM(lseq)+i); | 242 | u32 val = asd_read_reg_dword(asd_ha, LmSEQRAM(lseq)+i); |
243 | 243 | ||
244 | if (le32_to_cpu(*prog) != val) { | 244 | if (le32_to_cpu(*prog) != val) { |
245 | asd_printk("%s: LSEQ%d verify failed " | 245 | asd_printk("%s: LSEQ%d verify failed " |
246 | "page:%d, offs:%d\n", | 246 | "page:%d, offs:%d\n", |
247 | pci_name(asd_ha->pcidev), | 247 | pci_name(asd_ha->pcidev), |
248 | lseq, page, i); | 248 | lseq, page, i); |
249 | return -1; | 249 | return -1; |
250 | } | 250 | } |
251 | } | 251 | } |
252 | } | 252 | } |
253 | ASD_DPRINTK("LSEQ%d verified %d bytes, passed\n", lseq, | 253 | ASD_DPRINTK("LSEQ%d verified %d bytes, passed\n", lseq, |
254 | (int)((u8 *)prog-_prog)); | 254 | (int)((u8 *)prog-_prog)); |
255 | return 0; | 255 | return 0; |
256 | } | 256 | } |
257 | 257 | ||
258 | /** | 258 | /** |
259 | * asd_verify_seq -- verify CSEQ/LSEQ microcode | 259 | * asd_verify_seq -- verify CSEQ/LSEQ microcode |
260 | * @asd_ha: pointer to host adapter structure | 260 | * @asd_ha: pointer to host adapter structure |
261 | * @prog: pointer to microcode | 261 | * @prog: pointer to microcode |
262 | * @size: size of the microcode | 262 | * @size: size of the microcode |
263 | * @lseq_mask: if 0, verify CSEQ microcode, else mask of LSEQs of interest | 263 | * @lseq_mask: if 0, verify CSEQ microcode, else mask of LSEQs of interest |
264 | * | 264 | * |
265 | * Return 0 if microcode is correct, negative on mismatch. | 265 | * Return 0 if microcode is correct, negative on mismatch. |
266 | */ | 266 | */ |
267 | static int asd_verify_seq(struct asd_ha_struct *asd_ha, const u8 *prog, | 267 | static int asd_verify_seq(struct asd_ha_struct *asd_ha, const u8 *prog, |
268 | u32 size, u8 lseq_mask) | 268 | u32 size, u8 lseq_mask) |
269 | { | 269 | { |
270 | if (lseq_mask == 0) | 270 | if (lseq_mask == 0) |
271 | return asd_verify_cseq(asd_ha, prog, size); | 271 | return asd_verify_cseq(asd_ha, prog, size); |
272 | else { | 272 | else { |
273 | int lseq, err; | 273 | int lseq, err; |
274 | 274 | ||
275 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { | 275 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { |
276 | err = asd_verify_lseq(asd_ha, prog, size, lseq); | 276 | err = asd_verify_lseq(asd_ha, prog, size, lseq); |
277 | if (err) | 277 | if (err) |
278 | return err; | 278 | return err; |
279 | } | 279 | } |
280 | } | 280 | } |
281 | 281 | ||
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | #define ASD_DMA_MODE_DOWNLOAD | 284 | #define ASD_DMA_MODE_DOWNLOAD |
285 | #ifdef ASD_DMA_MODE_DOWNLOAD | 285 | #ifdef ASD_DMA_MODE_DOWNLOAD |
286 | /* This is the size of the CSEQ Mapped instruction page */ | 286 | /* This is the size of the CSEQ Mapped instruction page */ |
287 | #define MAX_DMA_OVLY_COUNT ((1U << 14)-1) | 287 | #define MAX_DMA_OVLY_COUNT ((1U << 14)-1) |
288 | static int asd_download_seq(struct asd_ha_struct *asd_ha, | 288 | static int asd_download_seq(struct asd_ha_struct *asd_ha, |
289 | const u8 * const prog, u32 size, u8 lseq_mask) | 289 | const u8 * const prog, u32 size, u8 lseq_mask) |
290 | { | 290 | { |
291 | u32 comstaten; | 291 | u32 comstaten; |
292 | u32 reg; | 292 | u32 reg; |
293 | int page; | 293 | int page; |
294 | const int pages = (size + MAX_DMA_OVLY_COUNT - 1) / MAX_DMA_OVLY_COUNT; | 294 | const int pages = (size + MAX_DMA_OVLY_COUNT - 1) / MAX_DMA_OVLY_COUNT; |
295 | struct asd_dma_tok *token; | 295 | struct asd_dma_tok *token; |
296 | int err = 0; | 296 | int err = 0; |
297 | 297 | ||
298 | if (size % 4) { | 298 | if (size % 4) { |
299 | asd_printk("sequencer program not multiple of 4\n"); | 299 | asd_printk("sequencer program not multiple of 4\n"); |
300 | return -1; | 300 | return -1; |
301 | } | 301 | } |
302 | 302 | ||
303 | asd_pause_cseq(asd_ha); | 303 | asd_pause_cseq(asd_ha); |
304 | asd_pause_lseq(asd_ha, 0xFF); | 304 | asd_pause_lseq(asd_ha, 0xFF); |
305 | 305 | ||
306 | /* save, disable and clear interrupts */ | 306 | /* save, disable and clear interrupts */ |
307 | comstaten = asd_read_reg_dword(asd_ha, COMSTATEN); | 307 | comstaten = asd_read_reg_dword(asd_ha, COMSTATEN); |
308 | asd_write_reg_dword(asd_ha, COMSTATEN, 0); | 308 | asd_write_reg_dword(asd_ha, COMSTATEN, 0); |
309 | asd_write_reg_dword(asd_ha, COMSTAT, COMSTAT_MASK); | 309 | asd_write_reg_dword(asd_ha, COMSTAT, COMSTAT_MASK); |
310 | 310 | ||
311 | asd_write_reg_dword(asd_ha, CHIMINTEN, RST_CHIMINTEN); | 311 | asd_write_reg_dword(asd_ha, CHIMINTEN, RST_CHIMINTEN); |
312 | asd_write_reg_dword(asd_ha, CHIMINT, CHIMINT_MASK); | 312 | asd_write_reg_dword(asd_ha, CHIMINT, CHIMINT_MASK); |
313 | 313 | ||
314 | token = asd_alloc_coherent(asd_ha, MAX_DMA_OVLY_COUNT, GFP_KERNEL); | 314 | token = asd_alloc_coherent(asd_ha, MAX_DMA_OVLY_COUNT, GFP_KERNEL); |
315 | if (!token) { | 315 | if (!token) { |
316 | asd_printk("out of memory for dma SEQ download\n"); | 316 | asd_printk("out of memory for dma SEQ download\n"); |
317 | err = -ENOMEM; | 317 | err = -ENOMEM; |
318 | goto out; | 318 | goto out; |
319 | } | 319 | } |
320 | ASD_DPRINTK("dma-ing %d bytes\n", size); | 320 | ASD_DPRINTK("dma-ing %d bytes\n", size); |
321 | 321 | ||
322 | for (page = 0; page < pages; page++) { | 322 | for (page = 0; page < pages; page++) { |
323 | int i; | 323 | int i; |
324 | u32 left = min(size-page*MAX_DMA_OVLY_COUNT, | 324 | u32 left = min(size-page*MAX_DMA_OVLY_COUNT, |
325 | (u32)MAX_DMA_OVLY_COUNT); | 325 | (u32)MAX_DMA_OVLY_COUNT); |
326 | 326 | ||
327 | memcpy(token->vaddr, prog + page*MAX_DMA_OVLY_COUNT, left); | 327 | memcpy(token->vaddr, prog + page*MAX_DMA_OVLY_COUNT, left); |
328 | asd_write_reg_addr(asd_ha, OVLYDMAADR, token->dma_handle); | 328 | asd_write_reg_addr(asd_ha, OVLYDMAADR, token->dma_handle); |
329 | asd_write_reg_dword(asd_ha, OVLYDMACNT, left); | 329 | asd_write_reg_dword(asd_ha, OVLYDMACNT, left); |
330 | reg = !page ? RESETOVLYDMA : 0; | 330 | reg = !page ? RESETOVLYDMA : 0; |
331 | reg |= (STARTOVLYDMA | OVLYHALTERR); | 331 | reg |= (STARTOVLYDMA | OVLYHALTERR); |
332 | reg |= (lseq_mask ? (((u32)lseq_mask) << 8) : OVLYCSEQ); | 332 | reg |= (lseq_mask ? (((u32)lseq_mask) << 8) : OVLYCSEQ); |
333 | /* Start DMA. */ | 333 | /* Start DMA. */ |
334 | asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); | 334 | asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); |
335 | 335 | ||
336 | for (i = PAUSE_TRIES*100; i > 0; i--) { | 336 | for (i = PAUSE_TRIES*100; i > 0; i--) { |
337 | u32 dmadone = asd_read_reg_dword(asd_ha, OVLYDMACTL); | 337 | u32 dmadone = asd_read_reg_dword(asd_ha, OVLYDMACTL); |
338 | if (!(dmadone & OVLYDMAACT)) | 338 | if (!(dmadone & OVLYDMAACT)) |
339 | break; | 339 | break; |
340 | udelay(PAUSE_DELAY); | 340 | udelay(PAUSE_DELAY); |
341 | } | 341 | } |
342 | } | 342 | } |
343 | 343 | ||
344 | reg = asd_read_reg_dword(asd_ha, COMSTAT); | 344 | reg = asd_read_reg_dword(asd_ha, COMSTAT); |
345 | if (!(reg & OVLYDMADONE) || (reg & OVLYERR) | 345 | if (!(reg & OVLYDMADONE) || (reg & OVLYERR) |
346 | || (asd_read_reg_dword(asd_ha, CHIMINT) & DEVEXCEPT_MASK)){ | 346 | || (asd_read_reg_dword(asd_ha, CHIMINT) & DEVEXCEPT_MASK)){ |
347 | asd_printk("%s: error DMA-ing sequencer code\n", | 347 | asd_printk("%s: error DMA-ing sequencer code\n", |
348 | pci_name(asd_ha->pcidev)); | 348 | pci_name(asd_ha->pcidev)); |
349 | err = -ENODEV; | 349 | err = -ENODEV; |
350 | } | 350 | } |
351 | 351 | ||
352 | asd_free_coherent(asd_ha, token); | 352 | asd_free_coherent(asd_ha, token); |
353 | out: | 353 | out: |
354 | asd_write_reg_dword(asd_ha, COMSTATEN, comstaten); | 354 | asd_write_reg_dword(asd_ha, COMSTATEN, comstaten); |
355 | 355 | ||
356 | return err ? : asd_verify_seq(asd_ha, prog, size, lseq_mask); | 356 | return err ? : asd_verify_seq(asd_ha, prog, size, lseq_mask); |
357 | } | 357 | } |
358 | #else /* ASD_DMA_MODE_DOWNLOAD */ | 358 | #else /* ASD_DMA_MODE_DOWNLOAD */ |
359 | static int asd_download_seq(struct asd_ha_struct *asd_ha, const u8 *_prog, | 359 | static int asd_download_seq(struct asd_ha_struct *asd_ha, const u8 *_prog, |
360 | u32 size, u8 lseq_mask) | 360 | u32 size, u8 lseq_mask) |
361 | { | 361 | { |
362 | int i; | 362 | int i; |
363 | u32 reg = 0; | 363 | u32 reg = 0; |
364 | const u32 *prog = (u32 *) _prog; | 364 | const u32 *prog = (u32 *) _prog; |
365 | 365 | ||
366 | if (size % 4) { | 366 | if (size % 4) { |
367 | asd_printk("sequencer program not multiple of 4\n"); | 367 | asd_printk("sequencer program not multiple of 4\n"); |
368 | return -1; | 368 | return -1; |
369 | } | 369 | } |
370 | 370 | ||
371 | asd_pause_cseq(asd_ha); | 371 | asd_pause_cseq(asd_ha); |
372 | asd_pause_lseq(asd_ha, 0xFF); | 372 | asd_pause_lseq(asd_ha, 0xFF); |
373 | 373 | ||
374 | reg |= (lseq_mask ? (((u32)lseq_mask) << 8) : OVLYCSEQ); | 374 | reg |= (lseq_mask ? (((u32)lseq_mask) << 8) : OVLYCSEQ); |
375 | reg |= PIOCMODE; | 375 | reg |= PIOCMODE; |
376 | 376 | ||
377 | asd_write_reg_dword(asd_ha, OVLYDMACNT, size); | 377 | asd_write_reg_dword(asd_ha, OVLYDMACNT, size); |
378 | asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); | 378 | asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); |
379 | 379 | ||
380 | ASD_DPRINTK("downloading %s sequencer%s in PIO mode...\n", | 380 | ASD_DPRINTK("downloading %s sequencer%s in PIO mode...\n", |
381 | lseq_mask ? "LSEQ" : "CSEQ", lseq_mask ? "s" : ""); | 381 | lseq_mask ? "LSEQ" : "CSEQ", lseq_mask ? "s" : ""); |
382 | 382 | ||
383 | for (i = 0; i < size; i += 4, prog++) | 383 | for (i = 0; i < size; i += 4, prog++) |
384 | asd_write_reg_dword(asd_ha, SPIODATA, *prog); | 384 | asd_write_reg_dword(asd_ha, SPIODATA, *prog); |
385 | 385 | ||
386 | reg = (reg & ~PIOCMODE) | OVLYHALTERR; | 386 | reg = (reg & ~PIOCMODE) | OVLYHALTERR; |
387 | asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); | 387 | asd_write_reg_dword(asd_ha, OVLYDMACTL, reg); |
388 | 388 | ||
389 | return asd_verify_seq(asd_ha, _prog, size, lseq_mask); | 389 | return asd_verify_seq(asd_ha, _prog, size, lseq_mask); |
390 | } | 390 | } |
391 | #endif /* ASD_DMA_MODE_DOWNLOAD */ | 391 | #endif /* ASD_DMA_MODE_DOWNLOAD */ |
392 | 392 | ||
393 | /** | 393 | /** |
394 | * asd_seq_download_seqs - download the sequencer microcode | 394 | * asd_seq_download_seqs - download the sequencer microcode |
395 | * @asd_ha: pointer to host adapter structure | 395 | * @asd_ha: pointer to host adapter structure |
396 | * | 396 | * |
397 | * Download the central and link sequencer microcode. | 397 | * Download the central and link sequencer microcode. |
398 | */ | 398 | */ |
399 | static int asd_seq_download_seqs(struct asd_ha_struct *asd_ha) | 399 | static int asd_seq_download_seqs(struct asd_ha_struct *asd_ha) |
400 | { | 400 | { |
401 | int err; | 401 | int err; |
402 | 402 | ||
403 | if (!asd_ha->hw_prof.enabled_phys) { | 403 | if (!asd_ha->hw_prof.enabled_phys) { |
404 | asd_printk("%s: no enabled phys!\n", pci_name(asd_ha->pcidev)); | 404 | asd_printk("%s: no enabled phys!\n", pci_name(asd_ha->pcidev)); |
405 | return -ENODEV; | 405 | return -ENODEV; |
406 | } | 406 | } |
407 | 407 | ||
408 | /* Download the CSEQ */ | 408 | /* Download the CSEQ */ |
409 | ASD_DPRINTK("downloading CSEQ...\n"); | 409 | ASD_DPRINTK("downloading CSEQ...\n"); |
410 | err = asd_download_seq(asd_ha, cseq_code, cseq_code_size, 0); | 410 | err = asd_download_seq(asd_ha, cseq_code, cseq_code_size, 0); |
411 | if (err) { | 411 | if (err) { |
412 | asd_printk("CSEQ download failed:%d\n", err); | 412 | asd_printk("CSEQ download failed:%d\n", err); |
413 | return err; | 413 | return err; |
414 | } | 414 | } |
415 | 415 | ||
416 | /* Download the Link Sequencers code. All of the Link Sequencers | 416 | /* Download the Link Sequencers code. All of the Link Sequencers |
417 | * microcode can be downloaded at the same time. | 417 | * microcode can be downloaded at the same time. |
418 | */ | 418 | */ |
419 | ASD_DPRINTK("downloading LSEQs...\n"); | 419 | ASD_DPRINTK("downloading LSEQs...\n"); |
420 | err = asd_download_seq(asd_ha, lseq_code, lseq_code_size, | 420 | err = asd_download_seq(asd_ha, lseq_code, lseq_code_size, |
421 | asd_ha->hw_prof.enabled_phys); | 421 | asd_ha->hw_prof.enabled_phys); |
422 | if (err) { | 422 | if (err) { |
423 | /* Try it one at a time */ | 423 | /* Try it one at a time */ |
424 | u8 lseq; | 424 | u8 lseq; |
425 | u8 lseq_mask = asd_ha->hw_prof.enabled_phys; | 425 | u8 lseq_mask = asd_ha->hw_prof.enabled_phys; |
426 | 426 | ||
427 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { | 427 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { |
428 | err = asd_download_seq(asd_ha, lseq_code, | 428 | err = asd_download_seq(asd_ha, lseq_code, |
429 | lseq_code_size, 1<<lseq); | 429 | lseq_code_size, 1<<lseq); |
430 | if (err) | 430 | if (err) |
431 | break; | 431 | break; |
432 | } | 432 | } |
433 | } | 433 | } |
434 | if (err) | 434 | if (err) |
435 | asd_printk("LSEQs download failed:%d\n", err); | 435 | asd_printk("LSEQs download failed:%d\n", err); |
436 | 436 | ||
437 | return err; | 437 | return err; |
438 | } | 438 | } |
439 | 439 | ||
440 | /* ---------- Initializing the chip, chip memory, etc. ---------- */ | 440 | /* ---------- Initializing the chip, chip memory, etc. ---------- */ |
441 | 441 | ||
442 | /** | 442 | /** |
443 | * asd_init_cseq_mip - initialize CSEQ mode independent pages 4-7 | 443 | * asd_init_cseq_mip - initialize CSEQ mode independent pages 4-7 |
444 | * @asd_ha: pointer to host adapter structure | 444 | * @asd_ha: pointer to host adapter structure |
445 | */ | 445 | */ |
446 | static void asd_init_cseq_mip(struct asd_ha_struct *asd_ha) | 446 | static void asd_init_cseq_mip(struct asd_ha_struct *asd_ha) |
447 | { | 447 | { |
448 | /* CSEQ Mode Independent, page 4 setup. */ | 448 | /* CSEQ Mode Independent, page 4 setup. */ |
449 | asd_write_reg_word(asd_ha, CSEQ_Q_EXE_HEAD, 0xFFFF); | 449 | asd_write_reg_word(asd_ha, CSEQ_Q_EXE_HEAD, 0xFFFF); |
450 | asd_write_reg_word(asd_ha, CSEQ_Q_EXE_TAIL, 0xFFFF); | 450 | asd_write_reg_word(asd_ha, CSEQ_Q_EXE_TAIL, 0xFFFF); |
451 | asd_write_reg_word(asd_ha, CSEQ_Q_DONE_HEAD, 0xFFFF); | 451 | asd_write_reg_word(asd_ha, CSEQ_Q_DONE_HEAD, 0xFFFF); |
452 | asd_write_reg_word(asd_ha, CSEQ_Q_DONE_TAIL, 0xFFFF); | 452 | asd_write_reg_word(asd_ha, CSEQ_Q_DONE_TAIL, 0xFFFF); |
453 | asd_write_reg_word(asd_ha, CSEQ_Q_SEND_HEAD, 0xFFFF); | 453 | asd_write_reg_word(asd_ha, CSEQ_Q_SEND_HEAD, 0xFFFF); |
454 | asd_write_reg_word(asd_ha, CSEQ_Q_SEND_TAIL, 0xFFFF); | 454 | asd_write_reg_word(asd_ha, CSEQ_Q_SEND_TAIL, 0xFFFF); |
455 | asd_write_reg_word(asd_ha, CSEQ_Q_DMA2CHIM_HEAD, 0xFFFF); | 455 | asd_write_reg_word(asd_ha, CSEQ_Q_DMA2CHIM_HEAD, 0xFFFF); |
456 | asd_write_reg_word(asd_ha, CSEQ_Q_DMA2CHIM_TAIL, 0xFFFF); | 456 | asd_write_reg_word(asd_ha, CSEQ_Q_DMA2CHIM_TAIL, 0xFFFF); |
457 | asd_write_reg_word(asd_ha, CSEQ_Q_COPY_HEAD, 0xFFFF); | 457 | asd_write_reg_word(asd_ha, CSEQ_Q_COPY_HEAD, 0xFFFF); |
458 | asd_write_reg_word(asd_ha, CSEQ_Q_COPY_TAIL, 0xFFFF); | 458 | asd_write_reg_word(asd_ha, CSEQ_Q_COPY_TAIL, 0xFFFF); |
459 | asd_write_reg_word(asd_ha, CSEQ_REG0, 0); | 459 | asd_write_reg_word(asd_ha, CSEQ_REG0, 0); |
460 | asd_write_reg_word(asd_ha, CSEQ_REG1, 0); | 460 | asd_write_reg_word(asd_ha, CSEQ_REG1, 0); |
461 | asd_write_reg_dword(asd_ha, CSEQ_REG2, 0); | 461 | asd_write_reg_dword(asd_ha, CSEQ_REG2, 0); |
462 | asd_write_reg_byte(asd_ha, CSEQ_LINK_CTL_Q_MAP, 0); | 462 | asd_write_reg_byte(asd_ha, CSEQ_LINK_CTL_Q_MAP, 0); |
463 | { | 463 | { |
464 | u8 con = asd_read_reg_byte(asd_ha, CCONEXIST); | 464 | u8 con = asd_read_reg_byte(asd_ha, CCONEXIST); |
465 | u8 val = hweight8(con); | 465 | u8 val = hweight8(con); |
466 | asd_write_reg_byte(asd_ha, CSEQ_MAX_CSEQ_MODE, (val<<4)|val); | 466 | asd_write_reg_byte(asd_ha, CSEQ_MAX_CSEQ_MODE, (val<<4)|val); |
467 | } | 467 | } |
468 | asd_write_reg_word(asd_ha, CSEQ_FREE_LIST_HACK_COUNT, 0); | 468 | asd_write_reg_word(asd_ha, CSEQ_FREE_LIST_HACK_COUNT, 0); |
469 | 469 | ||
470 | /* CSEQ Mode independent, page 5 setup. */ | 470 | /* CSEQ Mode independent, page 5 setup. */ |
471 | asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_QUEUE, 0); | 471 | asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_QUEUE, 0); |
472 | asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_QUEUE+4, 0); | 472 | asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_QUEUE+4, 0); |
473 | asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_COUNT, 0); | 473 | asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_COUNT, 0); |
474 | asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_COUNT+4, 0); | 474 | asd_write_reg_dword(asd_ha, CSEQ_EST_NEXUS_REQ_COUNT+4, 0); |
475 | asd_write_reg_word(asd_ha, CSEQ_Q_EST_NEXUS_HEAD, 0xFFFF); | 475 | asd_write_reg_word(asd_ha, CSEQ_Q_EST_NEXUS_HEAD, 0xFFFF); |
476 | asd_write_reg_word(asd_ha, CSEQ_Q_EST_NEXUS_TAIL, 0xFFFF); | 476 | asd_write_reg_word(asd_ha, CSEQ_Q_EST_NEXUS_TAIL, 0xFFFF); |
477 | asd_write_reg_word(asd_ha, CSEQ_NEED_EST_NEXUS_SCB, 0); | 477 | asd_write_reg_word(asd_ha, CSEQ_NEED_EST_NEXUS_SCB, 0); |
478 | asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_REQ_HEAD, 0); | 478 | asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_REQ_HEAD, 0); |
479 | asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_REQ_TAIL, 0); | 479 | asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_REQ_TAIL, 0); |
480 | asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_SCB_OFFSET, 0); | 480 | asd_write_reg_byte(asd_ha, CSEQ_EST_NEXUS_SCB_OFFSET, 0); |
481 | 481 | ||
482 | /* CSEQ Mode independent, page 6 setup. */ | 482 | /* CSEQ Mode independent, page 6 setup. */ |
483 | asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_RET_ADDR0, 0); | 483 | asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_RET_ADDR0, 0); |
484 | asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_RET_ADDR1, 0); | 484 | asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_RET_ADDR1, 0); |
485 | asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_SCBPTR, 0); | 485 | asd_write_reg_word(asd_ha, CSEQ_INT_ROUT_SCBPTR, 0); |
486 | asd_write_reg_byte(asd_ha, CSEQ_INT_ROUT_MODE, 0); | 486 | asd_write_reg_byte(asd_ha, CSEQ_INT_ROUT_MODE, 0); |
487 | asd_write_reg_byte(asd_ha, CSEQ_ISR_SCRATCH_FLAGS, 0); | 487 | asd_write_reg_byte(asd_ha, CSEQ_ISR_SCRATCH_FLAGS, 0); |
488 | asd_write_reg_word(asd_ha, CSEQ_ISR_SAVE_SINDEX, 0); | 488 | asd_write_reg_word(asd_ha, CSEQ_ISR_SAVE_SINDEX, 0); |
489 | asd_write_reg_word(asd_ha, CSEQ_ISR_SAVE_DINDEX, 0); | 489 | asd_write_reg_word(asd_ha, CSEQ_ISR_SAVE_DINDEX, 0); |
490 | asd_write_reg_word(asd_ha, CSEQ_Q_MONIRTT_HEAD, 0xFFFF); | 490 | asd_write_reg_word(asd_ha, CSEQ_Q_MONIRTT_HEAD, 0xFFFF); |
491 | asd_write_reg_word(asd_ha, CSEQ_Q_MONIRTT_TAIL, 0xFFFF); | 491 | asd_write_reg_word(asd_ha, CSEQ_Q_MONIRTT_TAIL, 0xFFFF); |
492 | /* Calculate the free scb mask. */ | 492 | /* Calculate the free scb mask. */ |
493 | { | 493 | { |
494 | u16 cmdctx = asd_get_cmdctx_size(asd_ha); | 494 | u16 cmdctx = asd_get_cmdctx_size(asd_ha); |
495 | cmdctx = (~((cmdctx/128)-1)) >> 8; | 495 | cmdctx = (~((cmdctx/128)-1)) >> 8; |
496 | asd_write_reg_byte(asd_ha, CSEQ_FREE_SCB_MASK, (u8)cmdctx); | 496 | asd_write_reg_byte(asd_ha, CSEQ_FREE_SCB_MASK, (u8)cmdctx); |
497 | } | 497 | } |
498 | asd_write_reg_word(asd_ha, CSEQ_BUILTIN_FREE_SCB_HEAD, | 498 | asd_write_reg_word(asd_ha, CSEQ_BUILTIN_FREE_SCB_HEAD, |
499 | first_scb_site_no); | 499 | first_scb_site_no); |
500 | asd_write_reg_word(asd_ha, CSEQ_BUILTIN_FREE_SCB_TAIL, | 500 | asd_write_reg_word(asd_ha, CSEQ_BUILTIN_FREE_SCB_TAIL, |
501 | last_scb_site_no); | 501 | last_scb_site_no); |
502 | asd_write_reg_word(asd_ha, CSEQ_EXTENDED_FREE_SCB_HEAD, 0xFFFF); | 502 | asd_write_reg_word(asd_ha, CSEQ_EXTENDED_FREE_SCB_HEAD, 0xFFFF); |
503 | asd_write_reg_word(asd_ha, CSEQ_EXTENDED_FREE_SCB_TAIL, 0xFFFF); | 503 | asd_write_reg_word(asd_ha, CSEQ_EXTENDED_FREE_SCB_TAIL, 0xFFFF); |
504 | 504 | ||
505 | /* CSEQ Mode independent, page 7 setup. */ | 505 | /* CSEQ Mode independent, page 7 setup. */ |
506 | asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_QUEUE, 0); | 506 | asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_QUEUE, 0); |
507 | asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_QUEUE+4, 0); | 507 | asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_QUEUE+4, 0); |
508 | asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_COUNT, 0); | 508 | asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_COUNT, 0); |
509 | asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_COUNT+4, 0); | 509 | asd_write_reg_dword(asd_ha, CSEQ_EMPTY_REQ_COUNT+4, 0); |
510 | asd_write_reg_word(asd_ha, CSEQ_Q_EMPTY_HEAD, 0xFFFF); | 510 | asd_write_reg_word(asd_ha, CSEQ_Q_EMPTY_HEAD, 0xFFFF); |
511 | asd_write_reg_word(asd_ha, CSEQ_Q_EMPTY_TAIL, 0xFFFF); | 511 | asd_write_reg_word(asd_ha, CSEQ_Q_EMPTY_TAIL, 0xFFFF); |
512 | asd_write_reg_word(asd_ha, CSEQ_NEED_EMPTY_SCB, 0); | 512 | asd_write_reg_word(asd_ha, CSEQ_NEED_EMPTY_SCB, 0); |
513 | asd_write_reg_byte(asd_ha, CSEQ_EMPTY_REQ_HEAD, 0); | 513 | asd_write_reg_byte(asd_ha, CSEQ_EMPTY_REQ_HEAD, 0); |
514 | asd_write_reg_byte(asd_ha, CSEQ_EMPTY_REQ_TAIL, 0); | 514 | asd_write_reg_byte(asd_ha, CSEQ_EMPTY_REQ_TAIL, 0); |
515 | asd_write_reg_byte(asd_ha, CSEQ_EMPTY_SCB_OFFSET, 0); | 515 | asd_write_reg_byte(asd_ha, CSEQ_EMPTY_SCB_OFFSET, 0); |
516 | asd_write_reg_word(asd_ha, CSEQ_PRIMITIVE_DATA, 0); | 516 | asd_write_reg_word(asd_ha, CSEQ_PRIMITIVE_DATA, 0); |
517 | asd_write_reg_dword(asd_ha, CSEQ_TIMEOUT_CONST, 0); | 517 | asd_write_reg_dword(asd_ha, CSEQ_TIMEOUT_CONST, 0); |
518 | } | 518 | } |
519 | 519 | ||
520 | /** | 520 | /** |
521 | * asd_init_cseq_mdp - initialize CSEQ Mode dependent pages | 521 | * asd_init_cseq_mdp - initialize CSEQ Mode dependent pages |
522 | * @asd_ha: pointer to host adapter structure | 522 | * @asd_ha: pointer to host adapter structure |
523 | */ | 523 | */ |
524 | static void asd_init_cseq_mdp(struct asd_ha_struct *asd_ha) | 524 | static void asd_init_cseq_mdp(struct asd_ha_struct *asd_ha) |
525 | { | 525 | { |
526 | int i; | 526 | int i; |
527 | int moffs; | 527 | int moffs; |
528 | 528 | ||
529 | moffs = CSEQ_PAGE_SIZE * 2; | 529 | moffs = CSEQ_PAGE_SIZE * 2; |
530 | 530 | ||
531 | /* CSEQ Mode dependent, modes 0-7, page 0 setup. */ | 531 | /* CSEQ Mode dependent, modes 0-7, page 0 setup. */ |
532 | for (i = 0; i < 8; i++) { | 532 | for (i = 0; i < 8; i++) { |
533 | asd_write_reg_word(asd_ha, i*moffs+CSEQ_LRM_SAVE_SINDEX, 0); | 533 | asd_write_reg_word(asd_ha, i*moffs+CSEQ_LRM_SAVE_SINDEX, 0); |
534 | asd_write_reg_word(asd_ha, i*moffs+CSEQ_LRM_SAVE_SCBPTR, 0); | 534 | asd_write_reg_word(asd_ha, i*moffs+CSEQ_LRM_SAVE_SCBPTR, 0); |
535 | asd_write_reg_word(asd_ha, i*moffs+CSEQ_Q_LINK_HEAD, 0xFFFF); | 535 | asd_write_reg_word(asd_ha, i*moffs+CSEQ_Q_LINK_HEAD, 0xFFFF); |
536 | asd_write_reg_word(asd_ha, i*moffs+CSEQ_Q_LINK_TAIL, 0xFFFF); | 536 | asd_write_reg_word(asd_ha, i*moffs+CSEQ_Q_LINK_TAIL, 0xFFFF); |
537 | asd_write_reg_byte(asd_ha, i*moffs+CSEQ_LRM_SAVE_SCRPAGE, 0); | 537 | asd_write_reg_byte(asd_ha, i*moffs+CSEQ_LRM_SAVE_SCRPAGE, 0); |
538 | } | 538 | } |
539 | 539 | ||
540 | /* CSEQ Mode dependent, mode 0-7, page 1 and 2 shall be ignored. */ | 540 | /* CSEQ Mode dependent, mode 0-7, page 1 and 2 shall be ignored. */ |
541 | 541 | ||
542 | /* CSEQ Mode dependent, mode 8, page 0 setup. */ | 542 | /* CSEQ Mode dependent, mode 8, page 0 setup. */ |
543 | asd_write_reg_word(asd_ha, CSEQ_RET_ADDR, 0xFFFF); | 543 | asd_write_reg_word(asd_ha, CSEQ_RET_ADDR, 0xFFFF); |
544 | asd_write_reg_word(asd_ha, CSEQ_RET_SCBPTR, 0); | 544 | asd_write_reg_word(asd_ha, CSEQ_RET_SCBPTR, 0); |
545 | asd_write_reg_word(asd_ha, CSEQ_SAVE_SCBPTR, 0); | 545 | asd_write_reg_word(asd_ha, CSEQ_SAVE_SCBPTR, 0); |
546 | asd_write_reg_word(asd_ha, CSEQ_EMPTY_TRANS_CTX, 0); | 546 | asd_write_reg_word(asd_ha, CSEQ_EMPTY_TRANS_CTX, 0); |
547 | asd_write_reg_word(asd_ha, CSEQ_RESP_LEN, 0); | 547 | asd_write_reg_word(asd_ha, CSEQ_RESP_LEN, 0); |
548 | asd_write_reg_word(asd_ha, CSEQ_TMF_SCBPTR, 0); | 548 | asd_write_reg_word(asd_ha, CSEQ_TMF_SCBPTR, 0); |
549 | asd_write_reg_word(asd_ha, CSEQ_GLOBAL_PREV_SCB, 0); | 549 | asd_write_reg_word(asd_ha, CSEQ_GLOBAL_PREV_SCB, 0); |
550 | asd_write_reg_word(asd_ha, CSEQ_GLOBAL_HEAD, 0); | 550 | asd_write_reg_word(asd_ha, CSEQ_GLOBAL_HEAD, 0); |
551 | asd_write_reg_word(asd_ha, CSEQ_CLEAR_LU_HEAD, 0); | 551 | asd_write_reg_word(asd_ha, CSEQ_CLEAR_LU_HEAD, 0); |
552 | asd_write_reg_byte(asd_ha, CSEQ_TMF_OPCODE, 0); | 552 | asd_write_reg_byte(asd_ha, CSEQ_TMF_OPCODE, 0); |
553 | asd_write_reg_byte(asd_ha, CSEQ_SCRATCH_FLAGS, 0); | 553 | asd_write_reg_byte(asd_ha, CSEQ_SCRATCH_FLAGS, 0); |
554 | asd_write_reg_word(asd_ha, CSEQ_HSB_SITE, 0); | 554 | asd_write_reg_word(asd_ha, CSEQ_HSB_SITE, 0); |
555 | asd_write_reg_word(asd_ha, CSEQ_FIRST_INV_SCB_SITE, | 555 | asd_write_reg_word(asd_ha, CSEQ_FIRST_INV_SCB_SITE, |
556 | (u16)last_scb_site_no+1); | 556 | (u16)last_scb_site_no+1); |
557 | asd_write_reg_word(asd_ha, CSEQ_FIRST_INV_DDB_SITE, | 557 | asd_write_reg_word(asd_ha, CSEQ_FIRST_INV_DDB_SITE, |
558 | (u16)asd_ha->hw_prof.max_ddbs); | 558 | (u16)asd_ha->hw_prof.max_ddbs); |
559 | 559 | ||
560 | /* CSEQ Mode dependent, mode 8, page 1 setup. */ | 560 | /* CSEQ Mode dependent, mode 8, page 1 setup. */ |
561 | asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CLEAR, 0); | 561 | asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CLEAR, 0); |
562 | asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CLEAR + 4, 0); | 562 | asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CLEAR + 4, 0); |
563 | asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CHECK, 0); | 563 | asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CHECK, 0); |
564 | asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CHECK + 4, 0); | 564 | asd_write_reg_dword(asd_ha, CSEQ_LUN_TO_CHECK + 4, 0); |
565 | 565 | ||
566 | /* CSEQ Mode dependent, mode 8, page 2 setup. */ | 566 | /* CSEQ Mode dependent, mode 8, page 2 setup. */ |
567 | /* Tell the sequencer the bus address of the first SCB. */ | 567 | /* Tell the sequencer the bus address of the first SCB. */ |
568 | asd_write_reg_addr(asd_ha, CSEQ_HQ_NEW_POINTER, | 568 | asd_write_reg_addr(asd_ha, CSEQ_HQ_NEW_POINTER, |
569 | asd_ha->seq.next_scb.dma_handle); | 569 | asd_ha->seq.next_scb.dma_handle); |
570 | ASD_DPRINTK("First SCB dma_handle: 0x%llx\n", | 570 | ASD_DPRINTK("First SCB dma_handle: 0x%llx\n", |
571 | (unsigned long long)asd_ha->seq.next_scb.dma_handle); | 571 | (unsigned long long)asd_ha->seq.next_scb.dma_handle); |
572 | 572 | ||
573 | /* Tell the sequencer the first Done List entry address. */ | 573 | /* Tell the sequencer the first Done List entry address. */ |
574 | asd_write_reg_addr(asd_ha, CSEQ_HQ_DONE_BASE, | 574 | asd_write_reg_addr(asd_ha, CSEQ_HQ_DONE_BASE, |
575 | asd_ha->seq.actual_dl->dma_handle); | 575 | asd_ha->seq.actual_dl->dma_handle); |
576 | 576 | ||
577 | /* Initialize the Q_DONE_POINTER with the least significant | 577 | /* Initialize the Q_DONE_POINTER with the least significant |
578 | * 4 bytes of the first Done List address. */ | 578 | * 4 bytes of the first Done List address. */ |
579 | asd_write_reg_dword(asd_ha, CSEQ_HQ_DONE_POINTER, | 579 | asd_write_reg_dword(asd_ha, CSEQ_HQ_DONE_POINTER, |
580 | ASD_BUSADDR_LO(asd_ha->seq.actual_dl->dma_handle)); | 580 | ASD_BUSADDR_LO(asd_ha->seq.actual_dl->dma_handle)); |
581 | 581 | ||
582 | asd_write_reg_byte(asd_ha, CSEQ_HQ_DONE_PASS, ASD_DEF_DL_TOGGLE); | 582 | asd_write_reg_byte(asd_ha, CSEQ_HQ_DONE_PASS, ASD_DEF_DL_TOGGLE); |
583 | 583 | ||
584 | /* CSEQ Mode dependent, mode 8, page 3 shall be ignored. */ | 584 | /* CSEQ Mode dependent, mode 8, page 3 shall be ignored. */ |
585 | } | 585 | } |
586 | 586 | ||
587 | /** | 587 | /** |
588 | * asd_init_cseq_scratch -- setup and init CSEQ | 588 | * asd_init_cseq_scratch -- setup and init CSEQ |
589 | * @asd_ha: pointer to host adapter structure | 589 | * @asd_ha: pointer to host adapter structure |
590 | * | 590 | * |
591 | * Setup and initialize Central sequencers. Initialize the mode | 591 | * Setup and initialize Central sequencers. Initialize the mode |
592 | * independent and dependent scratch page to the default settings. | 592 | * independent and dependent scratch page to the default settings. |
593 | */ | 593 | */ |
594 | static void asd_init_cseq_scratch(struct asd_ha_struct *asd_ha) | 594 | static void asd_init_cseq_scratch(struct asd_ha_struct *asd_ha) |
595 | { | 595 | { |
596 | asd_init_cseq_mip(asd_ha); | 596 | asd_init_cseq_mip(asd_ha); |
597 | asd_init_cseq_mdp(asd_ha); | 597 | asd_init_cseq_mdp(asd_ha); |
598 | } | 598 | } |
599 | 599 | ||
600 | /** | 600 | /** |
601 | * asd_init_lseq_mip -- initialize LSEQ Mode independent pages 0-3 | 601 | * asd_init_lseq_mip -- initialize LSEQ Mode independent pages 0-3 |
602 | * @asd_ha: pointer to host adapter structure | 602 | * @asd_ha: pointer to host adapter structure |
603 | */ | 603 | */ |
604 | static void asd_init_lseq_mip(struct asd_ha_struct *asd_ha, u8 lseq) | 604 | static void asd_init_lseq_mip(struct asd_ha_struct *asd_ha, u8 lseq) |
605 | { | 605 | { |
606 | int i; | 606 | int i; |
607 | 607 | ||
608 | /* LSEQ Mode independent page 0 setup. */ | 608 | /* LSEQ Mode independent page 0 setup. */ |
609 | asd_write_reg_word(asd_ha, LmSEQ_Q_TGTXFR_HEAD(lseq), 0xFFFF); | 609 | asd_write_reg_word(asd_ha, LmSEQ_Q_TGTXFR_HEAD(lseq), 0xFFFF); |
610 | asd_write_reg_word(asd_ha, LmSEQ_Q_TGTXFR_TAIL(lseq), 0xFFFF); | 610 | asd_write_reg_word(asd_ha, LmSEQ_Q_TGTXFR_TAIL(lseq), 0xFFFF); |
611 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_NUMBER(lseq), lseq); | 611 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_NUMBER(lseq), lseq); |
612 | asd_write_reg_byte(asd_ha, LmSEQ_SCRATCH_FLAGS(lseq), | 612 | asd_write_reg_byte(asd_ha, LmSEQ_SCRATCH_FLAGS(lseq), |
613 | ASD_NOTIFY_ENABLE_SPINUP); | 613 | ASD_NOTIFY_ENABLE_SPINUP); |
614 | asd_write_reg_dword(asd_ha, LmSEQ_CONNECTION_STATE(lseq),0x08000000); | 614 | asd_write_reg_dword(asd_ha, LmSEQ_CONNECTION_STATE(lseq),0x08000000); |
615 | asd_write_reg_word(asd_ha, LmSEQ_CONCTL(lseq), 0); | 615 | asd_write_reg_word(asd_ha, LmSEQ_CONCTL(lseq), 0); |
616 | asd_write_reg_byte(asd_ha, LmSEQ_CONSTAT(lseq), 0); | 616 | asd_write_reg_byte(asd_ha, LmSEQ_CONSTAT(lseq), 0); |
617 | asd_write_reg_byte(asd_ha, LmSEQ_CONNECTION_MODES(lseq), 0); | 617 | asd_write_reg_byte(asd_ha, LmSEQ_CONNECTION_MODES(lseq), 0); |
618 | asd_write_reg_word(asd_ha, LmSEQ_REG1_ISR(lseq), 0); | 618 | asd_write_reg_word(asd_ha, LmSEQ_REG1_ISR(lseq), 0); |
619 | asd_write_reg_word(asd_ha, LmSEQ_REG2_ISR(lseq), 0); | 619 | asd_write_reg_word(asd_ha, LmSEQ_REG2_ISR(lseq), 0); |
620 | asd_write_reg_word(asd_ha, LmSEQ_REG3_ISR(lseq), 0); | 620 | asd_write_reg_word(asd_ha, LmSEQ_REG3_ISR(lseq), 0); |
621 | asd_write_reg_dword(asd_ha, LmSEQ_REG0_ISR(lseq), 0); | 621 | asd_write_reg_dword(asd_ha, LmSEQ_REG0_ISR(lseq), 0); |
622 | asd_write_reg_dword(asd_ha, LmSEQ_REG0_ISR(lseq)+4, 0); | 622 | asd_write_reg_dword(asd_ha, LmSEQ_REG0_ISR(lseq)+4, 0); |
623 | 623 | ||
624 | /* LSEQ Mode independent page 1 setup. */ | 624 | /* LSEQ Mode independent page 1 setup. */ |
625 | asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR0(lseq), 0xFFFF); | 625 | asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR0(lseq), 0xFFFF); |
626 | asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR1(lseq), 0xFFFF); | 626 | asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR1(lseq), 0xFFFF); |
627 | asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR2(lseq), 0xFFFF); | 627 | asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR2(lseq), 0xFFFF); |
628 | asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR3(lseq), 0xFFFF); | 628 | asd_write_reg_word(asd_ha, LmSEQ_EST_NEXUS_SCBPTR3(lseq), 0xFFFF); |
629 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE0(lseq), 0); | 629 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE0(lseq), 0); |
630 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE1(lseq), 0); | 630 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE1(lseq), 0); |
631 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE2(lseq), 0); | 631 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE2(lseq), 0); |
632 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE3(lseq), 0); | 632 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_OPCODE3(lseq), 0); |
633 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_HEAD(lseq), 0); | 633 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_HEAD(lseq), 0); |
634 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_TAIL(lseq), 0); | 634 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_SCB_TAIL(lseq), 0); |
635 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_BUF_AVAIL(lseq), 0); | 635 | asd_write_reg_byte(asd_ha, LmSEQ_EST_NEXUS_BUF_AVAIL(lseq), 0); |
636 | asd_write_reg_dword(asd_ha, LmSEQ_TIMEOUT_CONST(lseq), 0); | 636 | asd_write_reg_dword(asd_ha, LmSEQ_TIMEOUT_CONST(lseq), 0); |
637 | asd_write_reg_word(asd_ha, LmSEQ_ISR_SAVE_SINDEX(lseq), 0); | 637 | asd_write_reg_word(asd_ha, LmSEQ_ISR_SAVE_SINDEX(lseq), 0); |
638 | asd_write_reg_word(asd_ha, LmSEQ_ISR_SAVE_DINDEX(lseq), 0); | 638 | asd_write_reg_word(asd_ha, LmSEQ_ISR_SAVE_DINDEX(lseq), 0); |
639 | 639 | ||
640 | /* LSEQ Mode Independent page 2 setup. */ | 640 | /* LSEQ Mode Independent page 2 setup. */ |
641 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR0(lseq), 0xFFFF); | 641 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR0(lseq), 0xFFFF); |
642 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR1(lseq), 0xFFFF); | 642 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR1(lseq), 0xFFFF); |
643 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR2(lseq), 0xFFFF); | 643 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR2(lseq), 0xFFFF); |
644 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR3(lseq), 0xFFFF); | 644 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_SCB_PTR3(lseq), 0xFFFF); |
645 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD0(lseq), 0); | 645 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD0(lseq), 0); |
646 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD1(lseq), 0); | 646 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD1(lseq), 0); |
647 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD2(lseq), 0); | 647 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD2(lseq), 0); |
648 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD3(lseq), 0); | 648 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_OPCD3(lseq), 0); |
649 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_HEAD(lseq), 0); | 649 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_HEAD(lseq), 0); |
650 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_TAIL(lseq), 0); | 650 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_SCB_TAIL(lseq), 0); |
651 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_BUFS_AVAIL(lseq), 0); | 651 | asd_write_reg_byte(asd_ha, LmSEQ_EMPTY_BUFS_AVAIL(lseq), 0); |
652 | for (i = 0; i < 12; i += 4) | 652 | for (i = 0; i < 12; i += 4) |
653 | asd_write_reg_dword(asd_ha, LmSEQ_ATA_SCR_REGS(lseq) + i, 0); | 653 | asd_write_reg_dword(asd_ha, LmSEQ_ATA_SCR_REGS(lseq) + i, 0); |
654 | 654 | ||
655 | /* LSEQ Mode Independent page 3 setup. */ | 655 | /* LSEQ Mode Independent page 3 setup. */ |
656 | 656 | ||
657 | /* Device present timer timeout */ | 657 | /* Device present timer timeout */ |
658 | asd_write_reg_dword(asd_ha, LmSEQ_DEV_PRES_TMR_TOUT_CONST(lseq), | 658 | asd_write_reg_dword(asd_ha, LmSEQ_DEV_PRES_TMR_TOUT_CONST(lseq), |
659 | ASD_DEV_PRESENT_TIMEOUT); | 659 | ASD_DEV_PRESENT_TIMEOUT); |
660 | 660 | ||
661 | /* SATA interlock timer disabled */ | 661 | /* SATA interlock timer disabled */ |
662 | asd_write_reg_dword(asd_ha, LmSEQ_SATA_INTERLOCK_TIMEOUT(lseq), | 662 | asd_write_reg_dword(asd_ha, LmSEQ_SATA_INTERLOCK_TIMEOUT(lseq), |
663 | ASD_SATA_INTERLOCK_TIMEOUT); | 663 | ASD_SATA_INTERLOCK_TIMEOUT); |
664 | 664 | ||
665 | /* STP shutdown timer timeout constant, IGNORED by the sequencer, | 665 | /* STP shutdown timer timeout constant, IGNORED by the sequencer, |
666 | * always 0. */ | 666 | * always 0. */ |
667 | asd_write_reg_dword(asd_ha, LmSEQ_STP_SHUTDOWN_TIMEOUT(lseq), | 667 | asd_write_reg_dword(asd_ha, LmSEQ_STP_SHUTDOWN_TIMEOUT(lseq), |
668 | ASD_STP_SHUTDOWN_TIMEOUT); | 668 | ASD_STP_SHUTDOWN_TIMEOUT); |
669 | 669 | ||
670 | asd_write_reg_dword(asd_ha, LmSEQ_SRST_ASSERT_TIMEOUT(lseq), | 670 | asd_write_reg_dword(asd_ha, LmSEQ_SRST_ASSERT_TIMEOUT(lseq), |
671 | ASD_SRST_ASSERT_TIMEOUT); | 671 | ASD_SRST_ASSERT_TIMEOUT); |
672 | 672 | ||
673 | asd_write_reg_dword(asd_ha, LmSEQ_RCV_FIS_TIMEOUT(lseq), | 673 | asd_write_reg_dword(asd_ha, LmSEQ_RCV_FIS_TIMEOUT(lseq), |
674 | ASD_RCV_FIS_TIMEOUT); | 674 | ASD_RCV_FIS_TIMEOUT); |
675 | 675 | ||
676 | asd_write_reg_dword(asd_ha, LmSEQ_ONE_MILLISEC_TIMEOUT(lseq), | 676 | asd_write_reg_dword(asd_ha, LmSEQ_ONE_MILLISEC_TIMEOUT(lseq), |
677 | ASD_ONE_MILLISEC_TIMEOUT); | 677 | ASD_ONE_MILLISEC_TIMEOUT); |
678 | 678 | ||
679 | /* COM_INIT timer */ | 679 | /* COM_INIT timer */ |
680 | asd_write_reg_dword(asd_ha, LmSEQ_TEN_MS_COMINIT_TIMEOUT(lseq), | 680 | asd_write_reg_dword(asd_ha, LmSEQ_TEN_MS_COMINIT_TIMEOUT(lseq), |
681 | ASD_TEN_MILLISEC_TIMEOUT); | 681 | ASD_TEN_MILLISEC_TIMEOUT); |
682 | 682 | ||
683 | asd_write_reg_dword(asd_ha, LmSEQ_SMP_RCV_TIMEOUT(lseq), | 683 | asd_write_reg_dword(asd_ha, LmSEQ_SMP_RCV_TIMEOUT(lseq), |
684 | ASD_SMP_RCV_TIMEOUT); | 684 | ASD_SMP_RCV_TIMEOUT); |
685 | } | 685 | } |
686 | 686 | ||
687 | /** | 687 | /** |
688 | * asd_init_lseq_mdp -- initialize LSEQ mode dependent pages. | 688 | * asd_init_lseq_mdp -- initialize LSEQ mode dependent pages. |
689 | * @asd_ha: pointer to host adapter structure | 689 | * @asd_ha: pointer to host adapter structure |
690 | */ | 690 | */ |
691 | static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq) | 691 | static void asd_init_lseq_mdp(struct asd_ha_struct *asd_ha, int lseq) |
692 | { | 692 | { |
693 | int i; | 693 | int i; |
694 | u32 moffs; | 694 | u32 moffs; |
695 | u16 ret_addr[] = { | 695 | u16 ret_addr[] = { |
696 | 0xFFFF, /* mode 0 */ | 696 | 0xFFFF, /* mode 0 */ |
697 | 0xFFFF, /* mode 1 */ | 697 | 0xFFFF, /* mode 1 */ |
698 | mode2_task, /* mode 2 */ | 698 | mode2_task, /* mode 2 */ |
699 | 0, | 699 | 0, |
700 | 0xFFFF, /* mode 4/5 */ | 700 | 0xFFFF, /* mode 4/5 */ |
701 | 0xFFFF, /* mode 4/5 */ | 701 | 0xFFFF, /* mode 4/5 */ |
702 | }; | 702 | }; |
703 | 703 | ||
704 | /* | 704 | /* |
705 | * Mode 0,1,2 and 4/5 have common field on page 0 for the first | 705 | * Mode 0,1,2 and 4/5 have common field on page 0 for the first |
706 | * 14 bytes. | 706 | * 14 bytes. |
707 | */ | 707 | */ |
708 | for (i = 0; i < 3; i++) { | 708 | for (i = 0; i < 3; i++) { |
709 | moffs = i * LSEQ_MODE_SCRATCH_SIZE; | 709 | moffs = i * LSEQ_MODE_SCRATCH_SIZE; |
710 | asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR(lseq)+moffs, | 710 | asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR(lseq)+moffs, |
711 | ret_addr[i]); | 711 | ret_addr[i]); |
712 | asd_write_reg_word(asd_ha, LmSEQ_REG0_MODE(lseq)+moffs, 0); | 712 | asd_write_reg_word(asd_ha, LmSEQ_REG0_MODE(lseq)+moffs, 0); |
713 | asd_write_reg_word(asd_ha, LmSEQ_MODE_FLAGS(lseq)+moffs, 0); | 713 | asd_write_reg_word(asd_ha, LmSEQ_MODE_FLAGS(lseq)+moffs, 0); |
714 | asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR2(lseq)+moffs,0xFFFF); | 714 | asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR2(lseq)+moffs,0xFFFF); |
715 | asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR1(lseq)+moffs,0xFFFF); | 715 | asd_write_reg_word(asd_ha, LmSEQ_RET_ADDR1(lseq)+moffs,0xFFFF); |
716 | asd_write_reg_byte(asd_ha, LmSEQ_OPCODE_TO_CSEQ(lseq)+moffs,0); | 716 | asd_write_reg_byte(asd_ha, LmSEQ_OPCODE_TO_CSEQ(lseq)+moffs,0); |
717 | asd_write_reg_word(asd_ha, LmSEQ_DATA_TO_CSEQ(lseq)+moffs,0); | 717 | asd_write_reg_word(asd_ha, LmSEQ_DATA_TO_CSEQ(lseq)+moffs,0); |
718 | } | 718 | } |
719 | /* | 719 | /* |
720 | * Mode 5 page 0 overlaps the same scratch page with Mode 0 page 3. | 720 | * Mode 5 page 0 overlaps the same scratch page with Mode 0 page 3. |
721 | */ | 721 | */ |
722 | asd_write_reg_word(asd_ha, | 722 | asd_write_reg_word(asd_ha, |
723 | LmSEQ_RET_ADDR(lseq)+LSEQ_MODE5_PAGE0_OFFSET, | 723 | LmSEQ_RET_ADDR(lseq)+LSEQ_MODE5_PAGE0_OFFSET, |
724 | ret_addr[5]); | 724 | ret_addr[5]); |
725 | asd_write_reg_word(asd_ha, | 725 | asd_write_reg_word(asd_ha, |
726 | LmSEQ_REG0_MODE(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0); | 726 | LmSEQ_REG0_MODE(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0); |
727 | asd_write_reg_word(asd_ha, | 727 | asd_write_reg_word(asd_ha, |
728 | LmSEQ_MODE_FLAGS(lseq)+LSEQ_MODE5_PAGE0_OFFSET, 0); | 728 | LmSEQ_MODE_FLAGS(lseq)+LSEQ_MODE5_PAGE0_OFFSET, 0); |
729 | asd_write_reg_word(asd_ha, | 729 | asd_write_reg_word(asd_ha, |
730 | LmSEQ_RET_ADDR2(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0xFFFF); | 730 | LmSEQ_RET_ADDR2(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0xFFFF); |
731 | asd_write_reg_word(asd_ha, | 731 | asd_write_reg_word(asd_ha, |
732 | LmSEQ_RET_ADDR1(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0xFFFF); | 732 | LmSEQ_RET_ADDR1(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0xFFFF); |
733 | asd_write_reg_byte(asd_ha, | 733 | asd_write_reg_byte(asd_ha, |
734 | LmSEQ_OPCODE_TO_CSEQ(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0); | 734 | LmSEQ_OPCODE_TO_CSEQ(lseq)+LSEQ_MODE5_PAGE0_OFFSET,0); |
735 | asd_write_reg_word(asd_ha, | 735 | asd_write_reg_word(asd_ha, |
736 | LmSEQ_DATA_TO_CSEQ(lseq)+LSEQ_MODE5_PAGE0_OFFSET, 0); | 736 | LmSEQ_DATA_TO_CSEQ(lseq)+LSEQ_MODE5_PAGE0_OFFSET, 0); |
737 | 737 | ||
738 | /* LSEQ Mode dependent 0, page 0 setup. */ | 738 | /* LSEQ Mode dependent 0, page 0 setup. */ |
739 | asd_write_reg_word(asd_ha, LmSEQ_FIRST_INV_DDB_SITE(lseq), | 739 | asd_write_reg_word(asd_ha, LmSEQ_FIRST_INV_DDB_SITE(lseq), |
740 | (u16)asd_ha->hw_prof.max_ddbs); | 740 | (u16)asd_ha->hw_prof.max_ddbs); |
741 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_TRANS_CTX(lseq), 0); | 741 | asd_write_reg_word(asd_ha, LmSEQ_EMPTY_TRANS_CTX(lseq), 0); |
742 | asd_write_reg_word(asd_ha, LmSEQ_RESP_LEN(lseq), 0); | 742 | asd_write_reg_word(asd_ha, LmSEQ_RESP_LEN(lseq), 0); |
743 | asd_write_reg_word(asd_ha, LmSEQ_FIRST_INV_SCB_SITE(lseq), | 743 | asd_write_reg_word(asd_ha, LmSEQ_FIRST_INV_SCB_SITE(lseq), |
744 | (u16)last_scb_site_no+1); | 744 | (u16)last_scb_site_no+1); |
745 | asd_write_reg_word(asd_ha, LmSEQ_INTEN_SAVE(lseq), | 745 | asd_write_reg_word(asd_ha, LmSEQ_INTEN_SAVE(lseq), |
746 | (u16) ((LmM0INTEN_MASK & 0xFFFF0000) >> 16)); | 746 | (u16) ((LmM0INTEN_MASK & 0xFFFF0000) >> 16)); |
747 | asd_write_reg_word(asd_ha, LmSEQ_INTEN_SAVE(lseq) + 2, | 747 | asd_write_reg_word(asd_ha, LmSEQ_INTEN_SAVE(lseq) + 2, |
748 | (u16) LmM0INTEN_MASK & 0xFFFF); | 748 | (u16) LmM0INTEN_MASK & 0xFFFF); |
749 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_FRM_LEN(lseq), 0); | 749 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_FRM_LEN(lseq), 0); |
750 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_PROTOCOL(lseq), 0); | 750 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_PROTOCOL(lseq), 0); |
751 | asd_write_reg_byte(asd_ha, LmSEQ_RESP_STATUS(lseq), 0); | 751 | asd_write_reg_byte(asd_ha, LmSEQ_RESP_STATUS(lseq), 0); |
752 | asd_write_reg_byte(asd_ha, LmSEQ_LAST_LOADED_SGE(lseq), 0); | 752 | asd_write_reg_byte(asd_ha, LmSEQ_LAST_LOADED_SGE(lseq), 0); |
753 | asd_write_reg_word(asd_ha, LmSEQ_SAVE_SCBPTR(lseq), 0); | 753 | asd_write_reg_word(asd_ha, LmSEQ_SAVE_SCBPTR(lseq), 0); |
754 | 754 | ||
755 | /* LSEQ mode dependent, mode 1, page 0 setup. */ | 755 | /* LSEQ mode dependent, mode 1, page 0 setup. */ |
756 | asd_write_reg_word(asd_ha, LmSEQ_Q_XMIT_HEAD(lseq), 0xFFFF); | 756 | asd_write_reg_word(asd_ha, LmSEQ_Q_XMIT_HEAD(lseq), 0xFFFF); |
757 | asd_write_reg_word(asd_ha, LmSEQ_M1_EMPTY_TRANS_CTX(lseq), 0); | 757 | asd_write_reg_word(asd_ha, LmSEQ_M1_EMPTY_TRANS_CTX(lseq), 0); |
758 | asd_write_reg_word(asd_ha, LmSEQ_INI_CONN_TAG(lseq), 0); | 758 | asd_write_reg_word(asd_ha, LmSEQ_INI_CONN_TAG(lseq), 0); |
759 | asd_write_reg_byte(asd_ha, LmSEQ_FAILED_OPEN_STATUS(lseq), 0); | 759 | asd_write_reg_byte(asd_ha, LmSEQ_FAILED_OPEN_STATUS(lseq), 0); |
760 | asd_write_reg_byte(asd_ha, LmSEQ_XMIT_REQUEST_TYPE(lseq), 0); | 760 | asd_write_reg_byte(asd_ha, LmSEQ_XMIT_REQUEST_TYPE(lseq), 0); |
761 | asd_write_reg_byte(asd_ha, LmSEQ_M1_RESP_STATUS(lseq), 0); | 761 | asd_write_reg_byte(asd_ha, LmSEQ_M1_RESP_STATUS(lseq), 0); |
762 | asd_write_reg_byte(asd_ha, LmSEQ_M1_LAST_LOADED_SGE(lseq), 0); | 762 | asd_write_reg_byte(asd_ha, LmSEQ_M1_LAST_LOADED_SGE(lseq), 0); |
763 | asd_write_reg_word(asd_ha, LmSEQ_M1_SAVE_SCBPTR(lseq), 0); | 763 | asd_write_reg_word(asd_ha, LmSEQ_M1_SAVE_SCBPTR(lseq), 0); |
764 | 764 | ||
765 | /* LSEQ Mode dependent mode 2, page 0 setup */ | 765 | /* LSEQ Mode dependent mode 2, page 0 setup */ |
766 | asd_write_reg_word(asd_ha, LmSEQ_PORT_COUNTER(lseq), 0); | 766 | asd_write_reg_word(asd_ha, LmSEQ_PORT_COUNTER(lseq), 0); |
767 | asd_write_reg_word(asd_ha, LmSEQ_PM_TABLE_PTR(lseq), 0); | 767 | asd_write_reg_word(asd_ha, LmSEQ_PM_TABLE_PTR(lseq), 0); |
768 | asd_write_reg_word(asd_ha, LmSEQ_SATA_INTERLOCK_TMR_SAVE(lseq), 0); | 768 | asd_write_reg_word(asd_ha, LmSEQ_SATA_INTERLOCK_TMR_SAVE(lseq), 0); |
769 | asd_write_reg_word(asd_ha, LmSEQ_IP_BITL(lseq), 0); | 769 | asd_write_reg_word(asd_ha, LmSEQ_IP_BITL(lseq), 0); |
770 | asd_write_reg_word(asd_ha, LmSEQ_COPY_SMP_CONN_TAG(lseq), 0); | 770 | asd_write_reg_word(asd_ha, LmSEQ_COPY_SMP_CONN_TAG(lseq), 0); |
771 | asd_write_reg_byte(asd_ha, LmSEQ_P0M2_OFFS1AH(lseq), 0); | 771 | asd_write_reg_byte(asd_ha, LmSEQ_P0M2_OFFS1AH(lseq), 0); |
772 | 772 | ||
773 | /* LSEQ Mode dependent, mode 4/5, page 0 setup. */ | 773 | /* LSEQ Mode dependent, mode 4/5, page 0 setup. */ |
774 | asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_STATUS(lseq), 0); | 774 | asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_STATUS(lseq), 0); |
775 | asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_MODE(lseq), 0); | 775 | asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_MODE(lseq), 0); |
776 | asd_write_reg_word(asd_ha, LmSEQ_Q_LINK_HEAD(lseq), 0xFFFF); | 776 | asd_write_reg_word(asd_ha, LmSEQ_Q_LINK_HEAD(lseq), 0xFFFF); |
777 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_ERR(lseq), 0); | 777 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_RST_ERR(lseq), 0); |
778 | asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_SIGNALS(lseq), 0); | 778 | asd_write_reg_byte(asd_ha, LmSEQ_SAVED_OOB_SIGNALS(lseq), 0); |
779 | asd_write_reg_byte(asd_ha, LmSEQ_SAS_RESET_MODE(lseq), 0); | 779 | asd_write_reg_byte(asd_ha, LmSEQ_SAS_RESET_MODE(lseq), 0); |
780 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_RESET_RETRY_COUNT(lseq), 0); | 780 | asd_write_reg_byte(asd_ha, LmSEQ_LINK_RESET_RETRY_COUNT(lseq), 0); |
781 | asd_write_reg_byte(asd_ha, LmSEQ_NUM_LINK_RESET_RETRIES(lseq), 0); | 781 | asd_write_reg_byte(asd_ha, LmSEQ_NUM_LINK_RESET_RETRIES(lseq), 0); |
782 | asd_write_reg_word(asd_ha, LmSEQ_OOB_INT_ENABLES(lseq), 0); | 782 | asd_write_reg_word(asd_ha, LmSEQ_OOB_INT_ENABLES(lseq), 0); |
783 | /* | 783 | /* |
784 | * Set the desired interval between transmissions of the NOTIFY | 784 | * Set the desired interval between transmissions of the NOTIFY |
785 | * (ENABLE SPINUP) primitive. Must be initialized to val - 1. | 785 | * (ENABLE SPINUP) primitive. Must be initialized to val - 1. |
786 | */ | 786 | */ |
787 | asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_TIMEOUT(lseq), | 787 | asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_TIMEOUT(lseq), |
788 | ASD_NOTIFY_TIMEOUT - 1); | 788 | ASD_NOTIFY_TIMEOUT - 1); |
789 | /* No delay for the first NOTIFY to be sent to the attached target. */ | 789 | /* No delay for the first NOTIFY to be sent to the attached target. */ |
790 | asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_DOWN_COUNT(lseq), | 790 | asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_DOWN_COUNT(lseq), |
791 | ASD_NOTIFY_DOWN_COUNT); | 791 | ASD_NOTIFY_DOWN_COUNT); |
792 | asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(lseq), | 792 | asd_write_reg_word(asd_ha, LmSEQ_NOTIFY_TIMER_INITIAL_COUNT(lseq), |
793 | ASD_NOTIFY_DOWN_COUNT); | 793 | ASD_NOTIFY_DOWN_COUNT); |
794 | 794 | ||
795 | /* LSEQ Mode dependent, mode 0 and 1, page 1 setup. */ | 795 | /* LSEQ Mode dependent, mode 0 and 1, page 1 setup. */ |
796 | for (i = 0; i < 2; i++) { | 796 | for (i = 0; i < 2; i++) { |
797 | int j; | 797 | int j; |
798 | /* Start from Page 1 of Mode 0 and 1. */ | 798 | /* Start from Page 1 of Mode 0 and 1. */ |
799 | moffs = LSEQ_PAGE_SIZE + i*LSEQ_MODE_SCRATCH_SIZE; | 799 | moffs = LSEQ_PAGE_SIZE + i*LSEQ_MODE_SCRATCH_SIZE; |
800 | /* All the fields of page 1 can be initialized to 0. */ | 800 | /* All the fields of page 1 can be initialized to 0. */ |
801 | for (j = 0; j < LSEQ_PAGE_SIZE; j += 4) | 801 | for (j = 0; j < LSEQ_PAGE_SIZE; j += 4) |
802 | asd_write_reg_dword(asd_ha, LmSCRATCH(lseq)+moffs+j,0); | 802 | asd_write_reg_dword(asd_ha, LmSCRATCH(lseq)+moffs+j,0); |
803 | } | 803 | } |
804 | 804 | ||
805 | /* LSEQ Mode dependent, mode 2, page 1 setup. */ | 805 | /* LSEQ Mode dependent, mode 2, page 1 setup. */ |
806 | asd_write_reg_dword(asd_ha, LmSEQ_INVALID_DWORD_COUNT(lseq), 0); | 806 | asd_write_reg_dword(asd_ha, LmSEQ_INVALID_DWORD_COUNT(lseq), 0); |
807 | asd_write_reg_dword(asd_ha, LmSEQ_DISPARITY_ERROR_COUNT(lseq), 0); | 807 | asd_write_reg_dword(asd_ha, LmSEQ_DISPARITY_ERROR_COUNT(lseq), 0); |
808 | asd_write_reg_dword(asd_ha, LmSEQ_LOSS_OF_SYNC_COUNT(lseq), 0); | 808 | asd_write_reg_dword(asd_ha, LmSEQ_LOSS_OF_SYNC_COUNT(lseq), 0); |
809 | 809 | ||
810 | /* LSEQ Mode dependent, mode 4/5, page 1. */ | 810 | /* LSEQ Mode dependent, mode 4/5, page 1. */ |
811 | for (i = 0; i < LSEQ_PAGE_SIZE; i+=4) | 811 | for (i = 0; i < LSEQ_PAGE_SIZE; i+=4) |
812 | asd_write_reg_dword(asd_ha, LmSEQ_FRAME_TYPE_MASK(lseq)+i, 0); | 812 | asd_write_reg_dword(asd_ha, LmSEQ_FRAME_TYPE_MASK(lseq)+i, 0); |
813 | asd_write_reg_byte(asd_ha, LmSEQ_FRAME_TYPE_MASK(lseq), 0xFF); | 813 | asd_write_reg_byte(asd_ha, LmSEQ_FRAME_TYPE_MASK(lseq), 0xFF); |
814 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq), 0xFF); | 814 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq), 0xFF); |
815 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq)+1,0xFF); | 815 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq)+1,0xFF); |
816 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq)+2,0xFF); | 816 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_DEST_ADDR_MASK(lseq)+2,0xFF); |
817 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq), 0xFF); | 817 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq), 0xFF); |
818 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq)+1, 0xFF); | 818 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq)+1, 0xFF); |
819 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq)+2, 0xFF); | 819 | asd_write_reg_byte(asd_ha, LmSEQ_HASHED_SRC_ADDR_MASK(lseq)+2, 0xFF); |
820 | asd_write_reg_dword(asd_ha, LmSEQ_DATA_OFFSET(lseq), 0xFFFFFFFF); | 820 | asd_write_reg_dword(asd_ha, LmSEQ_DATA_OFFSET(lseq), 0xFFFFFFFF); |
821 | 821 | ||
822 | /* LSEQ Mode dependent, mode 0, page 2 setup. */ | 822 | /* LSEQ Mode dependent, mode 0, page 2 setup. */ |
823 | asd_write_reg_dword(asd_ha, LmSEQ_SMP_RCV_TIMER_TERM_TS(lseq), 0); | 823 | asd_write_reg_dword(asd_ha, LmSEQ_SMP_RCV_TIMER_TERM_TS(lseq), 0); |
824 | asd_write_reg_byte(asd_ha, LmSEQ_DEVICE_BITS(lseq), 0); | 824 | asd_write_reg_byte(asd_ha, LmSEQ_DEVICE_BITS(lseq), 0); |
825 | asd_write_reg_word(asd_ha, LmSEQ_SDB_DDB(lseq), 0); | 825 | asd_write_reg_word(asd_ha, LmSEQ_SDB_DDB(lseq), 0); |
826 | asd_write_reg_byte(asd_ha, LmSEQ_SDB_NUM_TAGS(lseq), 0); | 826 | asd_write_reg_byte(asd_ha, LmSEQ_SDB_NUM_TAGS(lseq), 0); |
827 | asd_write_reg_byte(asd_ha, LmSEQ_SDB_CURR_TAG(lseq), 0); | 827 | asd_write_reg_byte(asd_ha, LmSEQ_SDB_CURR_TAG(lseq), 0); |
828 | 828 | ||
829 | /* LSEQ Mode Dependent 1, page 2 setup. */ | 829 | /* LSEQ Mode Dependent 1, page 2 setup. */ |
830 | asd_write_reg_dword(asd_ha, LmSEQ_TX_ID_ADDR_FRAME(lseq), 0); | 830 | asd_write_reg_dword(asd_ha, LmSEQ_TX_ID_ADDR_FRAME(lseq), 0); |
831 | asd_write_reg_dword(asd_ha, LmSEQ_TX_ID_ADDR_FRAME(lseq)+4, 0); | 831 | asd_write_reg_dword(asd_ha, LmSEQ_TX_ID_ADDR_FRAME(lseq)+4, 0); |
832 | asd_write_reg_dword(asd_ha, LmSEQ_OPEN_TIMER_TERM_TS(lseq), 0); | 832 | asd_write_reg_dword(asd_ha, LmSEQ_OPEN_TIMER_TERM_TS(lseq), 0); |
833 | asd_write_reg_dword(asd_ha, LmSEQ_SRST_AS_TIMER_TERM_TS(lseq), 0); | 833 | asd_write_reg_dword(asd_ha, LmSEQ_SRST_AS_TIMER_TERM_TS(lseq), 0); |
834 | asd_write_reg_dword(asd_ha, LmSEQ_LAST_LOADED_SG_EL(lseq), 0); | 834 | asd_write_reg_dword(asd_ha, LmSEQ_LAST_LOADED_SG_EL(lseq), 0); |
835 | 835 | ||
836 | /* LSEQ Mode Dependent 2, page 2 setup. */ | 836 | /* LSEQ Mode Dependent 2, page 2 setup. */ |
837 | /* The LmSEQ_STP_SHUTDOWN_TIMER_TERM_TS is IGNORED by the sequencer, | 837 | /* The LmSEQ_STP_SHUTDOWN_TIMER_TERM_TS is IGNORED by the sequencer, |
838 | * i.e. always 0. */ | 838 | * i.e. always 0. */ |
839 | asd_write_reg_dword(asd_ha, LmSEQ_STP_SHUTDOWN_TIMER_TERM_TS(lseq),0); | 839 | asd_write_reg_dword(asd_ha, LmSEQ_STP_SHUTDOWN_TIMER_TERM_TS(lseq),0); |
840 | asd_write_reg_dword(asd_ha, LmSEQ_CLOSE_TIMER_TERM_TS(lseq), 0); | 840 | asd_write_reg_dword(asd_ha, LmSEQ_CLOSE_TIMER_TERM_TS(lseq), 0); |
841 | asd_write_reg_dword(asd_ha, LmSEQ_BREAK_TIMER_TERM_TS(lseq), 0); | 841 | asd_write_reg_dword(asd_ha, LmSEQ_BREAK_TIMER_TERM_TS(lseq), 0); |
842 | asd_write_reg_dword(asd_ha, LmSEQ_DWS_RESET_TIMER_TERM_TS(lseq), 0); | 842 | asd_write_reg_dword(asd_ha, LmSEQ_DWS_RESET_TIMER_TERM_TS(lseq), 0); |
843 | asd_write_reg_dword(asd_ha,LmSEQ_SATA_INTERLOCK_TIMER_TERM_TS(lseq),0); | 843 | asd_write_reg_dword(asd_ha,LmSEQ_SATA_INTERLOCK_TIMER_TERM_TS(lseq),0); |
844 | asd_write_reg_dword(asd_ha, LmSEQ_MCTL_TIMER_TERM_TS(lseq), 0); | 844 | asd_write_reg_dword(asd_ha, LmSEQ_MCTL_TIMER_TERM_TS(lseq), 0); |
845 | 845 | ||
846 | /* LSEQ Mode Dependent 4/5, page 2 setup. */ | 846 | /* LSEQ Mode Dependent 4/5, page 2 setup. */ |
847 | asd_write_reg_dword(asd_ha, LmSEQ_COMINIT_TIMER_TERM_TS(lseq), 0); | 847 | asd_write_reg_dword(asd_ha, LmSEQ_COMINIT_TIMER_TERM_TS(lseq), 0); |
848 | asd_write_reg_dword(asd_ha, LmSEQ_RCV_ID_TIMER_TERM_TS(lseq), 0); | 848 | asd_write_reg_dword(asd_ha, LmSEQ_RCV_ID_TIMER_TERM_TS(lseq), 0); |
849 | asd_write_reg_dword(asd_ha, LmSEQ_RCV_FIS_TIMER_TERM_TS(lseq), 0); | 849 | asd_write_reg_dword(asd_ha, LmSEQ_RCV_FIS_TIMER_TERM_TS(lseq), 0); |
850 | asd_write_reg_dword(asd_ha, LmSEQ_DEV_PRES_TIMER_TERM_TS(lseq), 0); | 850 | asd_write_reg_dword(asd_ha, LmSEQ_DEV_PRES_TIMER_TERM_TS(lseq), 0); |
851 | } | 851 | } |
852 | 852 | ||
853 | /** | 853 | /** |
854 | * asd_init_lseq_scratch -- setup and init link sequencers | 854 | * asd_init_lseq_scratch -- setup and init link sequencers |
855 | * @asd_ha: pointer to host adapter struct | 855 | * @asd_ha: pointer to host adapter struct |
856 | */ | 856 | */ |
857 | static void asd_init_lseq_scratch(struct asd_ha_struct *asd_ha) | 857 | static void asd_init_lseq_scratch(struct asd_ha_struct *asd_ha) |
858 | { | 858 | { |
859 | u8 lseq; | 859 | u8 lseq; |
860 | u8 lseq_mask; | 860 | u8 lseq_mask; |
861 | 861 | ||
862 | lseq_mask = asd_ha->hw_prof.enabled_phys; | 862 | lseq_mask = asd_ha->hw_prof.enabled_phys; |
863 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { | 863 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { |
864 | asd_init_lseq_mip(asd_ha, lseq); | 864 | asd_init_lseq_mip(asd_ha, lseq); |
865 | asd_init_lseq_mdp(asd_ha, lseq); | 865 | asd_init_lseq_mdp(asd_ha, lseq); |
866 | } | 866 | } |
867 | } | 867 | } |
868 | 868 | ||
869 | /** | 869 | /** |
870 | * asd_init_scb_sites -- initialize sequencer SCB sites (memory). | 870 | * asd_init_scb_sites -- initialize sequencer SCB sites (memory). |
871 | * @asd_ha: pointer to host adapter structure | 871 | * @asd_ha: pointer to host adapter structure |
872 | * | 872 | * |
873 | * This should be done before initializing common CSEQ and LSEQ | 873 | * This should be done before initializing common CSEQ and LSEQ |
874 | * scratch since those areas depend on some computed values here, | 874 | * scratch since those areas depend on some computed values here, |
875 | * last_scb_site_no, etc. | 875 | * last_scb_site_no, etc. |
876 | */ | 876 | */ |
877 | static void asd_init_scb_sites(struct asd_ha_struct *asd_ha) | 877 | static void asd_init_scb_sites(struct asd_ha_struct *asd_ha) |
878 | { | 878 | { |
879 | u16 site_no; | 879 | u16 site_no; |
880 | u16 max_scbs = 0; | 880 | u16 max_scbs = 0; |
881 | 881 | ||
882 | for (site_no = asd_ha->hw_prof.max_scbs-1; | 882 | for (site_no = asd_ha->hw_prof.max_scbs-1; |
883 | site_no != (u16) -1; | 883 | site_no != (u16) -1; |
884 | site_no--) { | 884 | site_no--) { |
885 | u16 i; | 885 | u16 i; |
886 | 886 | ||
887 | /* Initialize all fields in the SCB site to 0. */ | 887 | /* Initialize all fields in the SCB site to 0. */ |
888 | for (i = 0; i < ASD_SCB_SIZE; i += 4) | 888 | for (i = 0; i < ASD_SCB_SIZE; i += 4) |
889 | asd_scbsite_write_dword(asd_ha, site_no, i, 0); | 889 | asd_scbsite_write_dword(asd_ha, site_no, i, 0); |
890 | 890 | ||
891 | /* Initialize SCB Site Opcode field to invalid. */ | 891 | /* Initialize SCB Site Opcode field to invalid. */ |
892 | asd_scbsite_write_byte(asd_ha, site_no, | 892 | asd_scbsite_write_byte(asd_ha, site_no, |
893 | offsetof(struct scb_header, opcode), | 893 | offsetof(struct scb_header, opcode), |
894 | 0xFF); | 894 | 0xFF); |
895 | 895 | ||
896 | /* Initialize SCB Site Flags field to mean a response | 896 | /* Initialize SCB Site Flags field to mean a response |
897 | * frame has been received. This means inadvertent | 897 | * frame has been received. This means inadvertent |
898 | * frames received to be dropped. */ | 898 | * frames received to be dropped. */ |
899 | asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01); | 899 | asd_scbsite_write_byte(asd_ha, site_no, 0x49, 0x01); |
900 | 900 | ||
901 | /* Workaround needed by SEQ to fix a SATA issue is to exclude | 901 | /* Workaround needed by SEQ to fix a SATA issue is to exclude |
902 | * certain SCB sites from the free list. */ | 902 | * certain SCB sites from the free list. */ |
903 | if (!SCB_SITE_VALID(site_no)) | 903 | if (!SCB_SITE_VALID(site_no)) |
904 | continue; | 904 | continue; |
905 | 905 | ||
906 | if (last_scb_site_no == 0) | 906 | if (last_scb_site_no == 0) |
907 | last_scb_site_no = site_no; | 907 | last_scb_site_no = site_no; |
908 | 908 | ||
909 | /* For every SCB site, we need to initialize the | 909 | /* For every SCB site, we need to initialize the |
910 | * following fields: Q_NEXT, SCB_OPCODE, SCB_FLAGS, | 910 | * following fields: Q_NEXT, SCB_OPCODE, SCB_FLAGS, |
911 | * and SG Element Flag. */ | 911 | * and SG Element Flag. */ |
912 | 912 | ||
913 | /* Q_NEXT field of the last SCB is invalidated. */ | 913 | /* Q_NEXT field of the last SCB is invalidated. */ |
914 | asd_scbsite_write_word(asd_ha, site_no, 0, first_scb_site_no); | 914 | asd_scbsite_write_word(asd_ha, site_no, 0, first_scb_site_no); |
915 | 915 | ||
916 | first_scb_site_no = site_no; | 916 | first_scb_site_no = site_no; |
917 | max_scbs++; | 917 | max_scbs++; |
918 | } | 918 | } |
919 | asd_ha->hw_prof.max_scbs = max_scbs; | 919 | asd_ha->hw_prof.max_scbs = max_scbs; |
920 | ASD_DPRINTK("max_scbs:%d\n", asd_ha->hw_prof.max_scbs); | 920 | ASD_DPRINTK("max_scbs:%d\n", asd_ha->hw_prof.max_scbs); |
921 | ASD_DPRINTK("first_scb_site_no:0x%x\n", first_scb_site_no); | 921 | ASD_DPRINTK("first_scb_site_no:0x%x\n", first_scb_site_no); |
922 | ASD_DPRINTK("last_scb_site_no:0x%x\n", last_scb_site_no); | 922 | ASD_DPRINTK("last_scb_site_no:0x%x\n", last_scb_site_no); |
923 | } | 923 | } |
924 | 924 | ||
925 | /** | 925 | /** |
926 | * asd_init_cseq_cio - initialize CSEQ CIO registers | 926 | * asd_init_cseq_cio - initialize CSEQ CIO registers |
927 | * @asd_ha: pointer to host adapter structure | 927 | * @asd_ha: pointer to host adapter structure |
928 | */ | 928 | */ |
929 | static void asd_init_cseq_cio(struct asd_ha_struct *asd_ha) | 929 | static void asd_init_cseq_cio(struct asd_ha_struct *asd_ha) |
930 | { | 930 | { |
931 | int i; | 931 | int i; |
932 | 932 | ||
933 | asd_write_reg_byte(asd_ha, CSEQCOMINTEN, 0); | 933 | asd_write_reg_byte(asd_ha, CSEQCOMINTEN, 0); |
934 | asd_write_reg_byte(asd_ha, CSEQDLCTL, ASD_DL_SIZE_BITS); | 934 | asd_write_reg_byte(asd_ha, CSEQDLCTL, ASD_DL_SIZE_BITS); |
935 | asd_write_reg_byte(asd_ha, CSEQDLOFFS, 0); | 935 | asd_write_reg_byte(asd_ha, CSEQDLOFFS, 0); |
936 | asd_write_reg_byte(asd_ha, CSEQDLOFFS+1, 0); | 936 | asd_write_reg_byte(asd_ha, CSEQDLOFFS+1, 0); |
937 | asd_ha->seq.scbpro = 0; | 937 | asd_ha->seq.scbpro = 0; |
938 | asd_write_reg_dword(asd_ha, SCBPRO, 0); | 938 | asd_write_reg_dword(asd_ha, SCBPRO, 0); |
939 | asd_write_reg_dword(asd_ha, CSEQCON, 0); | 939 | asd_write_reg_dword(asd_ha, CSEQCON, 0); |
940 | 940 | ||
941 | /* Initialize CSEQ Mode 11 Interrupt Vectors. | 941 | /* Initialize CSEQ Mode 11 Interrupt Vectors. |
942 | * The addresses are 16 bit wide and in dword units. | 942 | * The addresses are 16 bit wide and in dword units. |
943 | * The values of their macros are in byte units. | 943 | * The values of their macros are in byte units. |
944 | * Thus we have to divide by 4. */ | 944 | * Thus we have to divide by 4. */ |
945 | asd_write_reg_word(asd_ha, CM11INTVEC0, cseq_vecs[0]); | 945 | asd_write_reg_word(asd_ha, CM11INTVEC0, cseq_vecs[0]); |
946 | asd_write_reg_word(asd_ha, CM11INTVEC1, cseq_vecs[1]); | 946 | asd_write_reg_word(asd_ha, CM11INTVEC1, cseq_vecs[1]); |
947 | asd_write_reg_word(asd_ha, CM11INTVEC2, cseq_vecs[2]); | 947 | asd_write_reg_word(asd_ha, CM11INTVEC2, cseq_vecs[2]); |
948 | 948 | ||
949 | /* Enable ARP2HALTC (ARP2 Halted from Halt Code Write). */ | 949 | /* Enable ARP2HALTC (ARP2 Halted from Halt Code Write). */ |
950 | asd_write_reg_byte(asd_ha, CARP2INTEN, EN_ARP2HALTC); | 950 | asd_write_reg_byte(asd_ha, CARP2INTEN, EN_ARP2HALTC); |
951 | 951 | ||
952 | /* Initialize CSEQ Scratch Page to 0x04. */ | 952 | /* Initialize CSEQ Scratch Page to 0x04. */ |
953 | asd_write_reg_byte(asd_ha, CSCRATCHPAGE, 0x04); | 953 | asd_write_reg_byte(asd_ha, CSCRATCHPAGE, 0x04); |
954 | 954 | ||
955 | /* Initialize CSEQ Mode[0-8] Dependent registers. */ | 955 | /* Initialize CSEQ Mode[0-8] Dependent registers. */ |
956 | /* Initialize Scratch Page to 0. */ | 956 | /* Initialize Scratch Page to 0. */ |
957 | for (i = 0; i < 9; i++) | 957 | for (i = 0; i < 9; i++) |
958 | asd_write_reg_byte(asd_ha, CMnSCRATCHPAGE(i), 0); | 958 | asd_write_reg_byte(asd_ha, CMnSCRATCHPAGE(i), 0); |
959 | 959 | ||
960 | /* Reset the ARP2 Program Count. */ | 960 | /* Reset the ARP2 Program Count. */ |
961 | asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop); | 961 | asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop); |
962 | 962 | ||
963 | for (i = 0; i < 8; i++) { | 963 | for (i = 0; i < 8; i++) { |
964 | /* Initialize Mode n Link m Interrupt Enable. */ | 964 | /* Initialize Mode n Link m Interrupt Enable. */ |
965 | asd_write_reg_dword(asd_ha, CMnINTEN(i), EN_CMnRSPMBXF); | 965 | asd_write_reg_dword(asd_ha, CMnINTEN(i), EN_CMnRSPMBXF); |
966 | /* Initialize Mode n Request Mailbox. */ | 966 | /* Initialize Mode n Request Mailbox. */ |
967 | asd_write_reg_dword(asd_ha, CMnREQMBX(i), 0); | 967 | asd_write_reg_dword(asd_ha, CMnREQMBX(i), 0); |
968 | } | 968 | } |
969 | } | 969 | } |
970 | 970 | ||
971 | /** | 971 | /** |
972 | * asd_init_lseq_cio -- initialize LmSEQ CIO registers | 972 | * asd_init_lseq_cio -- initialize LmSEQ CIO registers |
973 | * @asd_ha: pointer to host adapter structure | 973 | * @asd_ha: pointer to host adapter structure |
974 | */ | 974 | */ |
975 | static void asd_init_lseq_cio(struct asd_ha_struct *asd_ha, int lseq) | 975 | static void asd_init_lseq_cio(struct asd_ha_struct *asd_ha, int lseq) |
976 | { | 976 | { |
977 | u8 *sas_addr; | 977 | u8 *sas_addr; |
978 | int i; | 978 | int i; |
979 | 979 | ||
980 | /* Enable ARP2HALTC (ARP2 Halted from Halt Code Write). */ | 980 | /* Enable ARP2HALTC (ARP2 Halted from Halt Code Write). */ |
981 | asd_write_reg_dword(asd_ha, LmARP2INTEN(lseq), EN_ARP2HALTC); | 981 | asd_write_reg_dword(asd_ha, LmARP2INTEN(lseq), EN_ARP2HALTC); |
982 | 982 | ||
983 | asd_write_reg_byte(asd_ha, LmSCRATCHPAGE(lseq), 0); | 983 | asd_write_reg_byte(asd_ha, LmSCRATCHPAGE(lseq), 0); |
984 | 984 | ||
985 | /* Initialize Mode 0,1, and 2 SCRATCHPAGE to 0. */ | 985 | /* Initialize Mode 0,1, and 2 SCRATCHPAGE to 0. */ |
986 | for (i = 0; i < 3; i++) | 986 | for (i = 0; i < 3; i++) |
987 | asd_write_reg_byte(asd_ha, LmMnSCRATCHPAGE(lseq, i), 0); | 987 | asd_write_reg_byte(asd_ha, LmMnSCRATCHPAGE(lseq, i), 0); |
988 | 988 | ||
989 | /* Initialize Mode 5 SCRATCHPAGE to 0. */ | 989 | /* Initialize Mode 5 SCRATCHPAGE to 0. */ |
990 | asd_write_reg_byte(asd_ha, LmMnSCRATCHPAGE(lseq, 5), 0); | 990 | asd_write_reg_byte(asd_ha, LmMnSCRATCHPAGE(lseq, 5), 0); |
991 | 991 | ||
992 | asd_write_reg_dword(asd_ha, LmRSPMBX(lseq), 0); | 992 | asd_write_reg_dword(asd_ha, LmRSPMBX(lseq), 0); |
993 | /* Initialize Mode 0,1,2 and 5 Interrupt Enable and | 993 | /* Initialize Mode 0,1,2 and 5 Interrupt Enable and |
994 | * Interrupt registers. */ | 994 | * Interrupt registers. */ |
995 | asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 0), LmM0INTEN_MASK); | 995 | asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 0), LmM0INTEN_MASK); |
996 | asd_write_reg_dword(asd_ha, LmMnINT(lseq, 0), 0xFFFFFFFF); | 996 | asd_write_reg_dword(asd_ha, LmMnINT(lseq, 0), 0xFFFFFFFF); |
997 | /* Mode 1 */ | 997 | /* Mode 1 */ |
998 | asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 1), LmM1INTEN_MASK); | 998 | asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 1), LmM1INTEN_MASK); |
999 | asd_write_reg_dword(asd_ha, LmMnINT(lseq, 1), 0xFFFFFFFF); | 999 | asd_write_reg_dword(asd_ha, LmMnINT(lseq, 1), 0xFFFFFFFF); |
1000 | /* Mode 2 */ | 1000 | /* Mode 2 */ |
1001 | asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 2), LmM2INTEN_MASK); | 1001 | asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 2), LmM2INTEN_MASK); |
1002 | asd_write_reg_dword(asd_ha, LmMnINT(lseq, 2), 0xFFFFFFFF); | 1002 | asd_write_reg_dword(asd_ha, LmMnINT(lseq, 2), 0xFFFFFFFF); |
1003 | /* Mode 5 */ | 1003 | /* Mode 5 */ |
1004 | asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 5), LmM5INTEN_MASK); | 1004 | asd_write_reg_dword(asd_ha, LmMnINTEN(lseq, 5), LmM5INTEN_MASK); |
1005 | asd_write_reg_dword(asd_ha, LmMnINT(lseq, 5), 0xFFFFFFFF); | 1005 | asd_write_reg_dword(asd_ha, LmMnINT(lseq, 5), 0xFFFFFFFF); |
1006 | 1006 | ||
1007 | /* Enable HW Timer status. */ | 1007 | /* Enable HW Timer status. */ |
1008 | asd_write_reg_byte(asd_ha, LmHWTSTATEN(lseq), LmHWTSTATEN_MASK); | 1008 | asd_write_reg_byte(asd_ha, LmHWTSTATEN(lseq), LmHWTSTATEN_MASK); |
1009 | 1009 | ||
1010 | /* Enable Primitive Status 0 and 1. */ | 1010 | /* Enable Primitive Status 0 and 1. */ |
1011 | asd_write_reg_dword(asd_ha, LmPRIMSTAT0EN(lseq), LmPRIMSTAT0EN_MASK); | 1011 | asd_write_reg_dword(asd_ha, LmPRIMSTAT0EN(lseq), LmPRIMSTAT0EN_MASK); |
1012 | asd_write_reg_dword(asd_ha, LmPRIMSTAT1EN(lseq), LmPRIMSTAT1EN_MASK); | 1012 | asd_write_reg_dword(asd_ha, LmPRIMSTAT1EN(lseq), LmPRIMSTAT1EN_MASK); |
1013 | 1013 | ||
1014 | /* Enable Frame Error. */ | 1014 | /* Enable Frame Error. */ |
1015 | asd_write_reg_dword(asd_ha, LmFRMERREN(lseq), LmFRMERREN_MASK); | 1015 | asd_write_reg_dword(asd_ha, LmFRMERREN(lseq), LmFRMERREN_MASK); |
1016 | asd_write_reg_byte(asd_ha, LmMnHOLDLVL(lseq, 0), 0x50); | 1016 | asd_write_reg_byte(asd_ha, LmMnHOLDLVL(lseq, 0), 0x50); |
1017 | 1017 | ||
1018 | /* Initialize Mode 0 Transfer Level to 512. */ | 1018 | /* Initialize Mode 0 Transfer Level to 512. */ |
1019 | asd_write_reg_byte(asd_ha, LmMnXFRLVL(lseq, 0), LmMnXFRLVL_512); | 1019 | asd_write_reg_byte(asd_ha, LmMnXFRLVL(lseq, 0), LmMnXFRLVL_512); |
1020 | /* Initialize Mode 1 Transfer Level to 256. */ | 1020 | /* Initialize Mode 1 Transfer Level to 256. */ |
1021 | asd_write_reg_byte(asd_ha, LmMnXFRLVL(lseq, 1), LmMnXFRLVL_256); | 1021 | asd_write_reg_byte(asd_ha, LmMnXFRLVL(lseq, 1), LmMnXFRLVL_256); |
1022 | 1022 | ||
1023 | /* Initialize Program Count. */ | 1023 | /* Initialize Program Count. */ |
1024 | asd_write_reg_word(asd_ha, LmPRGMCNT(lseq), lseq_idle_loop); | 1024 | asd_write_reg_word(asd_ha, LmPRGMCNT(lseq), lseq_idle_loop); |
1025 | 1025 | ||
1026 | /* Enable Blind SG Move. */ | 1026 | /* Enable Blind SG Move. */ |
1027 | asd_write_reg_dword(asd_ha, LmMODECTL(lseq), LmBLIND48); | 1027 | asd_write_reg_dword(asd_ha, LmMODECTL(lseq), LmBLIND48); |
1028 | asd_write_reg_word(asd_ha, LmM3SATATIMER(lseq), | 1028 | asd_write_reg_word(asd_ha, LmM3SATATIMER(lseq), |
1029 | ASD_SATA_INTERLOCK_TIMEOUT); | 1029 | ASD_SATA_INTERLOCK_TIMEOUT); |
1030 | 1030 | ||
1031 | (void) asd_read_reg_dword(asd_ha, LmREQMBX(lseq)); | 1031 | (void) asd_read_reg_dword(asd_ha, LmREQMBX(lseq)); |
1032 | 1032 | ||
1033 | /* Clear Primitive Status 0 and 1. */ | 1033 | /* Clear Primitive Status 0 and 1. */ |
1034 | asd_write_reg_dword(asd_ha, LmPRMSTAT0(lseq), 0xFFFFFFFF); | 1034 | asd_write_reg_dword(asd_ha, LmPRMSTAT0(lseq), 0xFFFFFFFF); |
1035 | asd_write_reg_dword(asd_ha, LmPRMSTAT1(lseq), 0xFFFFFFFF); | 1035 | asd_write_reg_dword(asd_ha, LmPRMSTAT1(lseq), 0xFFFFFFFF); |
1036 | 1036 | ||
1037 | /* Clear HW Timer status. */ | 1037 | /* Clear HW Timer status. */ |
1038 | asd_write_reg_byte(asd_ha, LmHWTSTAT(lseq), 0xFF); | 1038 | asd_write_reg_byte(asd_ha, LmHWTSTAT(lseq), 0xFF); |
1039 | 1039 | ||
1040 | /* Clear DMA Errors for Mode 0 and 1. */ | 1040 | /* Clear DMA Errors for Mode 0 and 1. */ |
1041 | asd_write_reg_byte(asd_ha, LmMnDMAERRS(lseq, 0), 0xFF); | 1041 | asd_write_reg_byte(asd_ha, LmMnDMAERRS(lseq, 0), 0xFF); |
1042 | asd_write_reg_byte(asd_ha, LmMnDMAERRS(lseq, 1), 0xFF); | 1042 | asd_write_reg_byte(asd_ha, LmMnDMAERRS(lseq, 1), 0xFF); |
1043 | 1043 | ||
1044 | /* Clear SG DMA Errors for Mode 0 and 1. */ | 1044 | /* Clear SG DMA Errors for Mode 0 and 1. */ |
1045 | asd_write_reg_byte(asd_ha, LmMnSGDMAERRS(lseq, 0), 0xFF); | 1045 | asd_write_reg_byte(asd_ha, LmMnSGDMAERRS(lseq, 0), 0xFF); |
1046 | asd_write_reg_byte(asd_ha, LmMnSGDMAERRS(lseq, 1), 0xFF); | 1046 | asd_write_reg_byte(asd_ha, LmMnSGDMAERRS(lseq, 1), 0xFF); |
1047 | 1047 | ||
1048 | /* Clear Mode 0 Buffer Parity Error. */ | 1048 | /* Clear Mode 0 Buffer Parity Error. */ |
1049 | asd_write_reg_byte(asd_ha, LmMnBUFSTAT(lseq, 0), LmMnBUFPERR); | 1049 | asd_write_reg_byte(asd_ha, LmMnBUFSTAT(lseq, 0), LmMnBUFPERR); |
1050 | 1050 | ||
1051 | /* Clear Mode 0 Frame Error register. */ | 1051 | /* Clear Mode 0 Frame Error register. */ |
1052 | asd_write_reg_dword(asd_ha, LmMnFRMERR(lseq, 0), 0xFFFFFFFF); | 1052 | asd_write_reg_dword(asd_ha, LmMnFRMERR(lseq, 0), 0xFFFFFFFF); |
1053 | 1053 | ||
1054 | /* Reset LSEQ external interrupt arbiter. */ | 1054 | /* Reset LSEQ external interrupt arbiter. */ |
1055 | asd_write_reg_byte(asd_ha, LmARP2INTCTL(lseq), RSTINTCTL); | 1055 | asd_write_reg_byte(asd_ha, LmARP2INTCTL(lseq), RSTINTCTL); |
1056 | 1056 | ||
1057 | /* Set the Phy SAS for the LmSEQ WWN. */ | 1057 | /* Set the Phy SAS for the LmSEQ WWN. */ |
1058 | sas_addr = asd_ha->phys[lseq].phy_desc->sas_addr; | 1058 | sas_addr = asd_ha->phys[lseq].phy_desc->sas_addr; |
1059 | for (i = 0; i < SAS_ADDR_SIZE; i++) | 1059 | for (i = 0; i < SAS_ADDR_SIZE; i++) |
1060 | asd_write_reg_byte(asd_ha, LmWWN(lseq) + i, sas_addr[i]); | 1060 | asd_write_reg_byte(asd_ha, LmWWN(lseq) + i, sas_addr[i]); |
1061 | 1061 | ||
1062 | /* Set the Transmit Size to 1024 bytes, 0 = 256 Dwords. */ | 1062 | /* Set the Transmit Size to 1024 bytes, 0 = 256 Dwords. */ |
1063 | asd_write_reg_byte(asd_ha, LmMnXMTSIZE(lseq, 1), 0); | 1063 | asd_write_reg_byte(asd_ha, LmMnXMTSIZE(lseq, 1), 0); |
1064 | 1064 | ||
1065 | /* Set the Bus Inactivity Time Limit Timer. */ | 1065 | /* Set the Bus Inactivity Time Limit Timer. */ |
1066 | asd_write_reg_word(asd_ha, LmBITL_TIMER(lseq), 9); | 1066 | asd_write_reg_word(asd_ha, LmBITL_TIMER(lseq), 9); |
1067 | 1067 | ||
1068 | /* Enable SATA Port Multiplier. */ | 1068 | /* Enable SATA Port Multiplier. */ |
1069 | asd_write_reg_byte(asd_ha, LmMnSATAFS(lseq, 1), 0x80); | 1069 | asd_write_reg_byte(asd_ha, LmMnSATAFS(lseq, 1), 0x80); |
1070 | 1070 | ||
1071 | /* Initialize Interrupt Vector[0-10] address in Mode 3. | 1071 | /* Initialize Interrupt Vector[0-10] address in Mode 3. |
1072 | * See the comment on CSEQ_INT_* */ | 1072 | * See the comment on CSEQ_INT_* */ |
1073 | asd_write_reg_word(asd_ha, LmM3INTVEC0(lseq), lseq_vecs[0]); | 1073 | asd_write_reg_word(asd_ha, LmM3INTVEC0(lseq), lseq_vecs[0]); |
1074 | asd_write_reg_word(asd_ha, LmM3INTVEC1(lseq), lseq_vecs[1]); | 1074 | asd_write_reg_word(asd_ha, LmM3INTVEC1(lseq), lseq_vecs[1]); |
1075 | asd_write_reg_word(asd_ha, LmM3INTVEC2(lseq), lseq_vecs[2]); | 1075 | asd_write_reg_word(asd_ha, LmM3INTVEC2(lseq), lseq_vecs[2]); |
1076 | asd_write_reg_word(asd_ha, LmM3INTVEC3(lseq), lseq_vecs[3]); | 1076 | asd_write_reg_word(asd_ha, LmM3INTVEC3(lseq), lseq_vecs[3]); |
1077 | asd_write_reg_word(asd_ha, LmM3INTVEC4(lseq), lseq_vecs[4]); | 1077 | asd_write_reg_word(asd_ha, LmM3INTVEC4(lseq), lseq_vecs[4]); |
1078 | asd_write_reg_word(asd_ha, LmM3INTVEC5(lseq), lseq_vecs[5]); | 1078 | asd_write_reg_word(asd_ha, LmM3INTVEC5(lseq), lseq_vecs[5]); |
1079 | asd_write_reg_word(asd_ha, LmM3INTVEC6(lseq), lseq_vecs[6]); | 1079 | asd_write_reg_word(asd_ha, LmM3INTVEC6(lseq), lseq_vecs[6]); |
1080 | asd_write_reg_word(asd_ha, LmM3INTVEC7(lseq), lseq_vecs[7]); | 1080 | asd_write_reg_word(asd_ha, LmM3INTVEC7(lseq), lseq_vecs[7]); |
1081 | asd_write_reg_word(asd_ha, LmM3INTVEC8(lseq), lseq_vecs[8]); | 1081 | asd_write_reg_word(asd_ha, LmM3INTVEC8(lseq), lseq_vecs[8]); |
1082 | asd_write_reg_word(asd_ha, LmM3INTVEC9(lseq), lseq_vecs[9]); | 1082 | asd_write_reg_word(asd_ha, LmM3INTVEC9(lseq), lseq_vecs[9]); |
1083 | asd_write_reg_word(asd_ha, LmM3INTVEC10(lseq), lseq_vecs[10]); | 1083 | asd_write_reg_word(asd_ha, LmM3INTVEC10(lseq), lseq_vecs[10]); |
1084 | /* | 1084 | /* |
1085 | * Program the Link LED control, applicable only for | 1085 | * Program the Link LED control, applicable only for |
1086 | * Chip Rev. B or later. | 1086 | * Chip Rev. B or later. |
1087 | */ | 1087 | */ |
1088 | asd_write_reg_dword(asd_ha, LmCONTROL(lseq), | 1088 | asd_write_reg_dword(asd_ha, LmCONTROL(lseq), |
1089 | (LEDTIMER | LEDMODE_TXRX | LEDTIMERS_100ms)); | 1089 | (LEDTIMER | LEDMODE_TXRX | LEDTIMERS_100ms)); |
1090 | 1090 | ||
1091 | /* Set the Align Rate for SAS and STP mode. */ | 1091 | /* Set the Align Rate for SAS and STP mode. */ |
1092 | asd_write_reg_byte(asd_ha, LmM1SASALIGN(lseq), SAS_ALIGN_DEFAULT); | 1092 | asd_write_reg_byte(asd_ha, LmM1SASALIGN(lseq), SAS_ALIGN_DEFAULT); |
1093 | asd_write_reg_byte(asd_ha, LmM1STPALIGN(lseq), STP_ALIGN_DEFAULT); | 1093 | asd_write_reg_byte(asd_ha, LmM1STPALIGN(lseq), STP_ALIGN_DEFAULT); |
1094 | } | 1094 | } |
1095 | 1095 | ||
1096 | 1096 | ||
1097 | /** | 1097 | /** |
1098 | * asd_post_init_cseq -- clear CSEQ Mode n Int. status and Response mailbox | 1098 | * asd_post_init_cseq -- clear CSEQ Mode n Int. status and Response mailbox |
1099 | * @asd_ha: pointer to host adapter struct | 1099 | * @asd_ha: pointer to host adapter struct |
1100 | */ | 1100 | */ |
1101 | static void asd_post_init_cseq(struct asd_ha_struct *asd_ha) | 1101 | static void asd_post_init_cseq(struct asd_ha_struct *asd_ha) |
1102 | { | 1102 | { |
1103 | int i; | 1103 | int i; |
1104 | 1104 | ||
1105 | for (i = 0; i < 8; i++) | 1105 | for (i = 0; i < 8; i++) |
1106 | asd_write_reg_dword(asd_ha, CMnINT(i), 0xFFFFFFFF); | 1106 | asd_write_reg_dword(asd_ha, CMnINT(i), 0xFFFFFFFF); |
1107 | for (i = 0; i < 8; i++) | 1107 | for (i = 0; i < 8; i++) |
1108 | asd_read_reg_dword(asd_ha, CMnRSPMBX(i)); | 1108 | asd_read_reg_dword(asd_ha, CMnRSPMBX(i)); |
1109 | /* Reset the external interrupt arbiter. */ | 1109 | /* Reset the external interrupt arbiter. */ |
1110 | asd_write_reg_byte(asd_ha, CARP2INTCTL, RSTINTCTL); | 1110 | asd_write_reg_byte(asd_ha, CARP2INTCTL, RSTINTCTL); |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | /** | 1113 | /** |
1114 | * asd_init_ddb_0 -- initialize DDB 0 | 1114 | * asd_init_ddb_0 -- initialize DDB 0 |
1115 | * @asd_ha: pointer to host adapter structure | 1115 | * @asd_ha: pointer to host adapter structure |
1116 | * | 1116 | * |
1117 | * Initialize DDB site 0 which is used internally by the sequencer. | 1117 | * Initialize DDB site 0 which is used internally by the sequencer. |
1118 | */ | 1118 | */ |
1119 | static void asd_init_ddb_0(struct asd_ha_struct *asd_ha) | 1119 | static void asd_init_ddb_0(struct asd_ha_struct *asd_ha) |
1120 | { | 1120 | { |
1121 | int i; | 1121 | int i; |
1122 | 1122 | ||
1123 | /* Zero out the DDB explicitly */ | 1123 | /* Zero out the DDB explicitly */ |
1124 | for (i = 0; i < sizeof(struct asd_ddb_seq_shared); i+=4) | 1124 | for (i = 0; i < sizeof(struct asd_ddb_seq_shared); i+=4) |
1125 | asd_ddbsite_write_dword(asd_ha, 0, i, 0); | 1125 | asd_ddbsite_write_dword(asd_ha, 0, i, 0); |
1126 | 1126 | ||
1127 | asd_ddbsite_write_word(asd_ha, 0, | 1127 | asd_ddbsite_write_word(asd_ha, 0, |
1128 | offsetof(struct asd_ddb_seq_shared, q_free_ddb_head), 0); | 1128 | offsetof(struct asd_ddb_seq_shared, q_free_ddb_head), 0); |
1129 | asd_ddbsite_write_word(asd_ha, 0, | 1129 | asd_ddbsite_write_word(asd_ha, 0, |
1130 | offsetof(struct asd_ddb_seq_shared, q_free_ddb_tail), | 1130 | offsetof(struct asd_ddb_seq_shared, q_free_ddb_tail), |
1131 | asd_ha->hw_prof.max_ddbs-1); | 1131 | asd_ha->hw_prof.max_ddbs-1); |
1132 | asd_ddbsite_write_word(asd_ha, 0, | 1132 | asd_ddbsite_write_word(asd_ha, 0, |
1133 | offsetof(struct asd_ddb_seq_shared, q_free_ddb_cnt), 0); | 1133 | offsetof(struct asd_ddb_seq_shared, q_free_ddb_cnt), 0); |
1134 | asd_ddbsite_write_word(asd_ha, 0, | 1134 | asd_ddbsite_write_word(asd_ha, 0, |
1135 | offsetof(struct asd_ddb_seq_shared, q_used_ddb_head), 0xFFFF); | 1135 | offsetof(struct asd_ddb_seq_shared, q_used_ddb_head), 0xFFFF); |
1136 | asd_ddbsite_write_word(asd_ha, 0, | 1136 | asd_ddbsite_write_word(asd_ha, 0, |
1137 | offsetof(struct asd_ddb_seq_shared, q_used_ddb_tail), 0xFFFF); | 1137 | offsetof(struct asd_ddb_seq_shared, q_used_ddb_tail), 0xFFFF); |
1138 | asd_ddbsite_write_word(asd_ha, 0, | 1138 | asd_ddbsite_write_word(asd_ha, 0, |
1139 | offsetof(struct asd_ddb_seq_shared, shared_mem_lock), 0); | 1139 | offsetof(struct asd_ddb_seq_shared, shared_mem_lock), 0); |
1140 | asd_ddbsite_write_word(asd_ha, 0, | 1140 | asd_ddbsite_write_word(asd_ha, 0, |
1141 | offsetof(struct asd_ddb_seq_shared, smp_conn_tag), 0); | 1141 | offsetof(struct asd_ddb_seq_shared, smp_conn_tag), 0); |
1142 | asd_ddbsite_write_word(asd_ha, 0, | 1142 | asd_ddbsite_write_word(asd_ha, 0, |
1143 | offsetof(struct asd_ddb_seq_shared, est_nexus_buf_cnt), 0); | 1143 | offsetof(struct asd_ddb_seq_shared, est_nexus_buf_cnt), 0); |
1144 | asd_ddbsite_write_word(asd_ha, 0, | 1144 | asd_ddbsite_write_word(asd_ha, 0, |
1145 | offsetof(struct asd_ddb_seq_shared, est_nexus_buf_thresh), | 1145 | offsetof(struct asd_ddb_seq_shared, est_nexus_buf_thresh), |
1146 | asd_ha->hw_prof.num_phys * 2); | 1146 | asd_ha->hw_prof.num_phys * 2); |
1147 | asd_ddbsite_write_byte(asd_ha, 0, | 1147 | asd_ddbsite_write_byte(asd_ha, 0, |
1148 | offsetof(struct asd_ddb_seq_shared, settable_max_contexts),0); | 1148 | offsetof(struct asd_ddb_seq_shared, settable_max_contexts),0); |
1149 | asd_ddbsite_write_byte(asd_ha, 0, | 1149 | asd_ddbsite_write_byte(asd_ha, 0, |
1150 | offsetof(struct asd_ddb_seq_shared, conn_not_active), 0xFF); | 1150 | offsetof(struct asd_ddb_seq_shared, conn_not_active), 0xFF); |
1151 | asd_ddbsite_write_byte(asd_ha, 0, | 1151 | asd_ddbsite_write_byte(asd_ha, 0, |
1152 | offsetof(struct asd_ddb_seq_shared, phy_is_up), 0x00); | 1152 | offsetof(struct asd_ddb_seq_shared, phy_is_up), 0x00); |
1153 | /* DDB 0 is reserved */ | 1153 | /* DDB 0 is reserved */ |
1154 | set_bit(0, asd_ha->hw_prof.ddb_bitmap); | 1154 | set_bit(0, asd_ha->hw_prof.ddb_bitmap); |
1155 | } | 1155 | } |
1156 | 1156 | ||
1157 | static void asd_seq_init_ddb_sites(struct asd_ha_struct *asd_ha) | 1157 | static void asd_seq_init_ddb_sites(struct asd_ha_struct *asd_ha) |
1158 | { | 1158 | { |
1159 | unsigned int i; | 1159 | unsigned int i; |
1160 | unsigned int ddb_site; | 1160 | unsigned int ddb_site; |
1161 | 1161 | ||
1162 | for (ddb_site = 0 ; ddb_site < ASD_MAX_DDBS; ddb_site++) | 1162 | for (ddb_site = 0 ; ddb_site < ASD_MAX_DDBS; ddb_site++) |
1163 | for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) | 1163 | for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) |
1164 | asd_ddbsite_write_dword(asd_ha, ddb_site, i, 0); | 1164 | asd_ddbsite_write_dword(asd_ha, ddb_site, i, 0); |
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | /** | 1167 | /** |
1168 | * asd_seq_setup_seqs -- setup and initialize central and link sequencers | 1168 | * asd_seq_setup_seqs -- setup and initialize central and link sequencers |
1169 | * @asd_ha: pointer to host adapter structure | 1169 | * @asd_ha: pointer to host adapter structure |
1170 | */ | 1170 | */ |
1171 | static void asd_seq_setup_seqs(struct asd_ha_struct *asd_ha) | 1171 | static void asd_seq_setup_seqs(struct asd_ha_struct *asd_ha) |
1172 | { | 1172 | { |
1173 | int lseq; | 1173 | int lseq; |
1174 | u8 lseq_mask; | 1174 | u8 lseq_mask; |
1175 | 1175 | ||
1176 | /* Initialize DDB sites */ | 1176 | /* Initialize DDB sites */ |
1177 | asd_seq_init_ddb_sites(asd_ha); | 1177 | asd_seq_init_ddb_sites(asd_ha); |
1178 | 1178 | ||
1179 | /* Initialize SCB sites. Done first to compute some values which | 1179 | /* Initialize SCB sites. Done first to compute some values which |
1180 | * the rest of the init code depends on. */ | 1180 | * the rest of the init code depends on. */ |
1181 | asd_init_scb_sites(asd_ha); | 1181 | asd_init_scb_sites(asd_ha); |
1182 | 1182 | ||
1183 | /* Initialize CSEQ Scratch RAM registers. */ | 1183 | /* Initialize CSEQ Scratch RAM registers. */ |
1184 | asd_init_cseq_scratch(asd_ha); | 1184 | asd_init_cseq_scratch(asd_ha); |
1185 | 1185 | ||
1186 | /* Initialize LmSEQ Scratch RAM registers. */ | 1186 | /* Initialize LmSEQ Scratch RAM registers. */ |
1187 | asd_init_lseq_scratch(asd_ha); | 1187 | asd_init_lseq_scratch(asd_ha); |
1188 | 1188 | ||
1189 | /* Initialize CSEQ CIO registers. */ | 1189 | /* Initialize CSEQ CIO registers. */ |
1190 | asd_init_cseq_cio(asd_ha); | 1190 | asd_init_cseq_cio(asd_ha); |
1191 | 1191 | ||
1192 | asd_init_ddb_0(asd_ha); | 1192 | asd_init_ddb_0(asd_ha); |
1193 | 1193 | ||
1194 | /* Initialize LmSEQ CIO registers. */ | 1194 | /* Initialize LmSEQ CIO registers. */ |
1195 | lseq_mask = asd_ha->hw_prof.enabled_phys; | 1195 | lseq_mask = asd_ha->hw_prof.enabled_phys; |
1196 | for_each_sequencer(lseq_mask, lseq_mask, lseq) | 1196 | for_each_sequencer(lseq_mask, lseq_mask, lseq) |
1197 | asd_init_lseq_cio(asd_ha, lseq); | 1197 | asd_init_lseq_cio(asd_ha, lseq); |
1198 | asd_post_init_cseq(asd_ha); | 1198 | asd_post_init_cseq(asd_ha); |
1199 | } | 1199 | } |
1200 | 1200 | ||
1201 | 1201 | ||
1202 | /** | 1202 | /** |
1203 | * asd_seq_start_cseq -- start the central sequencer, CSEQ | 1203 | * asd_seq_start_cseq -- start the central sequencer, CSEQ |
1204 | * @asd_ha: pointer to host adapter structure | 1204 | * @asd_ha: pointer to host adapter structure |
1205 | */ | 1205 | */ |
1206 | static int asd_seq_start_cseq(struct asd_ha_struct *asd_ha) | 1206 | static int asd_seq_start_cseq(struct asd_ha_struct *asd_ha) |
1207 | { | 1207 | { |
1208 | /* Reset the ARP2 instruction to location zero. */ | 1208 | /* Reset the ARP2 instruction to location zero. */ |
1209 | asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop); | 1209 | asd_write_reg_word(asd_ha, CPRGMCNT, cseq_idle_loop); |
1210 | 1210 | ||
1211 | /* Unpause the CSEQ */ | 1211 | /* Unpause the CSEQ */ |
1212 | return asd_unpause_cseq(asd_ha); | 1212 | return asd_unpause_cseq(asd_ha); |
1213 | } | 1213 | } |
1214 | 1214 | ||
1215 | /** | 1215 | /** |
1216 | * asd_seq_start_lseq -- start a link sequencer | 1216 | * asd_seq_start_lseq -- start a link sequencer |
1217 | * @asd_ha: pointer to host adapter structure | 1217 | * @asd_ha: pointer to host adapter structure |
1218 | * @lseq: the link sequencer of interest | 1218 | * @lseq: the link sequencer of interest |
1219 | */ | 1219 | */ |
1220 | static int asd_seq_start_lseq(struct asd_ha_struct *asd_ha, int lseq) | 1220 | static int asd_seq_start_lseq(struct asd_ha_struct *asd_ha, int lseq) |
1221 | { | 1221 | { |
1222 | /* Reset the ARP2 instruction to location zero. */ | 1222 | /* Reset the ARP2 instruction to location zero. */ |
1223 | asd_write_reg_word(asd_ha, LmPRGMCNT(lseq), lseq_idle_loop); | 1223 | asd_write_reg_word(asd_ha, LmPRGMCNT(lseq), lseq_idle_loop); |
1224 | 1224 | ||
1225 | /* Unpause the LmSEQ */ | 1225 | /* Unpause the LmSEQ */ |
1226 | return asd_seq_unpause_lseq(asd_ha, lseq); | 1226 | return asd_seq_unpause_lseq(asd_ha, lseq); |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | int asd_release_firmware(void) | 1229 | int asd_release_firmware(void) |
1230 | { | 1230 | { |
1231 | if (sequencer_fw) | 1231 | release_firmware(sequencer_fw); |
1232 | release_firmware(sequencer_fw); | ||
1233 | return 0; | 1232 | return 0; |
1234 | } | 1233 | } |
1235 | 1234 | ||
1236 | static int asd_request_firmware(struct asd_ha_struct *asd_ha) | 1235 | static int asd_request_firmware(struct asd_ha_struct *asd_ha) |
1237 | { | 1236 | { |
1238 | int err, i; | 1237 | int err, i; |
1239 | struct sequencer_file_header header; | 1238 | struct sequencer_file_header header; |
1240 | const struct sequencer_file_header *hdr_ptr; | 1239 | const struct sequencer_file_header *hdr_ptr; |
1241 | u32 csum = 0; | 1240 | u32 csum = 0; |
1242 | u16 *ptr_cseq_vecs, *ptr_lseq_vecs; | 1241 | u16 *ptr_cseq_vecs, *ptr_lseq_vecs; |
1243 | 1242 | ||
1244 | if (sequencer_fw) | 1243 | if (sequencer_fw) |
1245 | /* already loaded */ | 1244 | /* already loaded */ |
1246 | return 0; | 1245 | return 0; |
1247 | 1246 | ||
1248 | err = request_firmware(&sequencer_fw, | 1247 | err = request_firmware(&sequencer_fw, |
1249 | SAS_RAZOR_SEQUENCER_FW_FILE, | 1248 | SAS_RAZOR_SEQUENCER_FW_FILE, |
1250 | &asd_ha->pcidev->dev); | 1249 | &asd_ha->pcidev->dev); |
1251 | if (err) | 1250 | if (err) |
1252 | return err; | 1251 | return err; |
1253 | 1252 | ||
1254 | hdr_ptr = (const struct sequencer_file_header *)sequencer_fw->data; | 1253 | hdr_ptr = (const struct sequencer_file_header *)sequencer_fw->data; |
1255 | 1254 | ||
1256 | header.csum = le32_to_cpu(hdr_ptr->csum); | 1255 | header.csum = le32_to_cpu(hdr_ptr->csum); |
1257 | header.major = le32_to_cpu(hdr_ptr->major); | 1256 | header.major = le32_to_cpu(hdr_ptr->major); |
1258 | header.minor = le32_to_cpu(hdr_ptr->minor); | 1257 | header.minor = le32_to_cpu(hdr_ptr->minor); |
1259 | header.cseq_table_offset = le32_to_cpu(hdr_ptr->cseq_table_offset); | 1258 | header.cseq_table_offset = le32_to_cpu(hdr_ptr->cseq_table_offset); |
1260 | header.cseq_table_size = le32_to_cpu(hdr_ptr->cseq_table_size); | 1259 | header.cseq_table_size = le32_to_cpu(hdr_ptr->cseq_table_size); |
1261 | header.lseq_table_offset = le32_to_cpu(hdr_ptr->lseq_table_offset); | 1260 | header.lseq_table_offset = le32_to_cpu(hdr_ptr->lseq_table_offset); |
1262 | header.lseq_table_size = le32_to_cpu(hdr_ptr->lseq_table_size); | 1261 | header.lseq_table_size = le32_to_cpu(hdr_ptr->lseq_table_size); |
1263 | header.cseq_code_offset = le32_to_cpu(hdr_ptr->cseq_code_offset); | 1262 | header.cseq_code_offset = le32_to_cpu(hdr_ptr->cseq_code_offset); |
1264 | header.cseq_code_size = le32_to_cpu(hdr_ptr->cseq_code_size); | 1263 | header.cseq_code_size = le32_to_cpu(hdr_ptr->cseq_code_size); |
1265 | header.lseq_code_offset = le32_to_cpu(hdr_ptr->lseq_code_offset); | 1264 | header.lseq_code_offset = le32_to_cpu(hdr_ptr->lseq_code_offset); |
1266 | header.lseq_code_size = le32_to_cpu(hdr_ptr->lseq_code_size); | 1265 | header.lseq_code_size = le32_to_cpu(hdr_ptr->lseq_code_size); |
1267 | header.mode2_task = le16_to_cpu(hdr_ptr->mode2_task); | 1266 | header.mode2_task = le16_to_cpu(hdr_ptr->mode2_task); |
1268 | header.cseq_idle_loop = le16_to_cpu(hdr_ptr->cseq_idle_loop); | 1267 | header.cseq_idle_loop = le16_to_cpu(hdr_ptr->cseq_idle_loop); |
1269 | header.lseq_idle_loop = le16_to_cpu(hdr_ptr->lseq_idle_loop); | 1268 | header.lseq_idle_loop = le16_to_cpu(hdr_ptr->lseq_idle_loop); |
1270 | 1269 | ||
1271 | for (i = sizeof(header.csum); i < sequencer_fw->size; i++) | 1270 | for (i = sizeof(header.csum); i < sequencer_fw->size; i++) |
1272 | csum += sequencer_fw->data[i]; | 1271 | csum += sequencer_fw->data[i]; |
1273 | 1272 | ||
1274 | if (csum != header.csum) { | 1273 | if (csum != header.csum) { |
1275 | asd_printk("Firmware file checksum mismatch\n"); | 1274 | asd_printk("Firmware file checksum mismatch\n"); |
1276 | return -EINVAL; | 1275 | return -EINVAL; |
1277 | } | 1276 | } |
1278 | 1277 | ||
1279 | if (header.cseq_table_size != CSEQ_NUM_VECS || | 1278 | if (header.cseq_table_size != CSEQ_NUM_VECS || |
1280 | header.lseq_table_size != LSEQ_NUM_VECS) { | 1279 | header.lseq_table_size != LSEQ_NUM_VECS) { |
1281 | asd_printk("Firmware file table size mismatch\n"); | 1280 | asd_printk("Firmware file table size mismatch\n"); |
1282 | return -EINVAL; | 1281 | return -EINVAL; |
1283 | } | 1282 | } |
1284 | 1283 | ||
1285 | asd_printk("Found sequencer Firmware version %d.%d (%s)\n", | 1284 | asd_printk("Found sequencer Firmware version %d.%d (%s)\n", |
1286 | header.major, header.minor, hdr_ptr->version); | 1285 | header.major, header.minor, hdr_ptr->version); |
1287 | 1286 | ||
1288 | if (header.major != SAS_RAZOR_SEQUENCER_FW_MAJOR) { | 1287 | if (header.major != SAS_RAZOR_SEQUENCER_FW_MAJOR) { |
1289 | asd_printk("Firmware Major Version Mismatch;" | 1288 | asd_printk("Firmware Major Version Mismatch;" |
1290 | "driver requires version %d.X", | 1289 | "driver requires version %d.X", |
1291 | SAS_RAZOR_SEQUENCER_FW_MAJOR); | 1290 | SAS_RAZOR_SEQUENCER_FW_MAJOR); |
1292 | return -EINVAL; | 1291 | return -EINVAL; |
1293 | } | 1292 | } |
1294 | 1293 | ||
1295 | ptr_cseq_vecs = (u16 *)&sequencer_fw->data[header.cseq_table_offset]; | 1294 | ptr_cseq_vecs = (u16 *)&sequencer_fw->data[header.cseq_table_offset]; |
1296 | ptr_lseq_vecs = (u16 *)&sequencer_fw->data[header.lseq_table_offset]; | 1295 | ptr_lseq_vecs = (u16 *)&sequencer_fw->data[header.lseq_table_offset]; |
1297 | mode2_task = header.mode2_task; | 1296 | mode2_task = header.mode2_task; |
1298 | cseq_idle_loop = header.cseq_idle_loop; | 1297 | cseq_idle_loop = header.cseq_idle_loop; |
1299 | lseq_idle_loop = header.lseq_idle_loop; | 1298 | lseq_idle_loop = header.lseq_idle_loop; |
1300 | 1299 | ||
1301 | for (i = 0; i < CSEQ_NUM_VECS; i++) | 1300 | for (i = 0; i < CSEQ_NUM_VECS; i++) |
1302 | cseq_vecs[i] = le16_to_cpu(ptr_cseq_vecs[i]); | 1301 | cseq_vecs[i] = le16_to_cpu(ptr_cseq_vecs[i]); |
1303 | 1302 | ||
1304 | for (i = 0; i < LSEQ_NUM_VECS; i++) | 1303 | for (i = 0; i < LSEQ_NUM_VECS; i++) |
1305 | lseq_vecs[i] = le16_to_cpu(ptr_lseq_vecs[i]); | 1304 | lseq_vecs[i] = le16_to_cpu(ptr_lseq_vecs[i]); |
1306 | 1305 | ||
1307 | cseq_code = &sequencer_fw->data[header.cseq_code_offset]; | 1306 | cseq_code = &sequencer_fw->data[header.cseq_code_offset]; |
1308 | cseq_code_size = header.cseq_code_size; | 1307 | cseq_code_size = header.cseq_code_size; |
1309 | lseq_code = &sequencer_fw->data[header.lseq_code_offset]; | 1308 | lseq_code = &sequencer_fw->data[header.lseq_code_offset]; |
1310 | lseq_code_size = header.lseq_code_size; | 1309 | lseq_code_size = header.lseq_code_size; |
1311 | 1310 | ||
1312 | return 0; | 1311 | return 0; |
1313 | } | 1312 | } |
1314 | 1313 | ||
1315 | int asd_init_seqs(struct asd_ha_struct *asd_ha) | 1314 | int asd_init_seqs(struct asd_ha_struct *asd_ha) |
1316 | { | 1315 | { |
1317 | int err; | 1316 | int err; |
1318 | 1317 | ||
1319 | err = asd_request_firmware(asd_ha); | 1318 | err = asd_request_firmware(asd_ha); |
1320 | 1319 | ||
1321 | if (err) { | 1320 | if (err) { |
1322 | asd_printk("Failed to load sequencer firmware file %s, error %d\n", | 1321 | asd_printk("Failed to load sequencer firmware file %s, error %d\n", |
1323 | SAS_RAZOR_SEQUENCER_FW_FILE, err); | 1322 | SAS_RAZOR_SEQUENCER_FW_FILE, err); |
1324 | return err; | 1323 | return err; |
1325 | } | 1324 | } |
1326 | 1325 | ||
1327 | err = asd_seq_download_seqs(asd_ha); | 1326 | err = asd_seq_download_seqs(asd_ha); |
1328 | if (err) { | 1327 | if (err) { |
1329 | asd_printk("couldn't download sequencers for %s\n", | 1328 | asd_printk("couldn't download sequencers for %s\n", |
1330 | pci_name(asd_ha->pcidev)); | 1329 | pci_name(asd_ha->pcidev)); |
1331 | return err; | 1330 | return err; |
1332 | } | 1331 | } |
1333 | 1332 | ||
1334 | asd_seq_setup_seqs(asd_ha); | 1333 | asd_seq_setup_seqs(asd_ha); |
1335 | 1334 | ||
1336 | return 0; | 1335 | return 0; |
1337 | } | 1336 | } |
1338 | 1337 | ||
1339 | int asd_start_seqs(struct asd_ha_struct *asd_ha) | 1338 | int asd_start_seqs(struct asd_ha_struct *asd_ha) |
1340 | { | 1339 | { |
1341 | int err; | 1340 | int err; |
1342 | u8 lseq_mask; | 1341 | u8 lseq_mask; |
1343 | int lseq; | 1342 | int lseq; |
1344 | 1343 | ||
1345 | err = asd_seq_start_cseq(asd_ha); | 1344 | err = asd_seq_start_cseq(asd_ha); |
1346 | if (err) { | 1345 | if (err) { |
1347 | asd_printk("couldn't start CSEQ for %s\n", | 1346 | asd_printk("couldn't start CSEQ for %s\n", |
1348 | pci_name(asd_ha->pcidev)); | 1347 | pci_name(asd_ha->pcidev)); |
1349 | return err; | 1348 | return err; |
1350 | } | 1349 | } |
1351 | 1350 | ||
1352 | lseq_mask = asd_ha->hw_prof.enabled_phys; | 1351 | lseq_mask = asd_ha->hw_prof.enabled_phys; |
1353 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { | 1352 | for_each_sequencer(lseq_mask, lseq_mask, lseq) { |
1354 | err = asd_seq_start_lseq(asd_ha, lseq); | 1353 | err = asd_seq_start_lseq(asd_ha, lseq); |
1355 | if (err) { | 1354 | if (err) { |
1356 | asd_printk("coudln't start LSEQ %d for %s\n", lseq, | 1355 | asd_printk("coudln't start LSEQ %d for %s\n", lseq, |
1357 | pci_name(asd_ha->pcidev)); | 1356 | pci_name(asd_ha->pcidev)); |
1358 | return err; | 1357 | return err; |
1359 | } | 1358 | } |
1360 | } | 1359 | } |
1361 | 1360 | ||
1362 | return 0; | 1361 | return 0; |
1363 | } | 1362 | } |
1364 | 1363 | ||
1365 | /** | 1364 | /** |
1366 | * asd_update_port_links -- update port_map_by_links and phy_is_up | 1365 | * asd_update_port_links -- update port_map_by_links and phy_is_up |
1367 | * @sas_phy: pointer to the phy which has been added to a port | 1366 | * @sas_phy: pointer to the phy which has been added to a port |
1368 | * | 1367 | * |
1369 | * 1) When a link reset has completed and we got BYTES DMAED with a | 1368 | * 1) When a link reset has completed and we got BYTES DMAED with a |
1370 | * valid frame we call this function for that phy, to indicate that | 1369 | * valid frame we call this function for that phy, to indicate that |
1371 | * the phy is up, i.e. we update the phy_is_up in DDB 0. The | 1370 | * the phy is up, i.e. we update the phy_is_up in DDB 0. The |
1372 | * sequencer checks phy_is_up when pending SCBs are to be sent, and | 1371 | * sequencer checks phy_is_up when pending SCBs are to be sent, and |
1373 | * when an open address frame has been received. | 1372 | * when an open address frame has been received. |
1374 | * | 1373 | * |
1375 | * 2) When we know of ports, we call this function to update the map | 1374 | * 2) When we know of ports, we call this function to update the map |
1376 | * of phys participaing in that port, i.e. we update the | 1375 | * of phys participaing in that port, i.e. we update the |
1377 | * port_map_by_links in DDB 0. When a HARD_RESET primitive has been | 1376 | * port_map_by_links in DDB 0. When a HARD_RESET primitive has been |
1378 | * received, the sequencer disables all phys in that port. | 1377 | * received, the sequencer disables all phys in that port. |
1379 | * port_map_by_links is also used as the conn_mask byte in the | 1378 | * port_map_by_links is also used as the conn_mask byte in the |
1380 | * initiator/target port DDB. | 1379 | * initiator/target port DDB. |
1381 | */ | 1380 | */ |
1382 | void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) | 1381 | void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) |
1383 | { | 1382 | { |
1384 | const u8 phy_mask = (u8) phy->asd_port->phy_mask; | 1383 | const u8 phy_mask = (u8) phy->asd_port->phy_mask; |
1385 | u8 phy_is_up; | 1384 | u8 phy_is_up; |
1386 | u8 mask; | 1385 | u8 mask; |
1387 | int i, err; | 1386 | int i, err; |
1388 | unsigned long flags; | 1387 | unsigned long flags; |
1389 | 1388 | ||
1390 | spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); | 1389 | spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); |
1391 | for_each_phy(phy_mask, mask, i) | 1390 | for_each_phy(phy_mask, mask, i) |
1392 | asd_ddbsite_write_byte(asd_ha, 0, | 1391 | asd_ddbsite_write_byte(asd_ha, 0, |
1393 | offsetof(struct asd_ddb_seq_shared, | 1392 | offsetof(struct asd_ddb_seq_shared, |
1394 | port_map_by_links)+i,phy_mask); | 1393 | port_map_by_links)+i,phy_mask); |
1395 | 1394 | ||
1396 | for (i = 0; i < 12; i++) { | 1395 | for (i = 0; i < 12; i++) { |
1397 | phy_is_up = asd_ddbsite_read_byte(asd_ha, 0, | 1396 | phy_is_up = asd_ddbsite_read_byte(asd_ha, 0, |
1398 | offsetof(struct asd_ddb_seq_shared, phy_is_up)); | 1397 | offsetof(struct asd_ddb_seq_shared, phy_is_up)); |
1399 | err = asd_ddbsite_update_byte(asd_ha, 0, | 1398 | err = asd_ddbsite_update_byte(asd_ha, 0, |
1400 | offsetof(struct asd_ddb_seq_shared, phy_is_up), | 1399 | offsetof(struct asd_ddb_seq_shared, phy_is_up), |
1401 | phy_is_up, | 1400 | phy_is_up, |
1402 | phy_is_up | phy_mask); | 1401 | phy_is_up | phy_mask); |
1403 | if (!err) | 1402 | if (!err) |
1404 | break; | 1403 | break; |
1405 | else if (err == -EFAULT) { | 1404 | else if (err == -EFAULT) { |
1406 | asd_printk("phy_is_up: parity error in DDB 0\n"); | 1405 | asd_printk("phy_is_up: parity error in DDB 0\n"); |
1407 | break; | 1406 | break; |
1408 | } | 1407 | } |
1409 | } | 1408 | } |
1410 | spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); | 1409 | spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); |
1411 | 1410 | ||
1412 | if (err) | 1411 | if (err) |
1413 | asd_printk("couldn't update DDB 0:error:%d\n", err); | 1412 | asd_printk("couldn't update DDB 0:error:%d\n", err); |
1414 | } | 1413 | } |
1415 | 1414 | ||
1416 | MODULE_FIRMWARE(SAS_RAZOR_SEQUENCER_FW_FILE); | 1415 | MODULE_FIRMWARE(SAS_RAZOR_SEQUENCER_FW_FILE); |
1417 | 1416 |