ee2836b747bdf45b8d1c849ca74debae85255a08
[dragonfly.git] / sys / dev / atm / hfa / fore_stats.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/dev/hfa/fore_stats.c,v 1.4 1999/08/28 00:41:52 peter Exp $
27  *      @(#) $DragonFly: src/sys/dev/atm/hfa/fore_stats.c,v 1.8 2008/03/01 22:03:13 swildner Exp $
28  */
29
30 /*
31  * FORE Systems 200-Series Adapter Support
32  * ---------------------------------------
33  *
34  * Device statistics routines
35  *
36  */
37
38 #include "fore_include.h"
39
40 /*
41  * Get device statistics from CP
42  * 
43  * This function will issue a GET_STATS command to the CP in order to
44  * initiate the DMA transfer of the CP's statistics structure to the host.
45  * We will then sleep pending command completion.  This must only be called
46  * from the ioctl system call handler.
47  *
48  * Called from a critical section.
49  *
50  * Arguments:
51  *      fup     pointer to device unit structure
52  *
53  * Returns:
54  *      0       stats retrieval successful
55  *      errno   stats retrieval failed - reason indicated
56  *
57  */
58 int
59 fore_get_stats(Fore_unit *fup)
60 {
61         H_cmd_queue     *hcp;
62         Cmd_queue       *cqp;
63         int             sst;
64
65         ATM_DEBUG1("fore_get_stats: fup=%p\n", fup);
66
67         /*
68          * Make sure device has been initialized
69          */
70         if ((fup->fu_flags & CUF_INITED) == 0) {
71                 return (EIO);
72         }
73
74         /*
75          * If someone has already initiated a stats request, we'll
76          * just wait for that one to complete
77          */
78         crit_enter();
79         if (fup->fu_flags & FUF_STATCMD) {
80
81                 sst = tsleep((caddr_t)&fup->fu_stats, PCATCH, "fore", 0);
82                 crit_exit();
83                 return (sst ? sst : fup->fu_stats_ret);
84         }
85
86         /*
87          * Limit stats gathering to once a second or so
88          */
89         if (time_second == fup->fu_stats_time) {
90                 crit_exit();
91                 return (0);
92         } else
93                 fup->fu_stats_time = time_second;
94
95         /*
96          * Queue command at end of command queue
97          */
98         hcp = fup->fu_cmd_tail;
99         if ((*hcp->hcq_status) & QSTAT_FREE) {
100                 void    *dma;
101
102                 /*
103                  * Queue entry available, so set our view of things up
104                  */
105                 hcp->hcq_code = CMD_GET_STATS;
106                 hcp->hcq_arg = NULL;
107                 fup->fu_cmd_tail = hcp->hcq_next;
108
109                 /*
110                  * Now set the CP-resident queue entry - the CP will grab
111                  * the command when the op-code is set.
112                  */
113                 cqp = hcp->hcq_cpelem;
114                 (*hcp->hcq_status) = QSTAT_PENDING;
115
116                 dma = DMA_GET_ADDR(fup->fu_stats, sizeof(Fore_cp_stats),
117                         FORE_STATS_ALIGN, 0);
118                 if (dma == NULL) {
119                         fup->fu_stats->st_drv.drv_cm_nodma++;
120                         crit_exit();
121                         return (EIO);
122                 }
123                 fup->fu_statsd = dma;
124                 cqp->cmdq_stats.stats_buffer = (CP_dma) CP_WRITE(dma);
125
126                 fup->fu_flags |= FUF_STATCMD;
127                 cqp->cmdq_stats.stats_cmd = 
128                         CP_WRITE(CMD_GET_STATS | CMD_INTR_REQ);
129
130                 /*
131                  * Now wait for command to finish
132                  */
133                 sst = tsleep((caddr_t)&fup->fu_stats, PCATCH, "fore", 0);
134                 crit_exit();
135                 return (sst ? sst : fup->fu_stats_ret);
136
137         } else {
138                 /*
139                  * Command queue full
140                  */
141                 fup->fu_stats->st_drv.drv_cm_full++;
142                 crit_exit();
143                 return (EIO);
144         }
145 }
146