1/*-
2 * Copyright (c) 2002-2007 Neterion, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <dev/nxge/include/xgehal-mgmt.h>
30#include <dev/nxge/include/xgehal-driver.h>
31#include <dev/nxge/include/xgehal-device.h>
32
33/**
34 * xge_hal_mgmt_about - Retrieve about info.
35 * @devh: HAL device handle.
36 * @about_info: Filled in by HAL. See xge_hal_mgmt_about_info_t{}.
37 * @size: Size of the @about_info buffer. HAL will return error if the
38 *        size is smaller than sizeof(xge_hal_mgmt_about_info_t).
39 *
40 * Retrieve information such as PCI device and vendor IDs, board
41 * revision number, HAL version number, etc.
42 *
43 * Returns: XGE_HAL_OK - success;
44 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
45 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
46 * XGE_HAL_FAIL - Failed to retrieve the information.
47 *
48 * See also: xge_hal_mgmt_about_info_t{}.
49 */
50xge_hal_status_e
51xge_hal_mgmt_about(xge_hal_device_h devh, xge_hal_mgmt_about_info_t *about_info,
52	    int size)
53{
54	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
55
56	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
57	    return XGE_HAL_ERR_INVALID_DEVICE;
58	}
59
60	if (size != sizeof(xge_hal_mgmt_about_info_t)) {
61	    return XGE_HAL_ERR_VERSION_CONFLICT;
62	}
63
64	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
65	    xge_offsetof(xge_hal_pci_config_le_t, vendor_id),
66	    &about_info->vendor);
67
68	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
69	    xge_offsetof(xge_hal_pci_config_le_t, device_id),
70	    &about_info->device);
71
72	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
73	    xge_offsetof(xge_hal_pci_config_le_t, subsystem_vendor_id),
74	    &about_info->subsys_vendor);
75
76	xge_os_pci_read16(hldev->pdev, hldev->cfgh,
77	    xge_offsetof(xge_hal_pci_config_le_t, subsystem_id),
78	    &about_info->subsys_device);
79
80	xge_os_pci_read8(hldev->pdev, hldev->cfgh,
81	    xge_offsetof(xge_hal_pci_config_le_t, revision),
82	    &about_info->board_rev);
83
84	xge_os_strcpy(about_info->vendor_name, XGE_DRIVER_VENDOR);
85	xge_os_strcpy(about_info->chip_name, XGE_CHIP_FAMILY);
86	xge_os_strcpy(about_info->media, XGE_SUPPORTED_MEDIA_0);
87
88	xge_os_strcpy(about_info->hal_major, XGE_HAL_VERSION_MAJOR);
89	xge_os_strcpy(about_info->hal_minor, XGE_HAL_VERSION_MINOR);
90	xge_os_strcpy(about_info->hal_fix,   XGE_HAL_VERSION_FIX);
91	xge_os_strcpy(about_info->hal_build, XGE_HAL_VERSION_BUILD);
92
93	xge_os_strcpy(about_info->ll_major, XGELL_VERSION_MAJOR);
94	xge_os_strcpy(about_info->ll_minor, XGELL_VERSION_MINOR);
95	xge_os_strcpy(about_info->ll_fix,   XGELL_VERSION_FIX);
96	xge_os_strcpy(about_info->ll_build, XGELL_VERSION_BUILD);
97
98	about_info->transponder_temperature =
99	    xge_hal_read_xfp_current_temp(devh);
100
101	return XGE_HAL_OK;
102}
103
104/**
105 * xge_hal_mgmt_reg_read - Read Xframe register.
106 * @devh: HAL device handle.
107 * @bar_id: 0 - for BAR0, 1- for BAR1.
108 * @offset: Register offset in the Base Address Register (BAR) space.
109 * @value: Register value. Returned by HAL.
110 * Read Xframe register.
111 *
112 * Returns: XGE_HAL_OK - success.
113 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
114 * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not
115 * valid.
116 * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid.
117 *
118 * See also: xge_hal_aux_bar0_read(), xge_hal_aux_bar1_read().
119 */
120xge_hal_status_e
121xge_hal_mgmt_reg_read(xge_hal_device_h devh, int bar_id, unsigned int offset,
122	    u64 *value)
123{
124	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
125
126	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
127	    return XGE_HAL_ERR_INVALID_DEVICE;
128	}
129
130	if (bar_id == 0) {
131	    if (offset > sizeof(xge_hal_pci_bar0_t)-8) {
132	        return XGE_HAL_ERR_INVALID_OFFSET;
133	    }
134	    *value = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
135	                     (void *)(hldev->bar0 + offset));
136	} else if (bar_id == 1 &&
137	       (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA ||
138	        xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC))  {
139	    int i;
140	    for (i=0; i<XGE_HAL_MAX_FIFO_NUM_HERC; i++) {
141	        if (offset == i*0x2000 || offset == i*0x2000+0x18) {
142	            break;
143	        }
144	    }
145	    if (i == XGE_HAL_MAX_FIFO_NUM_HERC) {
146	        return XGE_HAL_ERR_INVALID_OFFSET;
147	    }
148	    *value = xge_os_pio_mem_read64(hldev->pdev, hldev->regh1,
149	                     (void *)(hldev->bar1 + offset));
150	} else if (bar_id == 1) {
151	    /* FIXME: check TITAN BAR1 offsets */
152	} else {
153	    return XGE_HAL_ERR_INVALID_BAR_ID;
154	}
155
156	return XGE_HAL_OK;
157}
158
159/**
160 * xge_hal_mgmt_reg_write - Write Xframe register.
161 * @devh: HAL device handle.
162 * @bar_id: 0 - for BAR0, 1- for BAR1.
163 * @offset: Register offset in the Base Address Register (BAR) space.
164 * @value: Register value.
165 *
166 * Write Xframe register.
167 *
168 * Returns: XGE_HAL_OK - success.
169 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
170 * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not
171 * valid.
172 * XGE_HAL_ERR_INVALID_BAR_ID - BAR id is not valid.
173 *
174 * See also: xge_hal_aux_bar0_write().
175 */
176xge_hal_status_e
177xge_hal_mgmt_reg_write(xge_hal_device_h devh, int bar_id, unsigned int offset,
178	    u64 value)
179{
180	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
181
182	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
183	    return XGE_HAL_ERR_INVALID_DEVICE;
184	}
185
186	if (bar_id == 0) {
187	    if (offset > sizeof(xge_hal_pci_bar0_t)-8) {
188	        return XGE_HAL_ERR_INVALID_OFFSET;
189	    }
190	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, value,
191	                 (void *)(hldev->bar0 + offset));
192	} else if (bar_id == 1 &&
193	       (xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA ||
194	        xge_hal_device_check_id(hldev) == XGE_HAL_CARD_HERC))  {
195	    int i;
196	    for (i=0; i<XGE_HAL_MAX_FIFO_NUM_HERC; i++) {
197	        if (offset == i*0x2000 || offset == i*0x2000+0x18) {
198	            break;
199	        }
200	    }
201	    if (i == XGE_HAL_MAX_FIFO_NUM_HERC) {
202	        return XGE_HAL_ERR_INVALID_OFFSET;
203	    }
204	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh1, value,
205	                 (void *)(hldev->bar1 + offset));
206	} else if (bar_id == 1) {
207	    /* FIXME: check TITAN BAR1 offsets */
208	} else {
209	    return XGE_HAL_ERR_INVALID_BAR_ID;
210	}
211
212	return XGE_HAL_OK;
213}
214
215/**
216 * xge_hal_mgmt_hw_stats - Get Xframe hardware statistics.
217 * @devh: HAL device handle.
218 * @hw_stats: Hardware statistics. Returned by HAL.
219 *            See xge_hal_stats_hw_info_t{}.
220 * @size: Size of the @hw_stats buffer. HAL will return an error
221 * if the size is smaller than sizeof(xge_hal_stats_hw_info_t).
222 * Get Xframe hardware statistics.
223 *
224 * Returns: XGE_HAL_OK - success.
225 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
226 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
227 *
228 * See also: xge_hal_mgmt_sw_stats().
229 */
230xge_hal_status_e
231xge_hal_mgmt_hw_stats(xge_hal_device_h devh, xge_hal_mgmt_hw_stats_t *hw_stats,
232	    int size)
233{
234	xge_hal_status_e status;
235	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
236	xge_hal_stats_hw_info_t *hw_info;
237
238	xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN);
239
240	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
241	    return XGE_HAL_ERR_INVALID_DEVICE;
242	}
243
244	if (size != sizeof(xge_hal_stats_hw_info_t)) {
245	    return XGE_HAL_ERR_VERSION_CONFLICT;
246	}
247
248	if ((status = xge_hal_stats_hw (devh, &hw_info)) != XGE_HAL_OK) {
249	    return status;
250	}
251
252	xge_os_memcpy(hw_stats, hw_info, sizeof(xge_hal_stats_hw_info_t));
253
254	return XGE_HAL_OK;
255}
256
257/**
258 * xge_hal_mgmt_hw_stats_off - TBD.
259 * @devh: HAL device handle.
260 * @off: TBD
261 * @size: TBD
262 * @out: TBD
263 *
264 * Returns: XGE_HAL_OK - success.
265 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
266 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
267 *
268 * See also: xge_hal_mgmt_sw_stats().
269 */
270xge_hal_status_e
271xge_hal_mgmt_hw_stats_off(xge_hal_device_h devh, int off, int size, char *out)
272{
273	xge_hal_status_e status;
274	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
275	xge_hal_stats_hw_info_t *hw_info;
276
277	xge_assert(xge_hal_device_check_id(hldev) != XGE_HAL_CARD_TITAN);
278
279	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
280	    return XGE_HAL_ERR_INVALID_DEVICE;
281	}
282
283	if (off > sizeof(xge_hal_stats_hw_info_t)-4 ||
284	    size > 8) {
285	    return XGE_HAL_ERR_INVALID_OFFSET;
286	}
287
288	if ((status = xge_hal_stats_hw (devh, &hw_info)) != XGE_HAL_OK) {
289	    return status;
290	}
291
292	xge_os_memcpy(out, (char*)hw_info + off, size);
293
294	return XGE_HAL_OK;
295}
296
297/**
298 * xge_hal_mgmt_pcim_stats - Get Titan hardware statistics.
299 * @devh: HAL device handle.
300 * @pcim_stats: PCIM statistics. Returned by HAL.
301 *            See xge_hal_stats_hw_info_t{}.
302 * @size: Size of the @hw_stats buffer. HAL will return an error
303 * if the size is smaller than sizeof(xge_hal_stats_hw_info_t).
304 * Get Xframe hardware statistics.
305 *
306 * Returns: XGE_HAL_OK - success.
307 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
308 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
309 *
310 * See also: xge_hal_mgmt_sw_stats().
311 */
312xge_hal_status_e
313xge_hal_mgmt_pcim_stats(xge_hal_device_h devh,
314	    xge_hal_mgmt_pcim_stats_t *pcim_stats, int size)
315{
316	xge_hal_status_e status;
317	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
318	xge_hal_stats_pcim_info_t   *pcim_info;
319
320	xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN);
321
322	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
323	    return XGE_HAL_ERR_INVALID_DEVICE;
324	}
325
326	if (size != sizeof(xge_hal_stats_pcim_info_t)) {
327	    return XGE_HAL_ERR_VERSION_CONFLICT;
328	}
329
330	if ((status = xge_hal_stats_pcim (devh, &pcim_info)) != XGE_HAL_OK) {
331	    return status;
332	}
333
334	xge_os_memcpy(pcim_stats, pcim_info,
335	    sizeof(xge_hal_stats_pcim_info_t));
336
337	return XGE_HAL_OK;
338}
339
340/**
341 * xge_hal_mgmt_pcim_stats_off - TBD.
342 * @devh: HAL device handle.
343 * @off: TBD
344 * @size: TBD
345 * @out: TBD
346 *
347 * Returns: XGE_HAL_OK - success.
348 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
349 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
350 *
351 * See also: xge_hal_mgmt_sw_stats().
352 */
353xge_hal_status_e
354xge_hal_mgmt_pcim_stats_off(xge_hal_device_h devh, int off, int size,
355	            char *out)
356{
357	xge_hal_status_e status;
358	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
359	xge_hal_stats_pcim_info_t   *pcim_info;
360
361	xge_assert(xge_hal_device_check_id(hldev) == XGE_HAL_CARD_TITAN);
362
363	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
364	    return XGE_HAL_ERR_INVALID_DEVICE;
365	}
366
367	if (off > sizeof(xge_hal_stats_pcim_info_t)-8 ||
368	    size > 8) {
369	    return XGE_HAL_ERR_INVALID_OFFSET;
370	}
371
372	if ((status = xge_hal_stats_pcim (devh, &pcim_info)) != XGE_HAL_OK) {
373	    return status;
374	}
375
376	xge_os_memcpy(out, (char*)pcim_info + off, size);
377
378	return XGE_HAL_OK;
379}
380
381/**
382 * xge_hal_mgmt_sw_stats - Get per-device software statistics.
383 * @devh: HAL device handle.
384 * @sw_stats: Hardware statistics. Returned by HAL.
385 *            See xge_hal_stats_sw_err_t{}.
386 * @size: Size of the @sw_stats buffer. HAL will return an error
387 * if the size is smaller than sizeof(xge_hal_stats_sw_err_t).
388 * Get device software statistics, including ECC and Parity error
389 * counters, etc.
390 *
391 * Returns: XGE_HAL_OK - success.
392 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
393 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
394 *
395 * See also: xge_hal_stats_sw_err_t{}, xge_hal_mgmt_hw_stats().
396 */
397xge_hal_status_e
398xge_hal_mgmt_sw_stats(xge_hal_device_h devh, xge_hal_mgmt_sw_stats_t *sw_stats,
399	    int size)
400{
401	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
402
403	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
404	    return XGE_HAL_ERR_INVALID_DEVICE;
405	}
406
407	if (size != sizeof(xge_hal_stats_sw_err_t)) {
408	    return XGE_HAL_ERR_VERSION_CONFLICT;
409	}
410
411	if (!hldev->stats.is_initialized ||
412	    !hldev->stats.is_enabled) {
413	    return XGE_HAL_INF_STATS_IS_NOT_READY;
414	}
415
416	/* Updating xpak stats value */
417	__hal_updt_stats_xpak(hldev);
418
419	xge_os_memcpy(sw_stats, &hldev->stats.sw_dev_err_stats,
420	            sizeof(xge_hal_stats_sw_err_t));
421
422	return XGE_HAL_OK;
423}
424
425/**
426 * xge_hal_mgmt_device_stats - Get HAL device statistics.
427 * @devh: HAL device handle.
428 * @device_stats: HAL device "soft" statistics. Maintained by HAL itself.
429 *            (as opposed to xge_hal_mgmt_hw_stats() - those are
430 *            maintained by the Xframe hardware).
431 *            Returned by HAL.
432 *            See xge_hal_stats_device_info_t{}.
433 * @size: Size of the @device_stats buffer. HAL will return an error
434 * if the size is smaller than sizeof(xge_hal_stats_device_info_t).
435 *
436 * Get HAL (layer) statistic counters.
437 * Returns: XGE_HAL_OK - success.
438 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
439 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
440 * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
441 * currently available.
442 *
443 */
444xge_hal_status_e
445xge_hal_mgmt_device_stats(xge_hal_device_h devh,
446	    xge_hal_mgmt_device_stats_t *device_stats, int size)
447{
448	xge_hal_status_e status;
449	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
450	xge_hal_stats_device_info_t *device_info;
451
452	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
453	    return XGE_HAL_ERR_INVALID_DEVICE;
454	}
455
456	if (size != sizeof(xge_hal_stats_device_info_t)) {
457	    return XGE_HAL_ERR_VERSION_CONFLICT;
458	}
459
460	if ((status = xge_hal_stats_device (devh, &device_info)) !=
461	XGE_HAL_OK) {
462	    return status;
463	}
464
465	xge_os_memcpy(device_stats, device_info,
466	        sizeof(xge_hal_stats_device_info_t));
467
468	return XGE_HAL_OK;
469}
470
471/*
472 * __hal_update_ring_bump - Update the ring bump counter for the
473 * particular channel.
474 * @hldev: HAL device handle.
475 * @queue: the queue who's data is to be collected.
476 * @chinfo: pointer to the statistics structure of the given channel.
477 * Usage: See xge_hal_aux_stats_hal_read{}
478 */
479
480static void
481__hal_update_ring_bump(xge_hal_device_t *hldev, int queue,
482	xge_hal_stats_channel_info_t *chinfo)
483{
484	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
485	u64 rbc = 0;
486	int reg = (queue / 4);
487	void * addr;
488
489	addr = (reg == 1)? (&bar0->ring_bump_counter2) :
490	    (&bar0->ring_bump_counter1);
491	rbc = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0, addr);
492	chinfo->ring_bump_cnt = XGE_HAL_RING_BUMP_CNT(queue, rbc);
493}
494
495/**
496 * xge_hal_mgmt_channel_stats - Get HAL channel statistics.
497 * @channelh: HAL channel handle.
498 * @channel_stats: HAL channel statistics. Maintained by HAL itself
499 *            (as opposed to xge_hal_mgmt_hw_stats() - those are
500 *            maintained by the Xframe hardware).
501 *            Returned by HAL.
502 *            See xge_hal_stats_channel_info_t{}.
503 * @size: Size of the @channel_stats buffer. HAL will return an error
504 * if the size is smaller than sizeof(xge_hal_mgmt_channel_stats_t).
505 *
506 * Get HAL per-channel statistic counters.
507 *
508 * Returns: XGE_HAL_OK - success.
509 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
510 * XGE_HAL_INF_STATS_IS_NOT_READY - Statistics information is not
511 * currently available.
512 *
513 */
514xge_hal_status_e
515xge_hal_mgmt_channel_stats(xge_hal_channel_h channelh,
516	    xge_hal_mgmt_channel_stats_t *channel_stats, int size)
517{
518	xge_hal_status_e status;
519	xge_hal_stats_channel_info_t *channel_info;
520	xge_hal_channel_t *channel = (xge_hal_channel_t* ) channelh;
521
522	if (size != sizeof(xge_hal_stats_channel_info_t)) {
523	    return XGE_HAL_ERR_VERSION_CONFLICT;
524	}
525
526	if ((status = xge_hal_stats_channel (channelh, &channel_info)) !=
527	                            XGE_HAL_OK) {
528	    return status;
529	}
530
531	if (xge_hal_device_check_id(channel->devh) == XGE_HAL_CARD_HERC) {
532	    __hal_update_ring_bump( (xge_hal_device_t *) channel->devh, channel->post_qid, channel_info);
533	}
534
535	xge_os_memcpy(channel_stats, channel_info,
536	        sizeof(xge_hal_stats_channel_info_t));
537
538	return XGE_HAL_OK;
539}
540
541/**
542 * xge_hal_mgmt_pcireg_read - Read PCI configuration at a specified
543 * offset.
544 * @devh: HAL device handle.
545 * @offset: Offset in the 256 byte PCI configuration space.
546 * @value_bits: 8, 16, or 32 (bits) to read.
547 * @value: Value returned by HAL.
548 *
549 * Read PCI configuration, given device and offset in the PCI space.
550 *
551 * Returns: XGE_HAL_OK - success.
552 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
553 * XGE_HAL_ERR_INVALID_OFFSET - Register offset in the BAR space is not
554 * valid.
555 * XGE_HAL_ERR_INVALID_VALUE_BIT_SIZE - Invalid bits size. Valid
556 * values(8/16/32).
557 *
558 */
559xge_hal_status_e
560xge_hal_mgmt_pcireg_read(xge_hal_device_h devh, unsigned int offset,
561	    int value_bits, u32 *value)
562{
563	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
564
565	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
566	    return XGE_HAL_ERR_INVALID_DEVICE;
567	}
568
569	if (offset > sizeof(xge_hal_pci_config_t)-value_bits/8) {
570	    return XGE_HAL_ERR_INVALID_OFFSET;
571	}
572
573	if (value_bits == 8) {
574	    xge_os_pci_read8(hldev->pdev, hldev->cfgh, offset, (u8*)value);
575	} else if (value_bits == 16) {
576	    xge_os_pci_read16(hldev->pdev, hldev->cfgh, offset,
577	    (u16*)value);
578	} else if (value_bits == 32) {
579	    xge_os_pci_read32(hldev->pdev, hldev->cfgh, offset, value);
580	} else {
581	    return XGE_HAL_ERR_INVALID_VALUE_BIT_SIZE;
582	}
583
584	return XGE_HAL_OK;
585}
586
587/**
588 * xge_hal_mgmt_device_config - Retrieve device configuration.
589 * @devh: HAL device handle.
590 * @dev_config: Device configuration, see xge_hal_device_config_t{}.
591 * @size: Size of the @dev_config buffer. HAL will return an error
592 * if the size is smaller than sizeof(xge_hal_mgmt_device_config_t).
593 *
594 * Get device configuration. Permits to retrieve at run-time configuration
595 * values that were used to initialize and configure the device.
596 *
597 * Returns: XGE_HAL_OK - success.
598 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
599 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
600 *
601 * See also: xge_hal_device_config_t{}, xge_hal_mgmt_driver_config().
602 */
603xge_hal_status_e
604xge_hal_mgmt_device_config(xge_hal_device_h devh,
605	    xge_hal_mgmt_device_config_t    *dev_config, int size)
606{
607	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
608
609	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
610	    return XGE_HAL_ERR_INVALID_DEVICE;
611	}
612
613	if (size != sizeof(xge_hal_mgmt_device_config_t)) {
614	    return XGE_HAL_ERR_VERSION_CONFLICT;
615	}
616
617	xge_os_memcpy(dev_config, &hldev->config,
618	sizeof(xge_hal_device_config_t));
619
620	return XGE_HAL_OK;
621}
622
623/**
624 * xge_hal_mgmt_driver_config - Retrieve driver configuration.
625 * @drv_config: Device configuration, see xge_hal_driver_config_t{}.
626 * @size: Size of the @dev_config buffer. HAL will return an error
627 * if the size is smaller than sizeof(xge_hal_mgmt_driver_config_t).
628 *
629 * Get driver configuration. Permits to retrieve at run-time configuration
630 * values that were used to configure the device at load-time.
631 *
632 * Returns: XGE_HAL_OK - success.
633 * XGE_HAL_ERR_DRIVER_NOT_INITIALIZED - HAL is not initialized.
634 * XGE_HAL_ERR_VERSION_CONFLICT - Version is not maching.
635 *
636 * See also: xge_hal_driver_config_t{}, xge_hal_mgmt_device_config().
637 */
638xge_hal_status_e
639xge_hal_mgmt_driver_config(xge_hal_mgmt_driver_config_t *drv_config, int size)
640{
641
642	if (g_xge_hal_driver == NULL) {
643	    return XGE_HAL_ERR_DRIVER_NOT_INITIALIZED;
644	}
645
646	if (size != sizeof(xge_hal_mgmt_driver_config_t)) {
647	    return XGE_HAL_ERR_VERSION_CONFLICT;
648	}
649
650	xge_os_memcpy(drv_config, &g_xge_hal_driver->config,
651	        sizeof(xge_hal_mgmt_driver_config_t));
652
653	return XGE_HAL_OK;
654}
655
656/**
657 * xge_hal_mgmt_pci_config - Retrieve PCI configuration.
658 * @devh: HAL device handle.
659 * @pci_config: 256 byte long buffer for PCI configuration space.
660 * @size: Size of the @ buffer. HAL will return an error
661 * if the size is smaller than sizeof(xge_hal_mgmt_pci_config_t).
662 *
663 * Get PCI configuration. Permits to retrieve at run-time configuration
664 * values that were used to configure the device at load-time.
665 *
666 * Returns: XGE_HAL_OK - success.
667 * XGE_HAL_ERR_INVALID_DEVICE - Device is not valid.
668 * XGE_HAL_ERR_VERSION_CONFLICT - Version it not maching.
669 *
670 */
671xge_hal_status_e
672xge_hal_mgmt_pci_config(xge_hal_device_h devh,
673	    xge_hal_mgmt_pci_config_t *pci_config, int size)
674{
675	int i;
676	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
677
678	if ((hldev == NULL) || (hldev->magic != XGE_HAL_MAGIC)) {
679	    return XGE_HAL_ERR_INVALID_DEVICE;
680	}
681
682	if (size != sizeof(xge_hal_mgmt_pci_config_t)) {
683	    return XGE_HAL_ERR_VERSION_CONFLICT;
684	}
685
686	/* refresh PCI config space */
687	for (i = 0; i < 0x68/4+1; i++) {
688	    xge_os_pci_read32(hldev->pdev, hldev->cfgh, i*4,
689	                    (u32*)&hldev->pci_config_space + i);
690	}
691
692	xge_os_memcpy(pci_config, &hldev->pci_config_space,
693	        sizeof(xge_hal_mgmt_pci_config_t));
694
695	return XGE_HAL_OK;
696}
697
698#ifdef XGE_TRACE_INTO_CIRCULAR_ARR
699/**
700 * xge_hal_mgmt_trace_read - Read trace buffer contents.
701 * @buffer: Buffer to store the trace buffer contents.
702 * @buf_size: Size of the buffer.
703 * @offset: Offset in the internal trace buffer to read data.
704 * @read_length: Size of the valid data in the buffer.
705 *
706 * Read  HAL trace buffer contents starting from the offset
707 * upto the size of the buffer or till EOF is reached.
708 *
709 * Returns: XGE_HAL_OK - success.
710 * XGE_HAL_EOF_TRACE_BUF - No more data in the trace buffer.
711 *
712 */
713xge_hal_status_e
714xge_hal_mgmt_trace_read (char       *buffer,
715	        unsigned    buf_size,
716	        unsigned    *offset,
717	        unsigned    *read_length)
718{
719	int data_offset;
720	int start_offset;
721
722	if ((g_xge_os_tracebuf == NULL) ||
723	    (g_xge_os_tracebuf->offset == g_xge_os_tracebuf->size - 2)) {
724	    return XGE_HAL_EOF_TRACE_BUF;
725	}
726
727	data_offset = g_xge_os_tracebuf->offset + 1;
728
729	if  (*offset >= (unsigned)xge_os_strlen(g_xge_os_tracebuf->data +
730	data_offset)) {
731
732	    return XGE_HAL_EOF_TRACE_BUF;
733	}
734
735	xge_os_memzero(buffer, buf_size);
736
737	start_offset  =  data_offset + *offset;
738	*read_length = xge_os_strlen(g_xge_os_tracebuf->data +
739	start_offset);
740
741	if (*read_length  >=  buf_size) {
742	    *read_length = buf_size - 1;
743	}
744
745	xge_os_memcpy(buffer, g_xge_os_tracebuf->data + start_offset,
746	*read_length);
747
748	*offset += *read_length;
749	(*read_length) ++;
750
751	return XGE_HAL_OK;
752}
753
754#endif
755
756/**
757 * xge_hal_restore_link_led - Restore link LED to its original state.
758 * @devh: HAL device handle.
759 */
760void
761xge_hal_restore_link_led(xge_hal_device_h devh)
762{
763	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
764	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
765	u64 val64;
766
767	/*
768	 * If the current link state is UP, switch on LED else make it
769	 * off.
770	 */
771
772	/*
773	 * For Xena 3 and lower revision cards, adapter control needs to be
774	 * used for making LED ON/OFF.
775	 */
776	if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) &&
777	   (xge_hal_device_rev(hldev) <= 3)) {
778	    val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
779	                      &bar0->adapter_control);
780	    if (hldev->link_state == XGE_HAL_LINK_UP) {
781	        val64 |= XGE_HAL_ADAPTER_LED_ON;
782	    } else {
783	        val64 &= ~XGE_HAL_ADAPTER_LED_ON;
784	    }
785
786	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
787	                &bar0->adapter_control);
788	    return;
789	}
790
791	/*
792	 * Use beacon control register to control the LED.
793	 * LED link output corresponds to bit 8 of the beacon control
794	 * register. Note that, in the case of Xena, beacon control register
795	 * represents the gpio control register. In the case of Herc, LED
796	 * handling is done by beacon control register as opposed to gpio
797	 * control register in Xena. Beacon control is used only to toggle
798	 * and the value written into it does not depend on the link state.
799	 * It is upto the ULD to toggle the LED even number of times which
800	 * brings the LED to it's original state.
801	 */
802	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
803	                  &bar0->beacon_control);
804	val64 |= 0x0000800000000000ULL;
805	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
806	               val64, &bar0->beacon_control);
807}
808
809/**
810 * xge_hal_flick_link_led - Flick (blink) link LED.
811 * @devh: HAL device handle.
812 *
813 * Depending on the card revision flicker the link LED by using the
814 * beacon control or the adapter_control register.
815 */
816void
817xge_hal_flick_link_led(xge_hal_device_h devh)
818{
819	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
820	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
821	u64 val64 = 0;
822
823	/*
824	 * For Xena 3 and lower revision cards, adapter control needs to be
825	 * used for making LED ON/OFF.
826	 */
827	if ((xge_hal_device_check_id(hldev) == XGE_HAL_CARD_XENA) &&
828	   (xge_hal_device_rev(hldev) <= 3)) {
829	    val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
830	                      &bar0->adapter_control);
831	    val64 ^= XGE_HAL_ADAPTER_LED_ON;
832	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
833	                &bar0->adapter_control);
834	    return;
835	}
836
837	/*
838	 * Use beacon control register to control the Link LED.
839	 * Note that, in the case of Xena, beacon control register represents
840	 * the gpio control register. In the case of Herc, LED handling is
841	 * done by beacon control register as opposed to gpio control register
842	 * in Xena.
843	 */
844	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
845	                  &bar0->beacon_control);
846	val64 ^= XGE_HAL_GPIO_CTRL_GPIO_0;
847	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
848	               &bar0->beacon_control);
849}
850
851/**
852 * xge_hal_read_eeprom - Read 4 bytes of data from user given offset.
853 * @devh: HAL device handle.
854 * @off: offset at which the data must be written
855 * @data: output parameter where the data is stored.
856 *
857 * Read 4 bytes of data from the user given offset and return the
858 * read data.
859 * Note: will allow to read only part of the EEPROM visible through the
860 * I2C bus.
861 * Returns: -1 on failure, 0 on success.
862 */
863xge_hal_status_e
864xge_hal_read_eeprom(xge_hal_device_h devh, int off, u32* data)
865{
866	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
867	xge_hal_status_e ret = XGE_HAL_FAIL;
868	u32 exit_cnt = 0;
869	u64 val64;
870	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
871
872	val64 = XGE_HAL_I2C_CONTROL_DEV_ID(XGE_DEV_ID) |
873	    XGE_HAL_I2C_CONTROL_ADDR(off) |
874	    XGE_HAL_I2C_CONTROL_BYTE_CNT(0x3) |
875	    XGE_HAL_I2C_CONTROL_READ | XGE_HAL_I2C_CONTROL_CNTL_START;
876
877	__hal_serial_mem_write64(hldev, val64, &bar0->i2c_control);
878
879	while (exit_cnt < 5) {
880	    val64 = __hal_serial_mem_read64(hldev, &bar0->i2c_control);
881	    if (XGE_HAL_I2C_CONTROL_CNTL_END(val64)) {
882	        *data = XGE_HAL_I2C_CONTROL_GET_DATA(val64);
883	        ret = XGE_HAL_OK;
884	        break;
885	    }
886	    exit_cnt++;
887	}
888
889	return ret;
890}
891
892/*
893 * xge_hal_write_eeprom - actually writes the relevant part of the data
894 value.
895 * @devh: HAL device handle.
896 * @off: offset at which the data must be written
897 * @data : The data that is to be written
898 * @cnt : Number of bytes of the data that are actually to be written into
899 * the Eeprom. (max of 3)
900 *
901 * Actually writes the relevant part of the data value into the Eeprom
902 * through the I2C bus.
903 * Return value:
904 * 0 on success, -1 on failure.
905 */
906
907xge_hal_status_e
908xge_hal_write_eeprom(xge_hal_device_h devh, int off, u32 data, int cnt)
909{
910	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
911	xge_hal_status_e ret = XGE_HAL_FAIL;
912	u32 exit_cnt = 0;
913	u64 val64;
914	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
915
916	val64 = XGE_HAL_I2C_CONTROL_DEV_ID(XGE_DEV_ID) |
917	    XGE_HAL_I2C_CONTROL_ADDR(off) |
918	    XGE_HAL_I2C_CONTROL_BYTE_CNT(cnt) |
919	    XGE_HAL_I2C_CONTROL_SET_DATA(data) |
920	    XGE_HAL_I2C_CONTROL_CNTL_START;
921	__hal_serial_mem_write64(hldev, val64, &bar0->i2c_control);
922
923	while (exit_cnt < 5) {
924	    val64 = __hal_serial_mem_read64(hldev, &bar0->i2c_control);
925	    if (XGE_HAL_I2C_CONTROL_CNTL_END(val64)) {
926	        if (!(val64 & XGE_HAL_I2C_CONTROL_NACK))
927	            ret = XGE_HAL_OK;
928	        break;
929	    }
930	    exit_cnt++;
931	}
932
933	return ret;
934}
935
936/*
937 * xge_hal_register_test - reads and writes into all clock domains.
938 * @hldev : private member of the device structure.
939 * xge_nic structure.
940 * @data : variable that returns the result of each of the test conducted b
941 * by the driver.
942 *
943 * Read and write into all clock domains. The NIC has 3 clock domains,
944 * see that registers in all the three regions are accessible.
945 * Return value:
946 * 0 on success.
947 */
948xge_hal_status_e
949xge_hal_register_test(xge_hal_device_h devh, u64 *data)
950{
951	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
952	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
953	u64 val64 = 0;
954	int fail = 0;
955
956	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
957	        &bar0->pif_rd_swapper_fb);
958	if (val64 != 0x123456789abcdefULL) {
959	    fail = 1;
960	    xge_debug_osdep(XGE_TRACE, "Read Test level 1 fails");
961	}
962
963	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
964	        &bar0->rmac_pause_cfg);
965	if (val64 != 0xc000ffff00000000ULL) {
966	    fail = 1;
967	    xge_debug_osdep(XGE_TRACE, "Read Test level 2 fails");
968	}
969
970	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
971	        &bar0->rx_queue_cfg);
972	if (val64 != 0x0808080808080808ULL) {
973	    fail = 1;
974	    xge_debug_osdep(XGE_TRACE, "Read Test level 3 fails");
975	}
976
977	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
978	        &bar0->xgxs_efifo_cfg);
979	if (val64 != 0x000000001923141EULL) {
980	    fail = 1;
981	    xge_debug_osdep(XGE_TRACE, "Read Test level 4 fails");
982	}
983
984	val64 = 0x5A5A5A5A5A5A5A5AULL;
985	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
986	        &bar0->xmsi_data);
987	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
988	        &bar0->xmsi_data);
989	if (val64 != 0x5A5A5A5A5A5A5A5AULL) {
990	    fail = 1;
991	    xge_debug_osdep(XGE_ERR, "Write Test level 1 fails");
992	}
993
994	val64 = 0xA5A5A5A5A5A5A5A5ULL;
995	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
996	        &bar0->xmsi_data);
997	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
998	        &bar0->xmsi_data);
999	if (val64 != 0xA5A5A5A5A5A5A5A5ULL) {
1000	    fail = 1;
1001	    xge_debug_osdep(XGE_ERR, "Write Test level 2 fails");
1002	}
1003
1004	*data = fail;
1005	return XGE_HAL_OK;
1006}
1007
1008/*
1009 * xge_hal_rldram_test - offline test for access to the RldRam chip on
1010 the NIC
1011 * @devh: HAL device handle.
1012 * @data: variable that returns the result of each of the test
1013 * conducted by the driver.
1014 *
1015 * This is one of the offline test that tests the read and write
1016 * access to the RldRam chip on the NIC.
1017 * Return value:
1018 * 0 on success.
1019 */
1020xge_hal_status_e
1021xge_hal_rldram_test(xge_hal_device_h devh, u64 *data)
1022{
1023	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1024	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
1025	u64 val64;
1026	int cnt, iteration = 0, test_pass = 0;
1027
1028	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
1029	        &bar0->adapter_control);
1030	val64 &= ~XGE_HAL_ADAPTER_ECC_EN;
1031	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1032	        &bar0->adapter_control);
1033
1034	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
1035	        &bar0->mc_rldram_test_ctrl);
1036	val64 |= XGE_HAL_MC_RLDRAM_TEST_MODE;
1037	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1038	        &bar0->mc_rldram_test_ctrl);
1039
1040	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
1041	        &bar0->mc_rldram_mrs);
1042	val64 |= XGE_HAL_MC_RLDRAM_QUEUE_SIZE_ENABLE;
1043	__hal_serial_mem_write64(hldev, val64, &bar0->i2c_control);
1044
1045	val64 |= XGE_HAL_MC_RLDRAM_MRS_ENABLE;
1046	__hal_serial_mem_write64(hldev, val64, &bar0->i2c_control);
1047
1048	while (iteration < 2) {
1049	    val64 = 0x55555555aaaa0000ULL;
1050	    if (iteration == 1) {
1051	        val64 ^= 0xFFFFFFFFFFFF0000ULL;
1052	    }
1053	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1054	        &bar0->mc_rldram_test_d0);
1055
1056	    val64 = 0xaaaa5a5555550000ULL;
1057	    if (iteration == 1) {
1058	        val64 ^= 0xFFFFFFFFFFFF0000ULL;
1059	    }
1060	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1061	        &bar0->mc_rldram_test_d1);
1062
1063	    val64 = 0x55aaaaaaaa5a0000ULL;
1064	    if (iteration == 1) {
1065	        val64 ^= 0xFFFFFFFFFFFF0000ULL;
1066	    }
1067	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1068	        &bar0->mc_rldram_test_d2);
1069
1070	    val64 = (u64) (0x0000003fffff0000ULL);
1071	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1072	        &bar0->mc_rldram_test_add);
1073
1074
1075	    val64 = XGE_HAL_MC_RLDRAM_TEST_MODE;
1076	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1077	        &bar0->mc_rldram_test_ctrl);
1078
1079	    val64 |=
1080	        XGE_HAL_MC_RLDRAM_TEST_MODE | XGE_HAL_MC_RLDRAM_TEST_WRITE |
1081	        XGE_HAL_MC_RLDRAM_TEST_GO;
1082	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1083	        &bar0->mc_rldram_test_ctrl);
1084
1085	    for (cnt = 0; cnt < 5; cnt++) {
1086	        val64 = xge_os_pio_mem_read64(hldev->pdev,
1087	            hldev->regh0, &bar0->mc_rldram_test_ctrl);
1088	        if (val64 & XGE_HAL_MC_RLDRAM_TEST_DONE)
1089	            break;
1090	        xge_os_mdelay(200);
1091	    }
1092
1093	    if (cnt == 5)
1094	        break;
1095
1096	    val64 = XGE_HAL_MC_RLDRAM_TEST_MODE;
1097	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1098	        &bar0->mc_rldram_test_ctrl);
1099
1100	    val64 |= XGE_HAL_MC_RLDRAM_TEST_MODE |
1101	    XGE_HAL_MC_RLDRAM_TEST_GO;
1102	    xge_os_pio_mem_write64(hldev->pdev, hldev->regh0, val64,
1103	        &bar0->mc_rldram_test_ctrl);
1104
1105	    for (cnt = 0; cnt < 5; cnt++) {
1106	        val64 = xge_os_pio_mem_read64(hldev->pdev,
1107	            hldev->regh0, &bar0->mc_rldram_test_ctrl);
1108	        if (val64 & XGE_HAL_MC_RLDRAM_TEST_DONE)
1109	            break;
1110	        xge_os_mdelay(500);
1111	    }
1112
1113	    if (cnt == 5)
1114	        break;
1115
1116	    val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
1117	        &bar0->mc_rldram_test_ctrl);
1118	    if (val64 & XGE_HAL_MC_RLDRAM_TEST_PASS)
1119	        test_pass = 1;
1120
1121	    iteration++;
1122	}
1123
1124	if (!test_pass)
1125	    *data = 1;
1126	else
1127	    *data = 0;
1128
1129	return XGE_HAL_OK;
1130}
1131
1132/*
1133 * xge_hal_pma_loopback - Enable or disable PMA loopback
1134 * @devh: HAL device handle.
1135 * @enable:Boolean set to 1 to enable and 0 to disable.
1136 *
1137 * Enable or disable PMA loopback.
1138 * Return value:
1139 * 0 on success.
1140 */
1141xge_hal_status_e
1142xge_hal_pma_loopback( xge_hal_device_h devh, int enable )
1143{
1144	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1145	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
1146	u64 val64;
1147	u16 data;
1148
1149	/*
1150	 * This code if for MAC loopbak
1151	 * Should be enabled through another parameter
1152	 */
1153#if 0
1154	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
1155	&bar0->mac_cfg);
1156	if ( enable )
1157	{
1158	    val64 |= ( XGE_HAL_MAC_CFG_TMAC_LOOPBACK | XGE_HAL_MAC_CFG_RMAC_PROM_ENABLE );
1159	}
1160	__hal_pio_mem_write32_upper(hldev->pdev, hldev->regh0,
1161	        (u32)(val64 >> 32), (char*)&bar0->mac_cfg);
1162	xge_os_mdelay(1);
1163#endif
1164
1165	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0)  |
1166	    XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1)   |
1167	    XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)   |
1168	    XGE_HAL_MDIO_CONTROL_MMD_CTRL(0)       |
1169	    XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS);
1170	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1171
1172	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1173	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1174
1175	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0)  |
1176	    XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1)   |
1177	    XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)   |
1178	    XGE_HAL_MDIO_CONTROL_MMD_CTRL(0)       |
1179	    XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ);
1180	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1181
1182	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1183	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1184
1185	val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control);
1186
1187	data = (u16)XGE_HAL_MDIO_CONTROL_MMD_DATA_GET(val64);
1188
1189#define _HAL_LOOPBK_PMA         1
1190
1191	if( enable )
1192	    data |= 1;
1193	else
1194	    data &= 0xfe;
1195
1196	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0)  |
1197	     XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1)   |
1198	     XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)   |
1199	     XGE_HAL_MDIO_CONTROL_MMD_CTRL(0)       |
1200	     XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS);
1201	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1202
1203	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1204	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1205
1206	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0)  |
1207	    XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1)   |
1208	    XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)   |
1209	    XGE_HAL_MDIO_CONTROL_MMD_DATA(data)    |
1210	    XGE_HAL_MDIO_CONTROL_MMD_CTRL(0x0)     |
1211	    XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_WRITE);
1212	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1213
1214	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1215	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1216
1217	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(0)  |
1218	    XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(1)   |
1219	    XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)   |
1220	    XGE_HAL_MDIO_CONTROL_MMD_CTRL(0x0)     |
1221	    XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ);
1222	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1223
1224	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1225	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1226
1227	return XGE_HAL_OK;
1228}
1229
1230u16
1231xge_hal_mdio_read( xge_hal_device_h devh, u32 mmd_type, u64 addr )
1232{
1233	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1234	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
1235	u64 val64 = 0x0;
1236	u16 rval16 = 0x0;
1237	u8  i = 0;
1238
1239	/* address transaction */
1240	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr)  |
1241	    XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type)   |
1242	    XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)   |
1243	    XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS);
1244	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1245
1246	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1247	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1248	do
1249	{
1250	    val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control);
1251	    if (i++ > 10)
1252	    {
1253	        break;
1254	    }
1255	}while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1));
1256
1257	/* Data transaction */
1258	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr)  |
1259	    XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type)   |
1260	    XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)   |
1261	    XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_READ);
1262	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1263
1264	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1265	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1266
1267	i = 0;
1268
1269	do
1270	{
1271	    val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control);
1272	    if (i++ > 10)
1273	    {
1274	        break;
1275	    }
1276	}while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1));
1277
1278	rval16 = (u16)XGE_HAL_MDIO_CONTROL_MMD_DATA_GET(val64);
1279
1280	return rval16;
1281}
1282
1283xge_hal_status_e
1284xge_hal_mdio_write( xge_hal_device_h devh, u32 mmd_type, u64 addr, u32 value )
1285{
1286	u64 val64 = 0x0;
1287	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1288	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
1289	u8  i = 0;
1290	/* address transaction */
1291
1292	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr)  |
1293	    XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type)   |
1294	    XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)   |
1295	    XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_ADDRESS);
1296	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1297
1298	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1299	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1300
1301	do
1302	{
1303	    val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control);
1304	    if (i++ > 10)
1305	    {
1306	        break;
1307	    }
1308	} while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) !=
1309	    XGE_HAL_MDIO_CONTROL_MMD_CTRL(1));
1310
1311	/* Data transaction */
1312
1313	val64 = 0x0;
1314
1315	val64 = XGE_HAL_MDIO_CONTROL_MMD_INDX_ADDR(addr)    |
1316	    XGE_HAL_MDIO_CONTROL_MMD_DEV_ADDR(mmd_type) |
1317	    XGE_HAL_MDIO_CONTROL_MMD_PRT_ADDR(0)        |
1318	    XGE_HAL_MDIO_CONTROL_MMD_DATA(value)        |
1319	    XGE_HAL_MDIO_CONTROL_MMD_OP(XGE_HAL_MDIO_OP_WRITE);
1320	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1321
1322	val64 |= XGE_HAL_MDIO_CONTROL_MMD_CTRL(XGE_HAL_MDIO_CTRL_START);
1323	__hal_serial_mem_write64(hldev, val64, &bar0->mdio_control);
1324
1325	i = 0;
1326
1327	do
1328	{
1329	    val64 = __hal_serial_mem_read64(hldev, &bar0->mdio_control);
1330	    if (i++ > 10)
1331	    {
1332	        break;
1333	    }
1334	}while((val64 & XGE_HAL_MDIO_CONTROL_MMD_CTRL(0xF)) != XGE_HAL_MDIO_CONTROL_MMD_CTRL(1));
1335
1336	return XGE_HAL_OK;
1337}
1338
1339/*
1340 * xge_hal_eeprom_test - to verify that EEprom in the xena can be
1341 programmed.
1342 * @devh: HAL device handle.
1343 * @data:variable that returns the result of each of the test conducted by
1344 * the driver.
1345 *
1346 * Verify that EEPROM in the xena can be programmed using I2C_CONTROL
1347 * register.
1348 * Return value:
1349 * 0 on success.
1350 */
1351xge_hal_status_e
1352xge_hal_eeprom_test(xge_hal_device_h devh, u64 *data)
1353{
1354	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1355	int fail     = 0;
1356	u32 ret_data = 0;
1357
1358	/* Test Write Error at offset 0 */
1359	if (!xge_hal_write_eeprom(hldev, 0, 0, 3))
1360	    fail = 1;
1361
1362	/* Test Write at offset 4f0 */
1363	if (xge_hal_write_eeprom(hldev, 0x4F0, 0x01234567, 3))
1364	    fail = 1;
1365	if (xge_hal_read_eeprom(hldev, 0x4F0, &ret_data))
1366	    fail = 1;
1367
1368	if (ret_data != 0x01234567)
1369	    fail = 1;
1370
1371	/* Reset the EEPROM data go FFFF */
1372	(void) xge_hal_write_eeprom(hldev, 0x4F0, 0xFFFFFFFF, 3);
1373
1374	/* Test Write Request Error at offset 0x7c */
1375	if (!xge_hal_write_eeprom(hldev, 0x07C, 0, 3))
1376	    fail = 1;
1377
1378	/* Test Write Request at offset 0x7fc */
1379	if (xge_hal_write_eeprom(hldev, 0x7FC, 0x01234567, 3))
1380	    fail = 1;
1381	if (xge_hal_read_eeprom(hldev, 0x7FC, &ret_data))
1382	    fail = 1;
1383
1384	if (ret_data != 0x01234567)
1385	    fail = 1;
1386
1387	/* Reset the EEPROM data go FFFF */
1388	(void) xge_hal_write_eeprom(hldev, 0x7FC, 0xFFFFFFFF, 3);
1389
1390	/* Test Write Error at offset 0x80 */
1391	if (!xge_hal_write_eeprom(hldev, 0x080, 0, 3))
1392	    fail = 1;
1393
1394	/* Test Write Error at offset 0xfc */
1395	if (!xge_hal_write_eeprom(hldev, 0x0FC, 0, 3))
1396	    fail = 1;
1397
1398	/* Test Write Error at offset 0x100 */
1399	if (!xge_hal_write_eeprom(hldev, 0x100, 0, 3))
1400	    fail = 1;
1401
1402	/* Test Write Error at offset 4ec */
1403	if (!xge_hal_write_eeprom(hldev, 0x4EC, 0, 3))
1404	    fail = 1;
1405
1406	*data = fail;
1407	return XGE_HAL_OK;
1408}
1409
1410/*
1411 * xge_hal_bist_test - invokes the MemBist test of the card .
1412 * @devh: HAL device handle.
1413 * xge_nic structure.
1414 * @data:variable that returns the result of each of the test conducted by
1415 * the driver.
1416 *
1417 * This invokes the MemBist test of the card. We give around
1418 * 2 secs time for the Test to complete. If it's still not complete
1419 * within this peiod, we consider that the test failed.
1420 * Return value:
1421 * 0 on success and -1 on failure.
1422 */
1423xge_hal_status_e
1424xge_hal_bist_test(xge_hal_device_h devh, u64 *data)
1425{
1426	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1427	u8 bist = 0;
1428	int cnt = 0;
1429	xge_hal_status_e ret = XGE_HAL_FAIL;
1430
1431	xge_os_pci_read8(hldev->pdev, hldev->cfgh, 0x0f, &bist);
1432	bist |= 0x40;
1433	xge_os_pci_write8(hldev->pdev, hldev->cfgh, 0x0f, bist);
1434
1435	while (cnt < 20) {
1436	    xge_os_pci_read8(hldev->pdev, hldev->cfgh, 0x0f, &bist);
1437	    if (!(bist & 0x40)) {
1438	        *data = (bist & 0x0f);
1439	        ret = XGE_HAL_OK;
1440	        break;
1441	    }
1442	    xge_os_mdelay(100);
1443	    cnt++;
1444	}
1445
1446	return ret;
1447}
1448
1449/*
1450 * xge_hal_link_test - verifies the link state of the nic
1451 * @devh: HAL device handle.
1452 * @data: variable that returns the result of each of the test conducted by
1453 * the driver.
1454 *
1455 * Verify the link state of the NIC and updates the input
1456 * argument 'data' appropriately.
1457 * Return value:
1458 * 0 on success.
1459 */
1460xge_hal_status_e
1461xge_hal_link_test(xge_hal_device_h devh, u64 *data)
1462{
1463	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1464	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
1465	u64 val64;
1466
1467	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
1468	        &bar0->adapter_status);
1469	if (val64 & XGE_HAL_ADAPTER_STATUS_RMAC_LOCAL_FAULT)
1470	    *data = 1;
1471
1472	return XGE_HAL_OK;
1473}
1474
1475
1476/**
1477 * xge_hal_getpause_data -Pause frame frame generation and reception.
1478 * @devh: HAL device handle.
1479 * @tx : A field to return the pause generation capability of the NIC.
1480 * @rx : A field to return the pause reception capability of the NIC.
1481 *
1482 * Returns the Pause frame generation and reception capability of the NIC.
1483 * Return value:
1484 *  void
1485 */
1486void xge_hal_getpause_data(xge_hal_device_h devh, int *tx, int *rx)
1487{
1488	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1489	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
1490	u64 val64;
1491
1492	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
1493	            &bar0->rmac_pause_cfg);
1494	if (val64 & XGE_HAL_RMAC_PAUSE_GEN_EN)
1495	    *tx = 1;
1496	if (val64 & XGE_HAL_RMAC_PAUSE_RCV_EN)
1497	    *rx = 1;
1498}
1499
1500/**
1501 * xge_hal_setpause_data -  set/reset pause frame generation.
1502 * @devh: HAL device handle.
1503 * @tx: A field that indicates the pause generation capability to be
1504 * set on the NIC.
1505 * @rx: A field that indicates the pause reception capability to be
1506 * set on the NIC.
1507 *
1508 * It can be used to set or reset Pause frame generation or reception
1509 * support of the NIC.
1510 * Return value:
1511 * int, returns 0 on Success
1512 */
1513
1514int xge_hal_setpause_data(xge_hal_device_h devh, int tx, int rx)
1515{
1516	xge_hal_device_t *hldev = (xge_hal_device_t*)devh;
1517	xge_hal_pci_bar0_t *bar0 = (xge_hal_pci_bar0_t *)hldev->bar0;
1518	u64 val64;
1519
1520	val64 = xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
1521	                &bar0->rmac_pause_cfg);
1522	if (tx)
1523	    val64 |= XGE_HAL_RMAC_PAUSE_GEN_EN;
1524	else
1525	    val64 &= ~XGE_HAL_RMAC_PAUSE_GEN_EN;
1526	if (rx)
1527	    val64 |= XGE_HAL_RMAC_PAUSE_RCV_EN;
1528	else
1529	    val64 &= ~XGE_HAL_RMAC_PAUSE_RCV_EN;
1530	xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
1531	             val64, &bar0->rmac_pause_cfg);
1532	return 0;
1533}
1534
1535/**
1536 * xge_hal_read_xfp_current_temp -
1537 * @hldev: HAL device handle.
1538 *
1539 * This routine only gets the temperature for XFP modules. Also, updating of the
1540 * NVRAM can sometimes fail and so the reading we might get may not be uptodate.
1541 */
1542u32 xge_hal_read_xfp_current_temp(xge_hal_device_h hldev)
1543{
1544	u16 val_1, val_2, i = 0;
1545	u32 actual;
1546
1547	/* First update the NVRAM table of XFP. */
1548
1549	(void) xge_hal_mdio_write(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8000, 0x3);
1550
1551
1552	/* Now wait for the transfer to complete */
1553	do
1554	{
1555	    xge_os_mdelay( 50 ); // wait 50 milliseonds
1556
1557	    val_1 =  xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8000);
1558
1559	    if ( i++ > 10 )
1560	    {
1561	        // waited 500 ms which should be plenty of time.
1562	        break;
1563	    }
1564	}while (( val_1 & 0x000C ) != 0x0004);
1565
1566	/* Now NVRAM table of XFP should be updated, so read the temp */
1567	val_1 =  (u8) xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8067);
1568	val_2 =  (u8) xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, 0x8068);
1569
1570	actual = ((val_1 << 8) | val_2);
1571
1572	if (actual >= 32768)
1573	    actual = actual- 65536;
1574	actual =  actual/256;
1575
1576	return actual;
1577}
1578
1579/**
1580 * __hal_chk_xpak_counter -  check the Xpak error count and log the msg.
1581 * @hldev: pointer to xge_hal_device_t structure
1582 * @type:  xpak stats error type
1583 * @value: xpak stats value
1584 *
1585 * It is used to log the error message based on the xpak stats value
1586 * Return value:
1587 * None
1588 */
1589
1590void __hal_chk_xpak_counter(xge_hal_device_t *hldev, int type, u32 value)
1591{
1592	/*
1593	 * If the value is high for three consecutive cylce,
1594	 * log a error message
1595	 */
1596	if(value == 3)
1597	{
1598	    switch(type)
1599	    {
1600	    case 1:
1601	        hldev->stats.sw_dev_err_stats.xpak_counter.
1602	            excess_temp = 0;
1603
1604	        /*
1605	         * Notify the ULD on Excess Xpak temperature alarm msg
1606	         */
1607	        if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) {
1608	            g_xge_hal_driver->uld_callbacks.xpak_alarm_log(
1609	                hldev->upper_layer_info,
1610	                XGE_HAL_XPAK_ALARM_EXCESS_TEMP);
1611	        }
1612	        break;
1613	    case 2:
1614	        hldev->stats.sw_dev_err_stats.xpak_counter.
1615	            excess_bias_current = 0;
1616
1617	        /*
1618	         * Notify the ULD on Excess  xpak bias current alarm msg
1619	         */
1620	        if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) {
1621	            g_xge_hal_driver->uld_callbacks.xpak_alarm_log(
1622	                hldev->upper_layer_info,
1623	                XGE_HAL_XPAK_ALARM_EXCESS_BIAS_CURRENT);
1624	        }
1625	        break;
1626	    case 3:
1627	        hldev->stats.sw_dev_err_stats.xpak_counter.
1628	            excess_laser_output = 0;
1629
1630	        /*
1631	         * Notify the ULD on Excess Xpak Laser o/p power
1632	         * alarm msg
1633	         */
1634	        if (g_xge_hal_driver->uld_callbacks.xpak_alarm_log) {
1635	            g_xge_hal_driver->uld_callbacks.xpak_alarm_log(
1636	                hldev->upper_layer_info,
1637	                XGE_HAL_XPAK_ALARM_EXCESS_LASER_OUTPUT);
1638	        }
1639	        break;
1640	    default:
1641	        xge_debug_osdep(XGE_TRACE, "Incorrect XPAK Alarm "
1642	        "type ");
1643	    }
1644	}
1645
1646}
1647
1648/**
1649 * __hal_updt_stats_xpak -  update the Xpak error count.
1650 * @hldev: pointer to xge_hal_device_t structure
1651 *
1652 * It is used to update the xpak stats value
1653 * Return value:
1654 * None
1655 */
1656void __hal_updt_stats_xpak(xge_hal_device_t *hldev)
1657{
1658	u16 val_1;
1659	u64 addr;
1660
1661	/* Check the communication with the MDIO slave */
1662	addr = 0x0000;
1663	val_1 = 0x0;
1664	val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr);
1665	if((val_1 == 0xFFFF) || (val_1 == 0x0000))
1666	    {
1667	            xge_debug_osdep(XGE_TRACE, "ERR: MDIO slave access failed - "
1668	                      "Returned %x", val_1);
1669	            return;
1670	    }
1671
1672	/* Check for the expected value of 2040 at PMA address 0x0000 */
1673	if(val_1 != 0x2040)
1674	    {
1675	            xge_debug_osdep(XGE_TRACE, "Incorrect value at PMA address 0x0000 - ");
1676	            xge_debug_osdep(XGE_TRACE, "Returned: %llx- Expected: 0x2040",
1677	            (unsigned long long)(unsigned long)val_1);
1678	            return;
1679	    }
1680
1681	/* Loading the DOM register to MDIO register */
1682	    addr = 0xA100;
1683	    (void) xge_hal_mdio_write(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr, 0x0);
1684	    val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr);
1685
1686	/*
1687	 * Reading the Alarm flags
1688	 */
1689	    addr = 0xA070;
1690	    val_1 = 0x0;
1691	    val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr);
1692	if(CHECKBIT(val_1, 0x7))
1693	{
1694	    hldev->stats.sw_dev_err_stats.stats_xpak.
1695	        alarm_transceiver_temp_high++;
1696	    hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp++;
1697	    __hal_chk_xpak_counter(hldev, 0x1,
1698	        hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp);
1699	} else {
1700	    hldev->stats.sw_dev_err_stats.xpak_counter.excess_temp = 0;
1701	}
1702	if(CHECKBIT(val_1, 0x6))
1703	    hldev->stats.sw_dev_err_stats.stats_xpak.
1704	        alarm_transceiver_temp_low++;
1705
1706	if(CHECKBIT(val_1, 0x3))
1707	{
1708	    hldev->stats.sw_dev_err_stats.stats_xpak.
1709	        alarm_laser_bias_current_high++;
1710	    hldev->stats.sw_dev_err_stats.xpak_counter.
1711	        excess_bias_current++;
1712	    __hal_chk_xpak_counter(hldev, 0x2,
1713	        hldev->stats.sw_dev_err_stats.xpak_counter.
1714	        excess_bias_current);
1715	} else {
1716	    hldev->stats.sw_dev_err_stats.xpak_counter.
1717	        excess_bias_current = 0;
1718	}
1719	if(CHECKBIT(val_1, 0x2))
1720	    hldev->stats.sw_dev_err_stats.stats_xpak.
1721	        alarm_laser_bias_current_low++;
1722
1723	if(CHECKBIT(val_1, 0x1))
1724	{
1725	    hldev->stats.sw_dev_err_stats.stats_xpak.
1726	        alarm_laser_output_power_high++;
1727	    hldev->stats.sw_dev_err_stats.xpak_counter.
1728	        excess_laser_output++;
1729	    __hal_chk_xpak_counter(hldev, 0x3,
1730	        hldev->stats.sw_dev_err_stats.xpak_counter.
1731	            excess_laser_output);
1732	} else {
1733	    hldev->stats.sw_dev_err_stats.xpak_counter.
1734	            excess_laser_output = 0;
1735	}
1736	if(CHECKBIT(val_1, 0x0))
1737	    hldev->stats.sw_dev_err_stats.stats_xpak.
1738	            alarm_laser_output_power_low++;
1739
1740	/*
1741	 * Reading the warning flags
1742	 */
1743	    addr = 0xA074;
1744	    val_1 = 0x0;
1745	    val_1 = xge_hal_mdio_read(hldev, XGE_HAL_MDIO_MMD_PMA_DEV_ADDR, addr);
1746	if(CHECKBIT(val_1, 0x7))
1747	    hldev->stats.sw_dev_err_stats.stats_xpak.
1748	        warn_transceiver_temp_high++;
1749	if(CHECKBIT(val_1, 0x6))
1750	    hldev->stats.sw_dev_err_stats.stats_xpak.
1751	        warn_transceiver_temp_low++;
1752	if(CHECKBIT(val_1, 0x3))
1753	    hldev->stats.sw_dev_err_stats.stats_xpak.
1754	        warn_laser_bias_current_high++;
1755	if(CHECKBIT(val_1, 0x2))
1756	    hldev->stats.sw_dev_err_stats.stats_xpak.
1757	        warn_laser_bias_current_low++;
1758	if(CHECKBIT(val_1, 0x1))
1759	    hldev->stats.sw_dev_err_stats.stats_xpak.
1760	        warn_laser_output_power_high++;
1761	if(CHECKBIT(val_1, 0x0))
1762	    hldev->stats.sw_dev_err_stats.stats_xpak.
1763	        warn_laser_output_power_low++;
1764}
1765